本文轉載自【微信公眾號:碼磚雜役,ID:whatis9527want】
迪米特法則(LoD:Law of Demeter)又叫最少知識原則(LKP:Least Knowledge Principle ),是由Ian Holland於1987年提出來的,指的是一個類/模塊對其他的類/模塊有越少的了解越好。簡言之:talk only to your immediate friends(只跟你最親密的朋友交談),不跟陌生人說話。
高內聚低耦合
軟體設計有一個meta rule:高內聚,低耦合。
內聚是從功能角度來度量模塊內的聯繫緊密度,一個好的內聚模塊應該恰好專注於完成一個事情,緊密相關的功能代碼才應該放置在一起。
耦合是軟體結構中模塊間的關聯複雜度,是依賴關係的度量,當然模塊間的依賴是無法完全避免的,孤立的模塊可能也沒什麼卵用,但軟體工程師應當樹立一個意識:即吾輩應該向簡化依賴關係的方向努力。
在軟體設計中,經常用內聚和耦合作為衡量模塊獨立性的尺度,許多OOD設計原則都是為了幫助達成這2個設計目標,鬆散、複雜的依賴關係是可信、可讀性、可維護性的大敵。
為什麼要降低耦合性?
迪米特法則的初衷就是為了降低耦合。降低模塊間的聯繫度,有利於提升模塊的獨立性,高獨立性的模塊受別的模塊改動的影響小,如果修改一個模塊,很多模塊受影響(比如引起編譯錯誤,或者需要重新構建),則是一件蛋疼的事。
模塊間的耦合強,意味著修改模塊A,所有依賴A的其他模塊,都需要配合修改和重新構建,需要協作的事情總是比可單獨完成的事情更棘手,複雜性是穩定性的大敵。相互block會導致延誤項目進展,好的設計應該追求更高的獨立性,高獨立性意味花在溝通上的成本更低,獨立性跟複雜性幾乎是互斥的,越耦合越複雜。
怎麼降低耦合性?
1. 單一職責讓代碼可讀性更強,可維護性更好,且更容易被復用,單一職責的理念貫穿於軟體設計的各個方面,不僅僅適用於類和函數的設計,也適用於模塊劃分,文件拆分。比如你應該讓一個函數專注於一件事情從而提高它的健壯性和可復用性,比如你不應該設計巨類從而避免讓你為類命名而頭疼,比如你應該讓文件保持簡潔短小,而不是隨意的把不相干的東西塞進來像垃圾一樣堆在一起。單一職責為軟體設計提高良好的指引,大多數STD C API都符合單一職責的原則,從最初的STD C API發展至今已有幾十年,但這些API無論數量還是函數原型都很少變化(只是為了安全加了一些防護,比如strncpy, strcat_s),可見,設計良好的接口才會有強盛的生命力。
2. 設計類的時候,要秉持最少知識原則,這表示應該降低成員的訪問權限,儘量減少接口暴露:考慮私有化成員變量,不需要公開的成員函數不公開。
3. 不需要被其他模塊調用的全局函數,應該添加static修飾從而將它限於模塊內,避免汙染全局空間,維護最小夠用的接口集,最小的接口集往往代表著最小的依賴。
4. 在編寫c文件的時候,要謹慎處理include,僅需include必須的頭文件,遵從頭文件包含自給自足原則(包含必要的頭文件,且只包含必須的頭文件)。包含不必要的頭文件,不僅僅意味著更長的編譯時間(源文件的預處理階段展開會得到更多內容),而且意味著該文件依賴的任何其他文件的修改都會導致它的重新構建。
5. 消息機制是模塊解耦的慣用手段,不僅限於跨進程的消息機制,也包括進程內模塊間的消息機制。模塊A與B要耦合,則可能需要相互包含頭文件,相互識別對方模塊的符號,消息機制提供了另一種思路,可以通過發送消息的方式,去驅動另一個模塊doSomething,也可以通過消息,把模塊內的信息發送給其他模塊。
6. 門面模式(Facede)和中介者模式(Mediator)都是迪米特法則的應用實例,它們都源自生活。門面模式解決的是將一對多轉變為更簡單的一對一,比如開一個公司,原先需要去各個不同的政府部門辦各種證明,改革之後,只有一個部門對外接口,這種好處是顯而易見的,它把複雜性從外部轉移到了模塊內部,政府內部封裝邏輯並暴露單一界面。中介者模式可以用房屋買賣來舉例,它避免房屋買賣雙方直接溝通,中介居中溝通協調,簡化耦合鬆散的關係。門面和中介兩種模式稍微有些不同,門面更多的是一個模塊要call或者use多個其他模塊,是單向的;而中介模式通過引入中介者這個角色,解決了相互call或者use的依賴問題。
不要盲信
迪米特法則不希望模塊或類之間建立直接的聯繫,如果需要也希望通過類似友元的方式來完成,因此它有可能造成大量中介類,這些類之所以存在完全是為了傳遞類之間的相互調用關係,這在一定程度上增加了系統的複雜度。
另外,遵循類之間的迪米特法則會是一個系統的局部設計簡化,因為每一個局部都不會和遠距離的對象有直接的關聯。但是,這也會造成系統的不同模塊之間的通信效率降低,也會使系統的不同模塊之間不容易協調。
迪米特法則是OOD的一個設計指引,如何正確、恰當的使用,取決於你的經驗和悟性,你懂我意思吧?
本文轉載自【微信公眾號:碼磚雜役,ID:whatis9527want】