最近review公司的程式碼,發現程式碼耦合程度特別高,修改一處,不知不覺就把其他地方影響到了,這就讓我思考該如何讓我們寫的程式碼足夠內聚,減少耦合呢?
"高內聚、鬆耦合"是一個非常重要的設計思想,能夠有效地提高程式碼的可讀性和可維護性,縮小功能改動導致的程式碼改動範圍。它可以用來指導不同粒度程式碼的設計與開發,比如系統、模組、類,甚至是函數,也可以應用到不同的開發場景中,比如微服務、框架、元件、類庫等。本文我們來探討下如何讓我們的應用做到高內聚、低耦合。
歡迎關注個人公眾號『JAVA旭陽』交流溝通
首先我們將目光投射到內聚上,通常我們的程式碼的內聚歸為7類,如下圖所示,內聚性從高到低。
將相同功能放到一個類或者模組中,內聚程度最高。
如果一個功能的輸出是另外一個功能的輸入,這種存在順序依賴關係的,我們將他們歸到一個模組中叫做順序內聚。
如果功能點使用相同輸入或輸出資料,我們將他們內聚到一個模組中,叫做通訊內聚。
如果不同的功能是由同一個控制流支配的,我們稱作過程內聚。
不同的功能在同一時間段內執行,比如銀行不同的跑批任務,由時間去控制是否放在同一個模組中的內聚叫做時間內聚。
不同的功能可能他們內部的邏輯是一致的,我們將他歸在一起叫做邏輯內聚。
而偶然內聚是指不同的功能,沒什麼關聯就直接放在一起了。這種情況很常見,比如A團隊同時承擔了支付、物流、產品等功能的開發,為了節省開發資源,他們就把不相干的功能放到一個模組中,那麼這種偶然內聚會隨著業務發展遇到各種問題。
上面講解了內聚的可能7種分類,大家不用太較真,瞭解一下就行。
小結一下,我們所說的高內聚,其實是用來指導類或者模組本身的設計,簡單來說,就是指相近的功能應該放到同一個類中,不相近的功能不要放到同一個類中。相近的功能往往會被同時修改,放到同一個類中,修改會比較集中,程式碼容易維護。
現在我們聚焦到耦合上,耦合實際上關注在類與類之間或者模組與模組之間依賴關係的設計,我們通常有下面7種型別的耦合關係。
兩個模組之間沒有直接關係,模組獨立性最強
兩個模組之間用引數傳遞關聯,模組之間影響最小的耦合關係。比如訂單系統輸入物流編號ID,物流系統返回你具體的物流資訊。
兩個模組依賴同樣的一個資料結構,傳遞的是資料結構。
比如租房費用計算系統,需要計算水費和電費,如果你傳使用者資訊這個資料結構,讓水費和電費系統領取使用者物件的用水量和用電量,這就是標記耦合。更好的做法應該只需要傳必要的用水量和用電量,而不是傳輸整個使用者物件。
兩個模組之間傳輸控制資訊,比如某個標誌或者開關,呼叫模組需要知道被呼叫模組的內部邏輯,增加了相互依賴和理解的複雜度。
一組模組需要與外部環境關聯,這組模組存取同一全域性變數,外部耦合有時候必不可少,但應儘量減少此類模組數量。
一組模組均存取同一全域性資料區,這種情況叫做公共耦合。比如有一個公共變數,不同模組都去修改它。
一個模組直接操作或修改另外一個模組的內部書,一個模組不通過正常入口存取另外一個模組,這就是內容耦合,是最糟糕的情況,需要避免。比如直接呼叫另外一個類的set方法,所以這就要求我們不要無腦的把類的任何屬性都加上set方法。
上面大致分享了耦合的7種情況,你們專案屬於哪種情況呢?
這邊再總結一下, 所謂低耦合是說,在程式碼中,類與類之間的依賴關係簡單清晰。即使兩個類有依賴關係,一個類的程式碼改動不會或者很少導致依賴類的程式碼改動。
前面講解了內聚和耦合的多種情況,那麼高內聚、低耦合之間有什麼關係呢?
上圖中左邊部分的程式碼設計中,類的粒度比較小,每個類的職責都比較單一。相近的功能都放到了一個類中,不相近的功能被分割到了多個類中。這樣類更加獨立,程式碼的內聚性更好。一個類的修改,只會影響到一個依賴類的程式碼改動。我們只需要測試這一個依賴類是否還能正常工作就行了。
上圖中右邊部分的程式碼設計中,類粒度比較大,低內聚,功能大而全,不相近的功能放到了一個類中。這就導致很多其他類都依賴這個類。當我們修改這個類的某一個功能程式碼的時候,會影響依賴它的多個類。我們需要測試這三個依賴類,是否還能正常工作。
所以說, 「高內聚」有助於「鬆耦合」,同理,「低內聚」也會導致「緊耦合」 。
關於如何做到模組或者類的高內聚、低耦合,有一個很經典的指導法則,那就是迪米特法則。
迪米特法則是說不該有直接依賴關係的類之間,不要有依賴;有依賴關係的類之間,儘量只依賴必要的介面。換更形象點的說,每個模組只和自己的朋友「說話」(talk),不和陌生人「說話」(talk)。
展開來講,我們在做設計的時候特別關注下面的一些要點。
「高內聚、鬆耦合」是一個非常重要的設計思想,能夠有效提高程式碼的可讀性和可維護性,縮小功能改動導致的程式碼改動範圍。「高內聚」用來指導類本身的設計,「鬆耦合」用來指導類與類之間依賴關係的設計。
所謂高內聚,就是指相近的功能應該放到同一個類中,不相近的功能不要放到同一類中。相近的功能往往會被同時修改,放到同一個類中,修改會比較集中。所謂鬆耦合指的是,在程式碼中,類與類之間的依賴關係簡單清晰。即使兩個類有依賴關係,一個類的程式碼改動也不會或者很少導致依賴類的程式碼改動。
所以我們在設計的時候,儘量要多動動腦子,想想這個功能是不是屬於這個模組的呢?他們之間的互動合理嗎?複雜嗎?有沒有更簡單的方式呢?多問自己幾個問題,你做出的設計會越來越優秀。
歡迎關注個人公眾號『JAVA旭陽』交流溝通
本文來自部落格園,作者:JAVA旭陽,轉載請註明原文連結:https://www.cnblogs.com/alvinscript/p/17030224.html