架構整潔之道

来源:https://www.cnblogs.com/haizai/archive/2019/05/14/10863225.html
-Advertisement-
Play Games

目標 用最少的人力成本滿足構建和維護該系統的需求 目標 衡量指標 版本迭代 -- 工程師團隊規模 版本迭代 -- 代碼總行數 版本迭代 -- 代碼變更行數 衡量指標 軟體系統的價值 行為價值 按需求文檔編寫代碼 可用性 功能性bug 性能 穩定性 緊急,但是並不總是重要,在緊急重要矩陣中占據A、C位 ...


目標

用最少的人力成本滿足構建和維護該系統的需求

衡量指標

版本迭代 -- 工程師團隊規模
版本迭代 -- 代碼總行數
版本迭代 -- 代碼變更行數

軟體系統的價值

行為價值
		按需求文檔編寫代碼
		可用性
				功能性bug
				性能
				穩定性
		緊急,但是並不總是重要,在緊急重要矩陣中占據A、C位置
架構價值
		Soft :當需求變更時,所需的軟體變更必須簡單方便
		變更實施的難道應該和變更的範疇(scope)成等比,而與變更的具體形狀(shape)無關
		不緊急,占據B、D,D的工作就是過度設計,過度設計會提升開發和維護成本

在這裡插入圖片描述

編程範式

目的 :設置限制,告訴我們不可以做什麼
現有範式 :
		結構化編程 :
				目的 :對控制權的直接轉移進行了限制和規範
				內容 :可以用順序介面、分支結構、迴圈結構這三種結構構造出任何結構。限制goto的使用
				意義 :用代碼把一些已證明的結構串聯起來,就可以推導出整個程式的正確性。實際上沒有辦法證明每個程式段是正確的,只能證偽,如果所有的基本單原都無法證偽,那麼整個就是無法證偽的,那目前就是正確的。
				延伸 :物理學與數學的區別,物理學的基本公式都是沒有辦法證明的,只能證偽,所以物理是實驗科學,沒有一個公式是完全靠得住的,只是目前靠得住。數據的基本公式都是可以證明的。
			面向對象編程 :
					目的 :對程式控制權的間接轉移進行了限制和規範
					定義 :
							封裝 :只暴露部分函數,數據則完全不暴露
							繼承
							多態 :其實只是函數指針的一種應用,通過介面和實現,抽象類和繼承,替代了函數指針的使用	
					意義 :函數指針,是跨越組件邊界的方法,是組件獨立部署的基礎,依賴反轉的基礎。依賴反轉指的是讓依賴與控制流向相反。
			函數式編程 :
					目的 :對賦值進行了限制和規範
					趨勢 :如果有足夠大的存儲量和計算量,應用程式可以用事件溯源的方式,用完成不可變的函數式編程,只通過事物記錄,從頭計算狀態
					意義 :所有的競爭問題、死鎖問題、併發問題都是由可變變數導致的。
					應用 :通過將狀態修改的部分和不需要修改的部分分隔成單獨的組件,提高系統的穩定性和效率

設計原則 :SOLID

意義 :
		如何將數據和函數組織成類
		如何將類鏈接起來成為組件和程式
內容 :
		OCP : 開閉原則
				目標 :讓系統易於擴展,同時限制每次修改所影響的範圍
				實現 :劃分組件,並將組件間依賴關係按層次結構進行組織
				本原則是我們進行架構設計的主導原則
		SRP :單一職責原則
				目標 :指導類、組件拆分
				定義 :任何一個軟體模塊,都應該有且只有一個被修改的原因,“被修改的原因”指系統的用戶或所有者
				痛點 :同樣的一塊邏輯,如果服務於兩個價值主體 :因為一個價值主體而修改,那麼第二個價值主體期望的功能將被影響。比如CTO和COO都要員工的工時,分別用於計算薪資和彙報,兩者的計算方式可能目前是相同的,一方有了更改,另一方就bug了
				如果一塊代碼,歸屬於兩個團隊共同維護 :就會有代碼合併問題		
		LSP : 里氏替換原則
				目標 :指導介面與實現方式(邊界處理)
				內容 :不是實現了同一個介面,它們的行為就一致並可以互相替換,長方形正方形是典型的案例
							如果兩個組件,替換之後需要分別做特別的設置,那就說明抽象的還不足夠,會引入許多if-else,可以同配置清單等方式消除
		ISP :介面隔離原則
				目標 :指導介面的定義(邊界處理)
				內容 :不依賴任何不需要的組件、類、方法
							如果不同的用戶分別使用一個大介面的幾個不同的方法,那麼應該把這個大介面拆分為針對這些用戶的小介面
		DIP : 依賴反轉原則
				目標 :指導依賴方向(依賴)
				內容 :組建間跨越邊界的源碼依賴的方向永遠與控制流的方向相反 																						

