架構整潔之道讀書筆記(一) 第一、二部分 緒論和編程範式 第三部分 設計原則 第四部分 組件構建原則

最近讀了《架構整潔之道》(https://u.jd.com/5nzQJQ) 這本書,這是由Bob大叔所寫的一本關於軟件架構的著作。書中開篇指明瞭軟件架構的核心目的是用最小的人力成本來構建和維護整個軟件系統。那麼要如何達到這個目的呢?全書共分爲6個部分,就這個問題分別從編程範式、設計原則和組件構建原則等方面進行了論述。

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

目前業界所流行的三大編程方式分別是結構化編程,面向對象編程以及函數式編程。結構化編程應該是最早出現的編程範式,它通過對程序控制權的直接轉移進行了限制和規範(如goto語句等)。而面向對象編程則在它的基礎上引入了多態的概念,來限制用戶對函數指針的使用。最後第三大範式是函數式編程,它的核心是通過變量的不變性來實現嚴格的賦值限制。

其中,結構化編程範式爲我們帶來了將龐大的軟件系統功能通過降級拆分的最佳實踐。同時賦予了我們創造可證僞程序單元的能力。從最小的函數到大的組件的開發過程,其實就是一個科學證僞(測試)過程。
衆所周知,面向對象編程語言的三大特性是封裝,繼承和多態。而這三大特性並不是最本質的,畢竟在類似C++這類語言當中,也能夠通過編程技巧來實現類似的效果。從軟件架構的角度來看,面向對象編程本質上是通過多態的方式來實現代碼控制關係的轉移。我們利用依賴反轉等技術,可以很輕易地實現源代碼級別依賴關係的反轉,從而更好地將高層組件與底層組件相分離。

函數式編程引入了不可變性這一個核心概念,從而利用該方式可以避免結構化編程和麪向對象編程中所遇到的競爭,死鎖以及併發更新等問題,所以該範式也在處理多線程、分佈式的編程領域都有比較大的應用。另一方面由於變量的不可變,使得對於狀態的追溯變得更加容易。這在複雜的日誌事務系統中都能找到其應用場景。

第三部分 設計原則

好的軟件架構基本上要遵循SOLID的設計原則。那麼什麼是SOLID原則呢?它其實是Single Responsibility Principle(單一職責原則)、Open Closed Principle(開閉原則)、Liskov Substitution Principle(里氏替換原則)、Interface Segregation Principle(接口隔離原則)和Dependence Inversion Principle(依賴反轉原則)這五個原則的首字母聯合起來的縮寫形式。這些設計原則可以用來指導我們如何將數據和函數組織成類。

單一職責原則是要將服務的不同行爲者之間的代碼進行切分,從而保證在修改某一個類的時候,不會影響另一個類的行爲。爲了踐行這個原則,最簡單的方式是將對象中數據和行爲分離,另一種方法就是將共用的邏輯和其對應的函數放在一起,這樣對於對象來說在內部它們是共用的,但是對於外部的對象來說卻是封閉的。
開閉原則強調的是可擴展性,軟件在不需要修改的前提下,就可以輕易的被擴展。那麼我們應該如何實現該原則呢?主要方式是可以將系統劃分爲一個個單獨的組件,並且將這些組件分門別類,根據它們的依賴關係,按層級進行劃分,同時可以利用依賴反轉等編程技巧,使得高階組件不會因爲低階組件頻繁修改而受到影響。
在面向對象編程裏面,繼承通常是實現里氏替換原則的一個有力工具。爲了不違反該原則,我們需要做到的是有着相同父類的兩個子類,可以在需要的時候進行相互替換,並且系統還能正常工作。在軟件架構的設計中,一旦違背了該原則來建造系統架構,就不得不添加額外的複雜的機制應對了。

接口隔離原則是爲了避免軟件中對於不需要模塊的依賴而導致不必要的重新編譯和重新部署。所以我們通常採用的方式是將系統的不同的操作隔離成對應的接口進行解決,這些接口則可以通過組合等方式進行協同工作。
最後一個原則是依賴反轉原則,它主要講的是要在源代碼的依賴關係當中多引用抽象類型的具體實現,這樣可以保持系統的靈活性。應用該原則主要是針對比較穩定的抽象層來說的。

第四部分 組件構建原則

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

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

第1個原則是複用發佈等同原則,這個原則其實講的就是軟件複用的最小粒度應該等同於其發佈的最小粒度。從程序開發者的角度來說,這就要求我們保證組件當中的模塊代碼都必須是強相關的,應該有一個共同的主題,從而保證在每一次發佈的時候,這些相關的代碼都可以被同時發佈,還可以共享相同的版本號和發行文檔。該原則強調的是組件的可複用性。

第2個原則就是共同閉包原則,本質上和前面所說的單一職責原則是一致的。該原則強調一個組件當中不應該存在多個變更的原因,此時該原則更加強調的是組件的可維護性。

第3個原則是共同複用原則,意思是不要強迫一個組件的用戶依賴他們不需要的東西。

這三大原則之間隨着業務的不同,考慮的側重點也不同,需要同時平衡可複用性和可維護性,而且這種平衡關係本身也會隨着項目的發展而不斷變化。

組件開發完成之後,我們需要進一步思考的是如何處理組件跟組件之間的關係,也就是如何將組件進行耦合。組件和組件之間通過依賴的方式進行組合協作,那麼在此時最容易產生的問題就是循環依賴。爲了避免循環依賴,我們主要有兩種方式,第一種方式是引入接口的方式進行依賴反轉。另一種方式是創建一個新的組件,並且讓要解耦的兩個組件都依賴於它。爲了系統的穩定性,我們通常會希望儘可能依賴比較穩定的組件,那麼,爲了實現這個目標可以將穩定組件至於底層,而那些頻繁變更的組件位於頂層。我們知道抽象組件通常是非常穩定的,因此在必要的時候可以創建一些不包含任何可執行代碼的抽象組件。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章