一、耦合
耦合度是從模塊外部考察模塊的獨立性,用來衡量模塊間的相互聯繫。
主要考察:
- 模塊相關聯的代碼和數據量,
- 模塊間調用的方式
- 耦合的類型;
模塊間耦合類型 | 含義 |
---|---|
獨立耦合 | 無直接聯繫,僅共有上層模塊 |
數據耦合 | 彼此交換數據(參數、返回值) |
控制耦合 | 通過參數控制執行邏輯分支 |
公共耦合 | 全局變量,公共數據/緩存 |
內容耦合 | 模塊存在多入口(功能不單一)和非正常訪問 |
低耦合建議:禁用內容耦合,限制公共耦合,少用控制耦合,推薦數據耦合
二、內聚
內聚是從功能角度來度量模塊內的聯繫,它描述的是模塊內的功能聯繫。
模塊內聚程度 | 含義 |
---|---|
偶然內聚 | 僅爲節省空間才把相同代碼挪到一個模塊 |
邏輯內聚 | 相似的功能組成一個新的模塊 |
時間內聚 | 相同時間執行的功能組成一個模塊 |
過程內聚 | 模塊內的功能有執行時間順序要求【中】 |
順序內聚 | 內部功能之間彼此有邏輯依賴(輸出->輸入)【中】 |
通信內聚 | 模塊內功能依賴共同的數據【中】 |
信息內聚 | 模塊內的多個功能基於同一數據結構,每項功能有唯一入口 |
功能內聚 | 內部所有僅爲實現某單一功能,無其他任何冗餘 |
高內聚建議:遵循單一職責原則。
三、SOLID’原則
原則 | 含義 | 備註 |
---|---|---|
單一職責(SRP) | 一個類只負責一種功能 | 除非功能改變否則不予修改 |
開放封閉(OCP) | 對拓展開放,對修改關閉 | 降低加入新的邏輯分支的門檻 |
里氏替換(LSP) | 只有子類實例能夠替換所有超類實例時,纔是IS-A關係 | 否則用組合 |
接口分離(ISP) | 使用多個專門的接口,而非單一的總接口 | 不能強迫用戶去依賴那些他們不使用的接口 |
依賴倒置(DIP) | 上層模塊不依賴下層模塊,二者都應依賴抽象 | 抽象不依賴實現,實現應依賴抽象 |
最小知識(LKP) | 最少知識原則,一個軟件單元應當對其他軟件單元有儘可能少的瞭解 | 迪米特法則:門面模式,中介者模式 |
四、類圖中的依賴關係
類圖反映各軟件單元的組織結構和設計思路。
OOP中,類之間的關係如下:
類型 | 關係名 |
---|---|
IS-A | 泛化(繼承),實現 |
HAS-A | 關聯,聚合,組合 |
USE-A | 依賴 |
各關係的耦合程度:
下面是具體描述:
依賴(Dependence)
在類A中使用到了另外一個類B,這種使用時臨時的、偶然的,代碼表現爲方法參數、局部變量、返回值,靜態方法調用。設計中不應該有雙向依賴。
關聯(Association)
類A使用了類B,其中B是A的成員變量,但B在邏輯上並非類A的組成部分。
具體關係可劃分爲:單向關聯,雙向關聯,自身關聯。
聚合(Aggregation)
類A聚合類B,但類B在某種問題域下可以獨立存在。
A可以不知道B的生命週期。
組合(Composition)
類A組合類B,但類B在某種問題域下不可以獨立存在。
A必須知道B的生命週期。(要麼A負責生成和釋放B、或者B在生成和釋放的時候通知A)
泛化(Generalization)
表現爲一個類繼承自另一個類(或者一個接口繼承另一個接口)。
實現(Implementation)
表現爲一個類實現一個或多個接口。
最後,
一張圖表示類之間的依賴關係:
五、流程圖
流程圖從宏觀上描述運行過程。
六、時序圖
時序圖反映調用關係。
七、狀態圖
狀態圖反映一個軟件單元的動態行爲。
八、思維導圖
開發可以用思維導圖來描述對需求的理解。
以上便是筆者日常文檔中常用的圖。
所謂:文不如表,表不如圖。
恰當地使用圖表來描述,不僅可以更好地理解代碼,甚至可以在畫圖的過程中找到一些難以察覺的BUG。