一文讀懂架構整潔之道
相信大家都非常清楚,文讀如何編寫(xiě)可讀性強的懂架道代碼是一個(gè)合格程序員的必修課。我在之前的構整文章《談?wù)勈裁词呛玫拇a》中談了一些自己對整潔代碼的感悟,代碼并不是文讀獨立存在的,成百上千個(gè)類(lèi)的懂架道系統在企業(yè)應用中非常常見(jiàn),如何將代碼進(jìn)行有效的構整組織,保持高可讀性,文讀高可維護性,懂架道則是構??整一個(gè)好的架構需要考慮的事情。本文從原??則切入,文讀聊聊組件的懂架道分層和解耦,淺談下ヾ(′▽?zhuān)??Bob大叔提出的構整整潔架構,感興(╯°□°)╯趣的文讀同學(xué)也可以發(fā)表下自己的看法。# 原則原則屬于做事情的懂架道指導方針,在討論架構前,構整先來(lái)看看相關(guān)的一些原則。有??適用于代碼層面的原則,有適用于再高一層級——組件的原則。? 代碼原則代碼的原則有SOLID,迪米特法則,組合復用原則等等,我在談?wù)勈裁词呛玫拇a中也(╯°□°)╯列出來(lái)過(guò),關(guān)于這些原則討論的文章非常之??多,大家也比較熟悉,本文主要談架構方面的,這里就??不展開(kāi)了(le)。? 組件原則組件是一組代碼的集 合,拿蓋房子來(lái)打比方,代碼原則指導如何使用磚塊建造ヽ(′ー`)ノ房間,而組件原則指導如何將房間構建成高樓大廈。組件的構建要遵循一些原則,否則即使墻砌的再好,房間修建的再漂亮,不按照規范建造,房子可ヽ(′▽?zhuān)?/(ke)能就歪歪扭扭,整棟樓房的質(zhì)量也堪憂(yōu)。組件原則包括組件內的關(guān)系(組件聚合)(?⊿?)以及組件間的關(guān)系(組件耦合)??。**組件聚(?Д?)合**組??件聚合方面的原則有以下幾個(gè):- REP:復用/發(fā)布等同原??則- CCP:共同閉包原則- CRP:共同復用原則REP是組件聚合總的指導原則,表示組件內的類(lèi)和模塊是彼此緊密相關(guān)的。CCP和CRP是對REP的補充,CCP可以看做是組件級別的單一職責原則(SRP):由于相同原因修改,并且需要同時(shí)修改的東西放一起;不(bu)同原因修改,并且不同時(shí)修改的東西分開(kāi)??。CRP可以看做是組件級別的接口隔離原則(IS(╥_╥)P):不要依賴(lài)不需要的東西??梢钥闯鐾ㄟ^(guò)這三個(gè)原則構建的組件,擁有以下幾個(gè)特點(diǎn):- 組件內的類(lèi)和模塊緊密相關(guān),需求變更時(shí)通常需要同時(shí)(′ω`*)修改;- 需求變更時(shí),需要進(jìn)行的修改只涉及很少的組件甚至在一個(gè)組件內;- 復用這個(gè)組件時(shí),通常組件內的功能均是用戶(hù)需要??的??,而不是有一些不相關(guān)的功能;這里貼下書(shū)(shu)中的張力圖:項目的初期,更多關(guān)注的是維護性而犧牲復用性,隨著(zhù)項目逐漸成熟,項目重心會(huì )逐漸傾向于(′?`)復用(yong)性。**組件耦合**組件耦合方面的原則有以下幾個(gè):- ADP:無(wú)依賴(lài)環(huán)原則- SDP:穩定依賴(lài)原則- SAP:穩定抽象原則組件間ヽ(′▽?zhuān)?ノ的依(′?ω?`)賴(lài)如果存在環(huán),則維護性將大大降低,我們應該避免組件間的循環(huán)依賴(lài)。組件間的依賴(lài)關(guān)系應該是指向更穩定的方向,每個(gè)組件的穩定性 都低于其依賴(lài)的組件穩定性。組件越穩定,則其抽象程度需要更高;組件越不(bu)穩定,則其抽象程度需要更低,越具體。有時(shí)候,可能會(huì )新引入一個(gè)引用,導致一個(gè)穩定的組件依賴(lài)了一個(gè)不穩定的組件,此時(shí)就可以使用依賴(lài)倒置原則(DIP)將依賴(lài)關(guān)系反轉,保持穩定依賴(lài)。# 分層與解耦談了組件相關(guān)的原(yuan)則,現在( ?° ?? ?°)來(lái)談?wù)劷M件間的分層和隔離的方式。通過(guò)有效的分┐(′д`)┌層手段,可以有效隔離不同功能的組件。? 水平???分層得益于??MVC模式的普及,水平分層在我們??的系統中已經(jīng)非常普及了,通常有以下幾層:表現層/UI層:負責系統的界面展示,通常包括Controller和VO等;領(lǐng)域層/業(yè)務(wù)邏輯層:負責處理系統的業(yè)務(wù)邏輯,通常包(//ω//)括Service,Mヽ(′▽?zhuān)?ノanager和DTO等;數據層:負責與DB等底層數據存儲介質(zhì)通信,通常包括Mapper和DO等ヾ(′?`)?;? 垂直分層但是,僅僅做到水平分層是不夠的。當業(yè)務(wù)邏輯比較復雜時(shí),涉及的(de)用例會(huì )非常多,這些用例之間的變更原因幾乎肯定是不同的,所以還要進(jìn)行垂直分層,將變更原因不一樣的用例切分開(kāi)。(°ロ°) !例如,很多系統的修改操作和刪除操作的變更原因和變更頻率是不一樣的,這時(shí)候可以考慮將修改和刪除進(jìn)行解耦。不論是水平分層還是垂直分層,其核心目的都是將更新頻率不同的代碼給分開(kāi),放入不同的組件中。? 解耦方式分層后的解耦方式有多種:- 源碼層次:通過(guò)控制源代碼模塊間的(de)依賴(lài)關(guān)(guan)系進(jìn)行解耦,部署時(shí)仍然一起部署,適用于項目早期(′?_?`)剛起步時(shí)??- 部署層次:通過(guò)控制部署單元(例如jar包等)之間依賴(lài)進(jìn)行解耦,當系統對部署和開(kāi)發(fā)方面(mian)有更高的要求時(shí),部分組件需要獨立出(chu)去形成新的部署單元;- 服務(wù)層次:通(tong)過(guò)(??ヮ?)?*:???將組件的依賴(lài)關(guān)系降低到數據結構級別??,然后通過(guò)服務(wù)進(jìn)行通信來(lái)(′?`)解耦,當系統足夠大??的時(shí)候,就需要服務(wù)層次的解耦了;但需要注意的是,不論通過(guò)哪種解耦方式進(jìn)行代碼的(de)隔離,并不意味ヽ(′▽?zhuān)?ノ著(zhù)這樣就萬(wàn)事大吉,擁有良好可擴展和可維護性了。這也是Bob在《架??構整潔之道》中提到的“橫跨型變更”(雖然作者是在服務(wù)的這一章提出的,但我認為也適用于其他兩種解耦層次)。請看下 面的出租車(chē)調度系統的服務(wù)架構圖圖中可以看出,T???axi UI依賴(lài) Taxi Finder查找符合條件的出租車(chē),依賴(lài)Taxi Selector進(jìn)行出租車(chē)調度。而Taxi Finder通過(guò)多個(gè)Taxi Supplier服務(wù)獲取車(chē)輛信息,Taxi Selector依賴(lài)Taxi Dispatcher進(jìn)行最終的派單。各個(gè)組件??都是服務(wù)化的??梢钥吹?,各個(gè)組件都是具體的類(lèi),雖然各個(gè)組件隔離部署,但其實(shí)??(shi)他們之(′?_?`)間是強耦合的,并沒(méi)有真正的解耦:加入現在出租車(chē)公司準備推出運送貓咪的服務(wù),則所有的組件都需要進(jìn)行更改,同時(shí)有些同學(xué)的更改方式就是在原有的類(lèi)中增加if...else,這顯然是不可取的。正確的做法應該是在組件最初的設計中,就應(ying)該考慮抽象化和多態(tài),如下圖,使用策略模式或┐(′?`)┌者模板方法進(jìn)行解耦:采用面向對象的方法來(lái)處理橫跨型變更注意看(kan)我紅框標出來(lái)的,(′ω`)除了服務(wù)間(′?`)的隔離外,在組件內部其實(shí)也存在隔離,而這個(gè)的隔離??更加重要。這也就是書(shū)中講的:服務(wù)邊界并ヾ(?■_■)ノ不能代表系統的架構邊界,服務(wù)內部的組件邊界才(?????)是。# 架構從代碼和組件原則到組件分層和解耦,( ?ヮ?)我們逐漸對系統底層的一些元素有了比較深入的了解,那么上層的架構到底是什么呢?? 什么是架構并沒(méi)有非常明(ming)確的定義,這里引用書(shū)中的(′_ゝ`)一些描述,大家應該有一些體會(huì ):軟件架構的實(shí)質(zhì)就是規劃如何將系統切分成組件,并安排好組件之間的排列關(guān)系,以及ヽ(′ー`)ノ組件之間互相通信的方式。軟件架構的終極目(′▽?zhuān)?標是,用最小的人力成本滿(mǎn)足構建和維護該系統的需求需要指出的?是,架構和框架并不是相同的東西:- 架構一定是業(yè)務(wù)相關(guān)的,包含了業(yè)務(wù)屬性,并且這個(gè)業(yè)務(wù)屬性是系統的核心價(jià)值;- 框架一般都??是業(yè)務(wù)無(wú)關(guān)的,是我們編碼實(shí)現架構的的工具,屬于實(shí)現細節(jie)。最初設計系統架構時(shí),并不需ヽ(′?`)ノ要過(guò)多考慮使用什么框架,而更多的是關(guān)注自身業(yè)務(wù)。此外,很多人可能對架構有些誤解:設計那么多┐(′?`)┌有什么用,代碼不還照樣得寫(xiě)?是的,代碼還得寫(xiě),架構并不能(neng)讓你不寫(xiě)代碼了(有時(shí)可能還會(huì )讓你多寫(xiě)代碼)。但是,好的架構會(huì )讓寫(xiě)代碼變得更容易了。容易不一定是體現在需要變更的代碼量多少上,好的(′?_?`)架構可??以讓你更快速的找出需要變更的范圍,并且很容易的就修改掉——這對于一個(gè)運行維護了多年的系統尤為重(′_`)要。大家可以回想下這樣的場(chǎng)景是不是很熟悉:明明是一個(gè)看起來(lái)很正常很合理的需求,看起來(lái)變(bian)更范圍也不大,但真的去擼代碼時(shí)發(fā)現需要改的地方好多,甚至無(wú)從下手去改。這(zhe)個(gè)時(shí)候可能就要去看看之前的架構設計是不是不夠合理,有哪些需要優(yōu)化改進(jìn)的??。# 六邊形架構六邊形架構,又名端口適配器架構(我更喜歡這個(gè)名字,因為六邊形老讓人感覺(jué)有(you)六個(gè)什么東西跟它對應),DDD極力推崇該架構。系統的領(lǐng)域模型是系統最為重要的部分,而其他的諸如DB,UI,緩存,消息隊列等等均通過(guò)適配器與領(lǐng)域層進(jìn)行通信,也就是依賴(lài)(′_`)關(guān)系是由外到內的(依賴(lài)倒置(′?`*))。之前在商家規?;\營(yíng)項目中也嘗試過(guò)使用DDD來(lái)進(jìn)??行架構設計。? 整潔架構Bob綜??合六邊形架構和其他幾個(gè)架構的特點(diǎn)提出了整潔架構,它具有以下幾個(gè)特點(diǎn):- 獨立于框架- 可被測試- 獨立于UI- 獨立于數據庫- 獨立于任何外部機構架構最內部是業(yè)務(wù)實(shí)體,??代表了系統關(guān)鍵業(yè)務(wù)邏輯。再外一層是用例——特定應用場(chǎng)景下的業(yè)務(wù)邏輯,在Bob看來(lái),用例是架構設計中非常重要的一環(huán),架構也是基于這些用例進(jìn)行設計的,如??果缺失了用ヾ(′▽?zhuān)??例,就無(wú)從談起架構設計了。緊接著(zhù)是控制(zhi)器,網(wǎng)關(guān)(guan)和展示器,是一層接口適配器。ヾ(?■_■)ノ最外層則是框架和驅動(dòng)程序,這里面包含了數據庫,web,工具等等,這一層一般只包含了(le)一些通信的黏合性代碼。也并不一定只有四層,真實(shí)的情況(╬?益?)可能會(huì )(???)超過(guò)四層,但總的原則不變:外層依賴(lài)內存,最內部是最通用、最高層的策略,最外層是最具體的實(shí)現細節。外層的是底層組件,內層的是高層組件,底層組件作為(′?_?`)高層的插件存在,換句話(huà)說(shuō)外層的這個(gè)組件是可以被其他的組件(jian)像插件一?樣替換掉的。這里需要明確的一點(diǎn)是:有時(shí)候,軟件運行的方向與依賴(lài)的方向是(???)不同的(這個(gè)很多同學(xué)可能會(huì )沒(méi)有注意到)。比如業(yè)務(wù)實(shí)體從數據庫取數據,運行方向是業(yè)務(wù)實(shí)體->數據庫(′_`),而通過(guò)依賴(lài)反轉(DI,業(yè)務(wù)實(shí)體定義查詢(xún)接口,數據庫層實(shí)現),我們的依賴(lài)關(guān)系是業(yè)務(wù)實(shí)體<-數據庫。這里講到的保持底層組件對高層組件的依賴(lài),高層組件的穩定性和抽象性,也就是前面講的SDP和SAP。# 總結本文從代碼和組件的原則講起,講到組件內和組件間的關(guān)系,以及如何進(jìn)行組件的分層和隔離,接著(zhù)引出了架構相關(guān)的討論,列舉了六邊形架構和整潔架構,并談了一些自己的理解。后續會(huì )結合自身做過(guò)的項目,談一談具體的一些架構模式。參考:《架構整潔之道》 Robert C. Martin《領(lǐng)域驅動(dòng)設計》 Eric Evans《企業(yè)應用架構模式》Martin Fowler
亚洲女同成aV人片在线观看|亚洲www啪成人一区二区麻豆|亚洲国产中日韩精品综合|亚洲国产成人精品一级片|亚洲无码在线视频免费
海晏县|
罗江县|
张北县|
尼勒克县|
仪陇县|
金坛市|
临西县|
綦江县|
苏州市|
璧山县|
秦皇岛市|
信阳市|
乐亭县|
瑞金市|
壤塘县|
南皮县|
宁化县|
象州县|
乌兰县|
教育|
定兴县|
襄垣县|
丰镇市|
清苑县|
房山区|
北川|
高雄县|
昌宁县|
蒙山县|
内乡县|
霞浦县|
云霄县|
大连市|
新源县|
江油市|
庆云县|
福建省|
赞皇县|
双桥区|
随州市|
沛县|
http://444
http://444
http://444
http://444
http://444
http://444