組件

定義 :是軟體的部署單元,是整個軟體系統可以獨立完成部署的最小實體
拆分三原則 :
		REP :復用、發佈等同原則 -- 內容 :軟體復用的最小粒度應等同於	其發佈的最小粒度
		CCP :共同閉包原則
				內容 :將為了相同目的而同時修改的類放在同一個組件中,是SRP原則在組件層面的描述
				執行 :對大部分應用程式而言,可維護性的重要性遠遠大於可復用性
							因為一個原因需要做修改,這個修改最後在同一個組件中,如果分散在多個組件中,那麼開放、提交、部署的成本都會提升
		CRP :共同復用原則
				內容 :不要強迫一個組件依賴它不需要的東西,是ISP原則在組件層面的描述
		張立圖 :
				架構設計中有許多矛盾,研發性和復用性的矛盾,而研發性本身又有粘性(CCP)和排斥性的矛盾(CRP)
				架構師做的往往是在這個張立圖中找到一個最符合現在需要的點,而這個平衡也是不斷變化的,根據項目的規模、迭代的節奏等。

在這裡插入圖片描述

依賴三原則 :

		無依賴環原則 :
				互相依賴的組件,實際上組成了一個大組件,這三個組件要一起發佈、一起做單元測試
				通過依賴反轉原則可以解依賴環
		穩定依賴原則 :
				內容 :
						依賴必須指向更穩定的方向,介面是最穩定的。
						組件的穩定性,指的是組件的變更空難度,影響因素有很多,比如代碼的體量大小、複雜度、清晰度等,但最最重要的一個因素就是依賴的數量 -- 讓組件難於修改的一個最直接的方法就是讓很多其他組件依賴於它
				定量指標 :不穩定性(|) = 出向依賴數量 / (入向依賴數量 + 出向依賴數量)
				方法 :可以通過抽介面,共同依賴介面的方式,修正違反文檔依賴的地方
		穩定抽象原則 :
				內容 :
						一個組件的抽象化程度應該與其穩定性保持一致
						為了防止高階架構設計與高階策略難以修改,通常抽象出穩定的介面或抽象類。越穩定的庫就應該越抽象,這樣它的穩定性就不會影響它的擴展性
				定量描述 :抽象程度(A) = 組件中抽象類和介面的數量 / 組件中類的數量
				將不穩定性和抽象程度分別作為橫軸和縱軸,畫一個二維的圖,(0,1)-(1,0)連線就是主序列線。靠近(0,0)的區域是痛苦區,改動成本很大,但是又很具體。靠近(1,1)的是無用區,非常抽象,但是沒有別的組件依賴它,改動成本很小,通常是廢棄的。
				離主序列先的距離D = | A + | -1 | ,可以定量化的衡量一個組件的健康程度。在D滿足期望的條件下,約靠近(0,1)和(1,0)越好			

軟體架構

目的 :
		終極目的 :最大化程式員的生產力,最小化系統的總運營成本
		細化目的 :支撐軟體系統的全生命周期,讓系統便於理解、易於修改、方便維護、輕鬆部署			
方針 :	
		選型指的是無關緊要的細節設計
		選型例子 :
				具體選用那個存儲方式,或那個資料庫
						資料庫 :擅長於內容的查詢
						文件 :擅長於文件的快速查找和整體讀取
						如果硬碟被淘汰時,用什麼存儲系統差別不大
				使用哪種web服務
				使用哪種框架 :
						框架的使用文檔是開發者角度寫的,他自然吹噓自己能力,希望你完全耦合他們的框架
						風險 :
								產品發展,框架不再滿足需求
								框架本身朝著我們不需要的方向演進
								未來我們可能希望遷到一個新的更好的框架上
			邊界約完善,開發和部署成本越高,所以不完全邊界能解決的,不要用完全邊界,低層次解耦能解決的,不要用高層次解耦
