架構(gòu)整潔之道讀書筆記(一)

最近讀了《架構(gòu)整潔之道》(https://u.jd.com/5nzQJQ) 這本書,這是由Bob大叔所寫的一本關(guān)于軟件架構(gòu)的著作。書中開篇指明了軟件架構(gòu)的核心目的是用最小的人力成本來構(gòu)建和維護(hù)整個軟件系統(tǒng)。那么要如何達(dá)到這個目的呢?全書共分為6個部分,就這個問題分別從編程范式、設(shè)計原則和組件構(gòu)建原則等方面進(jìn)行了論述。

第一、二部分 緒論和編程范式

目前業(yè)界所流行的三大編程方式分別是結(jié)構(gòu)化編程,面向?qū)ο缶幊桃约昂瘮?shù)式編程。結(jié)構(gòu)化編程應(yīng)該是最早出現(xiàn)的編程范式,它通過對程序控制權(quán)的直接轉(zhuǎn)移進(jìn)行了限制和規(guī)范(如goto語句等)。而面向?qū)ο缶幊虅t在它的基礎(chǔ)上引入了多態(tài)的概念,來限制用戶對函數(shù)指針的使用。最后第三大范式是函數(shù)式編程,它的核心是通過變量的不變性來實現(xiàn)嚴(yán)格的賦值限制。

其中,結(jié)構(gòu)化編程范式為我們帶來了將龐大的軟件系統(tǒng)功能通過降級拆分的最佳實踐。同時賦予了我們創(chuàng)造可證偽程序單元的能力。從最小的函數(shù)到大的組件的開發(fā)過程,其實就是一個科學(xué)證偽(測試)過程。
眾所周知,面向?qū)ο缶幊陶Z言的三大特性是封裝,繼承和多態(tài)。而這三大特性并不是最本質(zhì)的,畢竟在類似C++這類語言當(dāng)中,也能夠通過編程技巧來實現(xiàn)類似的效果。從軟件架構(gòu)的角度來看,面向?qū)ο缶幊瘫举|(zhì)上是通過多態(tài)的方式來實現(xiàn)代碼控制關(guān)系的轉(zhuǎn)移。我們利用依賴反轉(zhuǎn)等技術(shù),可以很輕易地實現(xiàn)源代碼級別依賴關(guān)系的反轉(zhuǎn),從而更好地將高層組件與底層組件相分離。

函數(shù)式編程引入了不可變性這一個核心概念,從而利用該方式可以避免結(jié)構(gòu)化編程和面向?qū)ο缶幊讨兴龅降母偁?,死鎖以及并發(fā)更新等問題,所以該范式也在處理多線程、分布式的編程領(lǐng)域都有比較大的應(yīng)用。另一方面由于變量的不可變,使得對于狀態(tài)的追溯變得更加容易。這在復(fù)雜的日志事務(wù)系統(tǒng)中都能找到其應(yīng)用場景。

第三部分 設(shè)計原則

好的軟件架構(gòu)基本上要遵循SOLID的設(shè)計原則。那么什么是SOLID原則呢?它其實是Single Responsibility Principle(單一職責(zé)原則)、Open Closed Principle(開閉原則)、Liskov Substitution Principle(里氏替換原則)、Interface Segregation Principle(接口隔離原則)和Dependence Inversion Principle(依賴反轉(zhuǎn)原則)這五個原則的首字母聯(lián)合起來的縮寫形式。這些設(shè)計原則可以用來指導(dǎo)我們?nèi)绾螌?shù)據(jù)和函數(shù)組織成類。

單一職責(zé)原則是要將服務(wù)的不同行為者之間的代碼進(jìn)行切分,從而保證在修改某一個類的時候,不會影響另一個類的行為。為了踐行這個原則,最簡單的方式是將對象中數(shù)據(jù)和行為分離,另一種方法就是將共用的邏輯和其對應(yīng)的函數(shù)放在一起,這樣對于對象來說在內(nèi)部它們是共用的,但是對于外部的對象來說卻是封閉的。
開閉原則強(qiáng)調(diào)的是可擴(kuò)展性,軟件在不需要修改的前提下,就可以輕易的被擴(kuò)展。那么我們應(yīng)該如何實現(xiàn)該原則呢?主要方式是可以將系統(tǒng)劃分為一個個單獨(dú)的組件,并且將這些組件分門別類,根據(jù)它們的依賴關(guān)系,按層級進(jìn)行劃分,同時可以利用依賴反轉(zhuǎn)等編程技巧,使得高階組件不會因為低階組件頻繁修改而受到影響。
在面向?qū)ο缶幊汤锩妫^承通常是實現(xiàn)里氏替換原則的一個有力工具。為了不違反該原則,我們需要做到的是有著相同父類的兩個子類,可以在需要的時候進(jìn)行相互替換,并且系統(tǒng)還能正常工作。在軟件架構(gòu)的設(shè)計中,一旦違背了該原則來建造系統(tǒng)架構(gòu),就不得不添加額外的復(fù)雜的機(jī)制應(yīng)對了。

