? ? 我所在的項目在公司本身是以組件化開發(fā)著稱,而我本身負責項目的組件集成,所以書中很多的觀點可以說深有體會(本想說不謀而合的,哈哈)。
組件的定義
? ? 作者認為組件是軟件的部署單元,是整個軟件系統在部署過程中可以獨立完成部署的最小實體。比如,對于Java應用程序而言,Jar包就是組件;Ruby中的組件則是Gem文件;Python中的Egg或Wheel文件以及.Net下的DLL文件。
? ? 當然,這里的jar包應該是把依賴的其它jar包等打包到自己的jar中(比如通過maven的maven-shade-plugin來實現),這樣出來的jar包就是獨立可部署的單元了。在實際的大項目中,每個jar包都只會打包自己的類,不會去包含依賴的jar包,否則底層jar包就會被多處包含,造成軟件體積變大。單體程序如此,微服務架構也有類似的問題,雖然微服務的容器運行體積不會變大,但是我們在操作的時候會把公共的SDK打包為一個基礎鏡像,供上層組件制作應用鏡像的時候進行依賴。所以一個jar包常常不能獨立部署,甚至我們常規(guī)定義的組件也不能獨立部署,而是提供一個獨立的功能。
好的組件要求是高內聚,底耦合,那么組件的聚合與耦合該遵循什么原則呢?
組件聚合
作者就組件聚合,也就是哪些類應該被組合到一個組件,提出了三個原則:
REP(復用/發(fā)布等同原則):軟件復用的最小粒度應該等同于其發(fā)布的最小粒度。
CCP(共同閉包原則):將會同時修改,并且為相同目的而修改的類放到同一個組件;不會同時修改,并且目的不同的類放到不同的組件
CRP(共同復用原則):不要強迫一個組件的用戶依賴他們不需要的東西
精華匯聚成如下的組件聚合張力圖,與CAP定理(指的是在一個分布式系統中,Consistency(一致性)、 Availability(可用性)、Partition tolerance(分區(qū)容錯性),三者不可兼得)差不多,一個系統中,無法完全兼顧三個原則,關注某兩個原則越多,對第三個原則損失也就越多。

? ? 我當前所在項目明顯是更多注重REP和CCP,犧牲了CRP原則,這樣造成的一個后果就是,我們會有一個較為龐大的基礎組件,但應用組件達到了最小化。當這個基礎組件不如預料那樣穩(wěn)定,而會頻繁修改,就會造成所有應用組件都會需要重新編譯、驗證。當還頻繁出現不兼容變更,影響就會更大些了,也就出現張力圖最上面的“太多不必要的發(fā)布”的問題,這對我們持續(xù)集成的要求就非常高了。
組件耦合
? ? 組件之間不可避免會出現依賴關系,依賴關系不同組件之間集合為一個大系統的必備條件。
? ? 我負責的上一個項目,使用ant構建,很多組件耦合在一起進行編譯,當某個組件依賴另一個組件編譯的時候,直接采用拷貝或寫死依賴路徑的方法。這樣每個組件完全沒法獨立編譯,開發(fā)人員本地編譯,通常需要對整個軟件進行全量編譯,完成后才可以對自己的代碼進行修改編譯。開發(fā)人員通常不會及時更新別的組件代碼,也不會經常進行全量編譯,造成明明本地編譯可以通過的代碼,項目集成全量編譯還是經常編譯不過。
? ? 后來為了進行組件化編譯,引用ant+ivy的方式進行依賴解耦,花了很大代價才完成改造,使得組件獨立構建成為可能。
? ? 所以依賴本身不能說好或者不好,作者在這里也提出了三個原則:
ADP(Acyclic Dependencies Principle 無依賴環(huán)原則):組件依賴關系圖中不應該出現循環(huán)。
當前我們項目采用maven構建,nexus倉庫進行制品管理,倉庫的緩存造成同版本出現依賴循環(huán)也無法及時發(fā)現,這個在當前構建中需要通過切換版本號才會暴露出問題,而切版本一般都是臨近版本發(fā)布集成時間點,這樣經常會阻塞集成,且沒有一個好的方法來提前發(fā)現。
SDP(Stable Dependencies Principle 穩(wěn)定依賴原則):依賴關系必須要指定更穩(wěn)定的方向。
該原則的核心就是被依賴多的,如我們常說的SDK,基礎組件,需要更多的保持穩(wěn)定性。作者提出一個穩(wěn)定性指標:出向依賴(Fan-out)/(出向依賴(Fan-out)+入向依賴(Fan-int)),極端情況,Fan-out為0,即該組件完全不依賴其它組件,說明這個組件的穩(wěn)定性指標高,反之,Fan-int為0,即完全沒有組件依賴自己,那么組件穩(wěn)定性指標差。
SAP(Stable Abstractions Principle 穩(wěn)定抽象原則):一個組件的抽象化程度應該與其穩(wěn)定性保持一致
這里是對第二點指標的補充,也就是說,并不是說組件穩(wěn)定性指標差就是不好,相反,穩(wěn)定性指標差的組件,有更多的修改是可以接受的,反而穩(wěn)定性指標高的組件,被頻繁修改,反而是不可接受的,這會造成一系列依賴組件的修改。