內容 :
		組件拆分 :
				拆分 :
						水平分層 :
								一條策略距離系統的輸入、輸出越遠,它的層次越高
								例子 :
										UI界面
										應用獨有的業務邏輯
										領域普適的業務邏輯
										存儲
						按用例垂直切分
								每個用例幾乎涉及到所有的水平分層,如何做到新加用例,不影響舊的用例
								比如 :訂單,聊天
						重覆 :
								如果兩段代碼,看起來重覆,但是走的是不同的演進路徑,就不是真正的重覆
				解耦模式 :
						源碼層次 :做了介面、類依賴上的(不完全的)解耦,但是放在同一個組件中,通常放在不同的路徑下
						部署層次 :任然運行在同一個機器上,彼此通過函數調用通訊
						服務層次 :
								運行在不同的機器上,通過url、網路數據包等方式進行通訊
								服務不等同於模塊,比如橫跨型變更需要改動所有服務,但是可能並不會改動架構
						從上到下,(開發、部署)成本依次升高,如果低層次的解耦已經滿足需要,不要	進行高層次的解耦
				組件是一組描述如何將輸入轉化為輸出的策略語句的集合,這些策略的變更原因、時間、層次相同		
		組件排列(依賴):依賴關係與數據流控制流脫鉤,與組件所在層次掛鉤。所以組件的依賴是與組件的水平分層息息相關的
				業務實體 :
						包含關鍵業務數據和業務邏輯
						與界面無關、與存儲無關、與框架無關,只有業務邏輯,沒有別的
				用例 :
						特定場景下的業務邏輯 :
								三要素 :
										需要用戶提供的輸入數據(註意解耦輸入方式,這裡只關心數據)
										用戶應該得到的輸出數據(註意解耦輸出方式,這裡只關心數據)
										從輸入數據到輸出數據,應該採取的處理步驟
								註意 :
										不要把業務實體直接當做輸入數據對象或者輸出數據對象,因為他們會以不同的原因的速率發生變更
				介面適配器 :
						整個MVC
						對存儲、設備、界面等的介面聲明和使用
				框架與驅動程式 :
						因為	與硬體太相關的部分,比如用戶界面,是不可測的,所以這裡的邊界處理通常使用謙卑對象模式
						謙卑對象要有自知之明,簡化到不能再簡化,不應該包含對數據的任何處理。數據處理全部放到介面適配器(比如視圖模型)中。
				測試層 :
						測試也是一個組件
						測試關鍵之外是耦合,測試如何依賴所有的其他組件的所有介面,那測試就是脆弱的,任何改動都引起n個case失效。													
						解法是給測試層單獨寫一套特有的API				
	組件通信 :
			方式 :
					介面調用
					服務調用
			完全邊界 :
					調用雙方都聲明介面
					專用的輸入數據類型
					專用的返回數據類型
			不完全邊界
					省掉最後一步
							保留到源碼層次的解耦
							聲明好介面,做好分割後,任然放在一個組件中。等到時機成熟時再拆出來獨立編譯部署
					單向邊界 :
							正常的切割,應該使用兩個介面,兩個雷各自使用對方的介面而不是直接使用類,但是這樣的開發成本很大,所以,只實現一個介面,高層用介面調用底層,而底層直接使用高層的類
					門戶模式 :
							控制權的間接轉移不用介面和實現去做,而是用門戶類去做,介面都不用聲明瞭。		
	軟體系統的聲明周期 :
			開發 :
					不同團隊負責的組件不交叉
					不使用大量複雜的腳手架
			部署 :
					減少組件數量,內部組件外部組件結合的方式
					不依賴成堆的腳本和配置文件
			運行 :
					這方面的價值對架構的影響最小
					不同吞吐量、不同的響應時長要求,是架構設計要考慮的點。採用微服務?單線程?多線程?
					架構應起到揭示系統運行的作用 :用例、功能、行為設置應該都對開發者可見的一級實體,以類、函數或模塊的形式占據明顯位置,
					命名能清洗地描述對應的功能				
			維護 :
					探秘成本 :
							對現有軟體系統的挖掘,確定新功能或修複問題的最佳位置和方式
					風險成本 :
							做改動時,可能衍生出新的問題

在這裡插入圖片描述


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • ...
  • 1 2 3 4 5 6 前端壓縮上傳圖片 7 8 9 10 11 12 13 121 122 123 ...
  • 廢話不多說,直接上源碼 ...
  • 文章首發: "結構型模式:代理模式" 七大結構型模式之七:代理模式。 簡介 姓名 :代理模式 英文名 :Proxy Pattern 價值觀 :為生活加點料 個人介紹 : Provide a surrogate or placeholder for another object to control ...
  • Spring AOP : Pointcut表達式: designators-指示器 wildcards-通配符 operators-操作符 wildcards: * -- 匹配任意數量的字元 + -- 匹配製定類及其子類 ..-- 一般用於匹配任意數的子包或參數 operator: && || ! ...
  • 工廠模式定義一個用於創建對象的介面,讓子類決定實例化哪一個類,工廠方法使一個類的實例化延遲到其子類。工廠模式主要分為簡單工廠模式、工廠方法模式以及抽象工廠模式。 Obj.m Object1.m Object2.m 簡單工廠模式: SimpleFactory.m 測試代碼: 工廠方法模式: Metho ...
  • saltstack快速入門 saltstack介紹 Salt,一種全新的基礎設施管理方式,部署輕鬆,在幾分鐘內可運行起來,擴展性好,很容易管理上萬台伺服器,速度夠快,伺服器之間秒級通訊 主要功能遠程執行配置管理Stalstack官方文檔 Saltstack原理 Salt使用server-agent通 ...
  • http://www.cnblogs.com/xing901022/p/4034492.html ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...