接口隔離原則是為了避免軟件中對于不需要模塊的依賴而導(dǎo)致不必要的重新編譯和重新部署。所以我們通常采用的方式是將系統(tǒng)的不同的操作隔離成對應(yīng)的接口進(jìn)行解決,這些接口則可以通過組合等方式進(jìn)行協(xié)同工作。
最后一個原則是依賴反轉(zhuǎn)原則,它主要講的是要在源代碼的依賴關(guān)系當(dāng)中多引用抽象類型的具體實現(xiàn),這樣可以保持系統(tǒng)的靈活性。應(yīng)用該原則主要是針對比較穩(wěn)定的抽象層來說的。

第四部分 組件構(gòu)建原則

組件是軟件系統(tǒng)當(dāng)中可以獨(dú)立部署的最小實體。根據(jù)不同的編程語言通常以jar,.dll或者exe等文件形式存在。組件還能以動態(tài)加載的插件形式來獨(dú)立部署。早期系統(tǒng)中,程序的編譯和加載都十分緩慢,所以為了縮短軟件代碼的編譯加載時間,程序員們將功能獨(dú)立的源代碼進(jìn)行單獨(dú)編譯。它們后來就形成了庫函數(shù)。而隨著函數(shù)庫中函數(shù)規(guī)模增加,調(diào)用函數(shù)時,內(nèi)存地址空間的定位就變得比較復(fù)雜。后面又衍生出了可重定位的二進(jìn)制文件和鏈接加載器的技術(shù)。在經(jīng)歷了大約50年的演變之后,組件化的插件式架構(gòu)在系統(tǒng)軟件架構(gòu)當(dāng)中就已經(jīng)變得習(xí)以為常。
了解了組件的概念之后,我們就得知道在軟件中是依據(jù)哪些原則將相關(guān)的代碼進(jìn)行聚合,從而形成一個個組件的。

主要依賴的是以下三大原則:

第1個原則是復(fù)用發(fā)布等同原則,這個原則其實講的就是軟件復(fù)用的最小粒度應(yīng)該等同于其發(fā)布的最小粒度。從程序開發(fā)者的角度來說,這就要求我們保證組件當(dāng)中的模塊代碼都必須是強(qiáng)相關(guān)的,應(yīng)該有一個共同的主題,從而保證在每一次發(fā)布的時候,這些相關(guān)的代碼都可以被同時發(fā)布,還可以共享相同的版本號和發(fā)行文檔。該原則強(qiáng)調(diào)的是組件的可復(fù)用性。

第2個原則就是共同閉包原則,本質(zhì)上和前面所說的單一職責(zé)原則是一致的。該原則強(qiáng)調(diào)一個組件當(dāng)中不應(yīng)該存在多個變更的原因,此時該原則更加強(qiáng)調(diào)的是組件的可維護(hù)性。

第3個原則是共同復(fù)用原則,意思是不要強(qiáng)迫一個組件的用戶依賴他們不需要的東西。

這三大原則之間隨著業(yè)務(wù)的不同,考慮的側(cè)重點也不同,需要同時平衡可復(fù)用性和可維護(hù)性,而且這種平衡關(guān)系本身也會隨著項目的發(fā)展而不斷變化。

組件開發(fā)完成之后,我們需要進(jìn)一步思考的是如何處理組件跟組件之間的關(guān)系,也就是如何將組件進(jìn)行耦合。組件和組件之間通過依賴的方式進(jìn)行組合協(xié)作,那么在此時最容易產(chǎn)生的問題就是循環(huán)依賴。為了避免循環(huán)依賴,我們主要有兩種方式,第一種方式是引入接口的方式進(jìn)行依賴反轉(zhuǎn)。另一種方式是創(chuàng)建一個新的組件,并且讓要解耦的兩個組件都依賴于它。為了系統(tǒng)的穩(wěn)定性,我們通常會希望盡可能依賴比較穩(wěn)定的組件,那么,為了實現(xiàn)這個目標(biāo)可以將穩(wěn)定組件至于底層,而那些頻繁變更的組件位于頂層。我們知道抽象組件通常是非常穩(wěn)定的,因此在必要的時候可以創(chuàng)建一些不包含任何可執(zhí)行代碼的抽象組件。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容