《架構(gòu)整潔之道》摘記

第1部分:概述

  • 軟件架構(gòu)的終極目標(biāo)時,用最小的人力成本來滿足構(gòu)建和維護(hù)該系統(tǒng)的需求

  • 本書的主題:描述什么是優(yōu)秀的绒北、整潔的軟件架構(gòu)與設(shè)計

  • 兩個價值維度

  • 行為價值:讓機(jī)器按照某種指定方式運轉(zhuǎn)

  • 架構(gòu)價值:軟件系統(tǒng)的靈活性箱硕,即是否容易被修改

  • 如果忽略軟件架構(gòu)的價值蒜魄,系統(tǒng)將會變得越來越難以維護(hù)跋破,終會有一天婉徘,系統(tǒng)將會變得再也無法修改。

第2部分:從基礎(chǔ)構(gòu)建開始:編程范式

結(jié)構(gòu)化編程

  • 結(jié)構(gòu)化編程對程序控制權(quán)的直接轉(zhuǎn)移進(jìn)行了限制和規(guī)范
  • 用順序結(jié)構(gòu)、分支結(jié)構(gòu)钠乏、循環(huán)結(jié)構(gòu)可構(gòu)造出任何程序
  • 結(jié)構(gòu)化編程范式可將模塊遞歸拆分為可推導(dǎo)的單元
  • goto有害,某些用法會導(dǎo)致某個模塊無法被遞歸拆分成更小春塌、可證明的單元

面向?qū)ο缶幊?/h4>
  • 面向?qū)ο缶幊虒?strong>程序控制權(quán)的間接轉(zhuǎn)移進(jìn)行了限制和規(guī)范
  • 面向?qū)ο缶幊叹褪且远鄳B(tài)為手段來對源代碼中的依賴關(guān)系進(jìn)行控制的能力晓避,這種能力讓軟件架構(gòu)師可以構(gòu)建出某種插件式架構(gòu),讓高層策略性組件與底層實現(xiàn)性組件相分離只壳,底層組件可以被編譯成插件俏拱,實現(xiàn)獨立于高層組件的開發(fā)和部署

函數(shù)式編程

  • 函數(shù)式編程對程序中的賦值進(jìn)行了限制和規(guī)范

  • 可變變量導(dǎo)致競爭問題、死鎖問題吼句、并發(fā)更新問題

  • 不可變性方案:

  • 一個架構(gòu)設(shè)計良好的應(yīng)用程序應(yīng)該將狀態(tài)修改的部分和不需要修改狀態(tài)的部分隔離成單獨的組件彰触,然后用合適的機(jī)制來保護(hù)可變量。軟件架構(gòu)師應(yīng)該致力于將大部分處理邏輯都?xì)w于不可變組件中命辖,可變狀態(tài)組件的邏輯應(yīng)該越少越好况毅。

  • 事件溯源:只存儲事務(wù)記錄分蓖,不存儲具體狀態(tài)。當(dāng)需要具體狀態(tài)時尔许,從頭開始計算所有的事務(wù)么鹤。當(dāng)只有CR,沒有UD味廊,自然也就不存在并發(fā)問題蒸甜。

第3部分:設(shè)計原則

SRP:單一職責(zé)原則

  • Single Responsibility Principle
  • There should never be more than one reason for a class to change
  • 單一職責(zé)原則主要討論的是函數(shù)和類之間的關(guān)系--但是它在兩個討論層面上會以不同的形式出現(xiàn)。在組件層面余佛,我們可以將其稱為共同必包原則(Common Closure Principle)柠新,在軟件架構(gòu)層面,它則是用于奠定架構(gòu)邊界的變更軸心(Axis of Change)辉巡。

OCP:開閉原則

  • Open-Closed Principle
  • 設(shè)計良好的計算機(jī)軟件應(yīng)該易于擴(kuò)展恨憎,同時抗拒修改
  • 其主要目標(biāo)是讓系統(tǒng)易于擴(kuò)展,同時限制器每次被修改所影響的范圍郊楣。實現(xiàn)方式是通過將系統(tǒng)劃分為一系列組件憔恳,并且將這些組件間的依賴關(guān)系按層次結(jié)構(gòu)進(jìn)行組織,使得高階組件不會因低階組件被修改而受到影響净蚤。

LSP:里氏替換原則

  • Liskov Substitution Principle
  • 對于每個類型是S的對象o1钥组,都存在一個類型為T的對象o2,能使操作T類型的程序P在用o2替換o1時行為保持不變今瀑,我們就可以將S稱為T的子類型程梦。
  • 正方形/長方形問題:正方形不是長方形的子類,它們具有不同的修改邊長的邏輯

ISP:接口隔離原則

  • Interface Segregation Principle
  • 避免不必要的依賴
  • image.png

DIP:依賴反轉(zhuǎn)原則

  • Dependency Inversion Principle

  • 具體的編碼守則

  • 應(yīng)在代碼中多使用抽象接口橘荠,盡量避免使用那些多變的具體實現(xiàn)類

  • 不要在具體實現(xiàn)類上創(chuàng)建衍生類

  • 不要覆蓋包含具體實現(xiàn)的函數(shù)

  • 應(yīng)避免在代碼中寫入與任何具體實現(xiàn)相關(guān)的名字作烟,或者是其他容易變動的事物的名字

  • 對易變對象的創(chuàng)建過程做一些處理,通常會選擇用抽象工廠模式來解決源代碼的依賴問題

  • 依賴方向與控制流方向相反

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

組件

  • 組件是軟件的部署單元砾医,是整個軟件系統(tǒng)在部署過程中可以獨立完成部署的最小實體。例如衣厘,對于Java來說如蚜,它的組件是jar文件。

組件聚合

  • 哪些類應(yīng)該被組合成一個組件呢影暴?三個與構(gòu)建組件相關(guān)的基本原則:

  • REP:復(fù)用/發(fā)布等同原則(為復(fù)用性而組合)

  • 軟件復(fù)用的最小粒度應(yīng)等同于其發(fā)布的最小粒度

  • 組件中的類和模塊必須是彼此緊密相關(guān)的

  • CCP:共同閉包原則(為維護(hù)性而組合)

  • 我們應(yīng)該將那些會同時修改错邦,并且為相同目的而修改的類放到同一個組件中,而將不會同時修改型宙,并且不會為了相同目的而修改的那些類放到不同的組件中撬呢。

  • SRP原則在組件層面上的再度闡述,可共同概括為:將由于相同原因而修改妆兑,并且需要同時修改的東西放在一起魂拦;將由于不同原因而修改毛仪,并且不同時修改的東西分開。

  • CRP:共同復(fù)用原則(為避免不必要的發(fā)布而切分)

  • 不要強(qiáng)迫一個組件的用戶依賴他們不需要的東西

  • 和ISP可共同概括為:不要依賴不需要用到的東西

  • 組件聚合張力圖

1659167256317-99501afa-1a04-4447-bda5-32574645287a.png
  • REP和CCP是黏合性原則芯勘, 它們會讓組件變得更大箱靴,而CRP原則是排除性原則, 它會盡量讓組件變小荷愕。
  • 一般來說衡怀,一個軟件項目的重心會從該三角區(qū)域的右側(cè)開始,先期主要犧牲的是復(fù)用性安疗。然后抛杨,隨著項目逐漸成熟,其他項目會逐漸開始對其產(chǎn)生依賴荐类,項目重心就會逐漸向該三角區(qū)域的左側(cè)滑動怖现。換句話說,一個項目在組件結(jié)構(gòu)設(shè)計上的重心是根據(jù)該項目的開發(fā)時間和成熟度不斷變動的掉冶,我們對組件結(jié)構(gòu)的安排主要與項目開發(fā)的進(jìn)度和它被使用的方式有關(guān)真竖,與項目本身功能的關(guān)系其實很小。

組件耦合

  • 三條主要關(guān)注組件之間關(guān)系的原則:

  • ADP:無依賴環(huán)原則

  • 組件依賴關(guān)系圖中不應(yīng)該出現(xiàn)環(huán)

  • 循環(huán)依賴會使得組件的獨立維護(hù)厌小、單元測試和發(fā)布流程變得困難

  • 打破依賴循環(huán)的兩種方式:

  • 應(yīng)用依賴反轉(zhuǎn)原則(DIP)恢共,依賴于接口而不是實現(xiàn)

  • 創(chuàng)建一個新的組件,將現(xiàn)有組件互相依賴的類全部放入新組件

  • SDP:穩(wěn)定依賴原則

  • 依賴關(guān)系必須要指向更穩(wěn)定的方向

  • 任何一個我們預(yù)期會經(jīng)常變更的組件都不應(yīng)該被一個難于修改的組件所依賴璧亚,否則這個多變的組件也將會變得非常難以修改讨韭。(通過遵守穩(wěn)定依賴原則解決)

  • 當(dāng)組件不依賴于任何組件,則不會有任何原因?qū)е滤枰蛔兏Ⅲ覀兎Q它為“獨立”組件

  • 一種計算組件穩(wěn)定性的方式透硝,I指標(biāo):I = Fan-out / (Fan-in + Fan-out)

  • Fan-in: 入向依賴,組件外部類依賴于組件內(nèi)部類的數(shù)量

  • Fan-out: 出向依賴疯搅,組件內(nèi)部類依賴于組件外部類的數(shù)量

  • I 不穩(wěn)定性濒生,指標(biāo)范圍是[0, 1],值越小越穩(wěn)定

  • 每個組件的I指標(biāo)都必須大于其所依賴組件的I指標(biāo)幔欧,即組件結(jié)構(gòu)依賴圖中的I指標(biāo)必須要按其依賴關(guān)系方向遞減罪治。

  • 可使用DIP來解決違反穩(wěn)定依賴原則的組件依賴

  • SAP:穩(wěn)定抽象原則

  • 一個組件的抽象化程度應(yīng)該與其穩(wěn)定性保持一致

  • 該原則要求穩(wěn)定的組件同時應(yīng)該是抽象的,這樣它的穩(wěn)定性就不會影響到擴(kuò)展性礁蔗;另一方面觉义,該原則也要求一個不穩(wěn)定的組件應(yīng)該包含具體的實現(xiàn)代碼,這樣它的不穩(wěn)定性就可以通過具體的代碼被輕易修改浴井。

  • 對組件抽象化程度的一個衡量方式晒骇,A指標(biāo):A = Na / Nc

  • Nc: 組件中類的數(shù)量

  • Na: 組件中抽象類和接口的數(shù)量

  • A:抽象程度

  • 穩(wěn)定程度與抽象化程度的區(qū)間分析

1659187162660-87dba48a-2cea-43f3-bd60-607b1f1b2860.png
  • 痛苦區(qū):非常穩(wěn)定但也非常具體,難以被修改
  • 無用區(qū):抽象但沒有被其他組件依賴
  • 最優(yōu)的位置是主序列線的兩端,實際項目中貼近線即可
  • 衡量一個組件距離最佳位置的指標(biāo)洪囤,D指標(biāo):D=|A+I-1|

第5部分:軟件架構(gòu)

什么是軟件架構(gòu)

  • 軟件架構(gòu)這項工作的實質(zhì)就是規(guī)劃如何將系統(tǒng)切分成組件徒坡,并安排好組件之間的排列關(guān)系,以及組件之間互相通信的方式箍鼓。
  • 設(shè)計軟件架構(gòu)的目的是為了在工作中更好地對這些組件進(jìn)行研發(fā)崭参、部署運行以及運維;最大化程序員的生產(chǎn)力款咖,同時最小化系統(tǒng)的總運營成本何暮。
  • 將軟件的高層策略與其底層實現(xiàn)隔離開
  • 一個優(yōu)秀的軟件架構(gòu)師應(yīng)該致力于最大化可選項數(shù)量

獨立性

  • 康威定律:任何一個組織在設(shè)計系統(tǒng)時,往往都會復(fù)制出一個與該組織內(nèi)部溝通結(jié)構(gòu)相同的系統(tǒng)铐殃。

  • 將系統(tǒng)正確地劃分為一些隔離良好的組件海洼,以便盡可能長時間地為我們的未來保留盡可能多的可選項

  • 通過采用單一職責(zé)原則(SRP)和共同閉包原則(CCP),以及既定的系統(tǒng)設(shè)計意圖來隔離那些變更原因不同的部分富腊,集成變更原因原因相同的部分

  • 按層解耦:UI界面坏逢、應(yīng)用獨有的業(yè)務(wù)邏輯、領(lǐng)域普適的業(yè)務(wù)邏輯赘被、數(shù)據(jù)庫等是整。

  • 用例的解耦:根據(jù)用例進(jìn)行垂直切片(比如添加訂單和刪除訂單)

  • 解耦模式

  • 源碼層次:源代碼模塊之間的依賴;系統(tǒng)所有的組件都會在同一個地址空間內(nèi)執(zhí)行民假,通過簡單的函數(shù)調(diào)用來進(jìn)行彼此的交互浮入;通常叫做單體結(jié)構(gòu)。

  • 部署層次:部署單元(譬如jar文件羊异、DLL事秀、共享庫等)之間的依賴;大部分組件可能還是依然運行在同一個地址空間內(nèi)野舶,通過彼此的函數(shù)調(diào)用通信易迹,部分嗎可能會運行在同一個處理器下的其他進(jìn)程內(nèi);可以產(chǎn)生出許多可獨立部署的單元平道。

  • 服務(wù)層次:通過網(wǎng)絡(luò)數(shù)據(jù)包進(jìn)行通信睹欲;每個執(zhí)行單元在源碼層和二進(jìn)制層都會是一個獨立的個體。

  • 一個設(shè)計良好的架構(gòu)應(yīng)該允許一個系統(tǒng)從單體結(jié)構(gòu)開始一屋,以單一文件的形式部署窘疮,然后逐漸成長為一組相互同理的可部署單元,甚至是獨立的服務(wù)或者微服務(wù)陆淀。最后還能隨著情況的變化,允許系統(tǒng)逐漸回退到單體結(jié)構(gòu)先嬉。

劃分邊界

  • 邊界的作用是將軟件分割成各種元素轧苫,以便約束邊界兩側(cè)之間的依賴關(guān)系
  • 盡可能地推遲細(xì)節(jié)性的決策(采用的框架、數(shù)據(jù)庫、web服務(wù)器含懊、工具庫身冬、依賴注入等),并將這種推遲所產(chǎn)生的影響降低到最低
  • 過早的細(xì)節(jié)性決策會浪費大量人力
  • 邊界線應(yīng)該畫在那些不相關(guān)的事情中間岔乔,比如GUI酥筝、業(yè)務(wù)邏輯、數(shù)據(jù)庫
1659366285458-7c4b6bb2-8459-467c-8a6d-ce6f94b4bd67.png
  • 數(shù)據(jù)庫可以采用多種實現(xiàn)雏门,而業(yè)務(wù)邏輯并不需要關(guān)心這件事嘿歌。這意味著我們可以將與數(shù)據(jù)庫相關(guān)的決策延后,先專注編寫業(yè)務(wù)邏輯的代碼茁影,進(jìn)行測試宙帝,直到不得不選擇數(shù)據(jù)庫為止。
  • 插件式架構(gòu)
  • 為了在軟件架構(gòu)中畫邊界線募闲,我們需要先將系統(tǒng)分割成組件步脓,其中一部分是系統(tǒng)的核心業(yè)務(wù)邏輯組件,而另一部分則是與核心業(yè)務(wù)邏輯無關(guān)但負(fù)責(zé)提供必要功能的插件浩螺。然后通過對源代碼的修改靴患,讓這些非核心組件依賴于系統(tǒng)的核心業(yè)務(wù)邏輯組件。這也是一種對依賴反轉(zhuǎn)原則(DIP)和穩(wěn)定抽象原則(SAP)的具體應(yīng)用要出,依賴箭頭應(yīng)該由底層具體實現(xiàn)細(xì)節(jié)指向高層抽象的方向鸳君。

邊界剖析

  • 邊界形式

  • 單體結(jié)構(gòu):低層客戶端調(diào)用高層服務(wù)函數(shù)

  • 部署層次的組件:動態(tài)鏈接庫

  • 線程?

  • 本地進(jìn)程

  • 服務(wù)

策略和層次

  • 策略:描述計算部分的業(yè)務(wù)邏輯厨幻、描述計算報告的格式相嵌、描述如何校驗輸入數(shù)據(jù)等
  • 層次:一條策略具體系統(tǒng)的輸入/輸出越遠(yuǎn),它所屬的層次就越高
  • 在一個設(shè)計良好的架構(gòu)中况脆,依賴關(guān)系的方向通常取決于它們所關(guān)聯(lián)的組件層次饭宾。一般來說,低層組件被設(shè)計為依賴于高層組件格了。
錯誤:
function encrypt() {
  while(true)
    writeChar(translate(readChar()))
}
高層組件encrypt()依賴于低層組件中的函數(shù)readChar()和writeChar()

正確:
Encrypt類依賴于Char Reader接口和Char Writer接口看铆,由具體類實現(xiàn)接口方法。這樣低層組件(實現(xiàn)類)就變成依賴于高層組件(Encrypt類加兩個接口)

業(yè)務(wù)邏輯

  • 關(guān)鍵業(yè)務(wù)邏輯和關(guān)鍵業(yè)務(wù)數(shù)據(jù)是緊密相關(guān)的盛末,所以它們很適合被放在同一個對象中處理弹惦,這種對象也被叫做“業(yè)務(wù)實體(Entity)”
  • 業(yè)務(wù)實體獨自代表了整個業(yè)務(wù)邏輯,它與數(shù)據(jù)庫悄但、用戶界面棠隐、第三方框架等內(nèi)容無關(guān)
  • 用例更靠近系統(tǒng)的輸入和輸出,屬于低層概念檐嚣;而業(yè)務(wù)實體是一個可以適用于多個應(yīng)用情景的一般化概念助泽,相對地離系統(tǒng)的輸入和輸出更遠(yuǎn)。所以用例依賴于業(yè)務(wù)實體,而業(yè)務(wù)實體并不依賴于用例嗡贺。
  • 不要選擇直接在數(shù)據(jù)結(jié)構(gòu)中使用對業(yè)務(wù)實體對象的引用隐解!這兩個對象存在的意義是非常不一樣的,而且這兩個對象會以不同的原因诫睬、不同的速率發(fā)生變更煞茫。整合在一起是對共同閉包原則(CCP)和單一職責(zé)原則(SRP)的違反。

尖叫的軟件架構(gòu)

  • 軟件的系統(tǒng)架構(gòu)應(yīng)該為該系統(tǒng)的用例提供支持摄凡。 -- 《Object Oriented Software Engineering, A Use Case Driven Approach》
  • 一個良好的架構(gòu)設(shè)計應(yīng)該圍繞著用例來展開续徽,這樣的架構(gòu)設(shè)計可以在脫離框架、工具以及使用環(huán)境的情況下完整地描述用例架谎。
  • 避免讓框架主導(dǎo)我們的架構(gòu)設(shè)計
  • 在不依賴任何框架的情況下針對用例進(jìn)行單元測試炸宵。另外,我們運行測試的時候不應(yīng)該運行web服務(wù)谷扣,也不應(yīng)該需要連接數(shù)據(jù)庫土全。

整潔架構(gòu)

  • 各類架構(gòu)(六邊形架構(gòu)、DCI架構(gòu)会涎、BCE架構(gòu)等)都具有同一個設(shè)計目標(biāo):按照不同關(guān)注點對軟件進(jìn)行切割裹匙。也就是說,這些架構(gòu)都會將軟件切割成不同的層末秃,至少有一層是只包含該軟件的業(yè)務(wù)邏輯的概页,而用戶接口、系統(tǒng)接口則屬于其他層练慕。

  • 按照這些架構(gòu)設(shè)計出來的系統(tǒng)惰匙,通常都具有以下特點:

  • 獨立于框架

  • 可被測試

  • 獨立于UI

  • 獨立于數(shù)據(jù)集

  • 獨立于任何外部機(jī)構(gòu)

  • 將上述所有架構(gòu)的設(shè)計理念綜合稱為一個獨立的理念:

image.png
  • 依賴關(guān)系規(guī)則

  • 通常越靠近中心,其所在的軟件層次就越高铃将∠罟恚基本上,外層圓代表的是機(jī)制劲阎,內(nèi)層圓代表的是策略绘盟。

  • 貫穿整個架構(gòu)設(shè)計的規(guī)則:源碼中的依賴關(guān)系必須只指向同心圓的內(nèi)層,即由低層機(jī)制指向高層策略悯仙。

  • 業(yè)務(wù)實體:封裝了該應(yīng)用中最通用龄毡、最高層的業(yè)務(wù)邏輯,它們應(yīng)該屬于系統(tǒng)中最不容易受外界影響而變動的部分锡垄。

  • 用例:通常包含的是特定應(yīng)用場景下的業(yè)務(wù)邏輯沦零,這里面封裝并實現(xiàn)了整個系統(tǒng)的所有用例。這些用例引導(dǎo)了數(shù)據(jù)在業(yè)務(wù)實體之間的流入/流出货岭,并指揮著業(yè)務(wù)實體利用其中的關(guān)鍵業(yè)務(wù)邏輯來實現(xiàn)用例的設(shè)計目標(biāo)路操。

  • 接口適配器

  • 通常是一組數(shù)據(jù)轉(zhuǎn)換器序攘,它們負(fù)責(zé)將數(shù)據(jù)從對用例和業(yè)務(wù)實體而言最方便操作的格式,轉(zhuǎn)換為外部系統(tǒng)(譬如數(shù)據(jù)庫以及web)和持久層框架最方便操作的格式寻拂。

  • 如果采用的是SQL數(shù)據(jù)庫,那么所有的SQL語句都應(yīng)該被限制在這一層的代碼中丈牢。

  • 這層也會負(fù)責(zé)將來自外部服務(wù)的數(shù)據(jù)轉(zhuǎn)換成系統(tǒng)內(nèi)用例和業(yè)務(wù)實體所需的格式

  • 框架和驅(qū)動程序:最外層的模型層一般是由工具祭钉、數(shù)據(jù)庫、web框架等組成己沛。在這一層中慌核,我們通常只需要編寫一些于內(nèi)層溝通的黏合性代碼。

  • 真正的架構(gòu)可能會超過四層申尼,但是源碼層面的依賴關(guān)系一定要指向同心圓的內(nèi)層垮卓。

  • 通常采用依賴反轉(zhuǎn)原則(DIP)來解決控制流和依賴方向的相反性。

展示器和謙卑對象

  • 謙卑對象模式:將容易測試的行為和難以測試的行為拆分成兩組模塊或類师幕,并將它們隔離粟按。包含難以測試的行為的模塊被稱為謙卑(Humble)組。 (具體可參考 xUnit Test Patterns: Refractoring Test Code)
  • 謙卑組的代碼通常應(yīng)該越簡單越好
  • 強(qiáng)大的可測試性是一個架構(gòu)設(shè)計是否優(yōu)秀的顯著衡量標(biāo)準(zhǔn)之一
  • 因為跨邊界通信肯定需要用到某種簡單的數(shù)據(jù)結(jié)構(gòu)霹粥,而邊界會自然而然地將系統(tǒng)分割成難以測試的部分與容易測試的部分灭将,所以通過在系統(tǒng)的邊界處運用對象模式,我們可以大幅地提高整個系統(tǒng)的可測試性后控。

不完全邊界

  • 為了解決YAGNI原則(You aren't going to need it, 不要預(yù)測未來的需要)和架構(gòu)師工作本身(預(yù)見性設(shè)計)之間的矛盾庙曙,需要引入不完全邊界的概念。

  • 幾種不完全邊界策略浩淘,除此外還有許多其他實現(xiàn)方式捌朴,根據(jù)不同的場景進(jìn)行選擇

  • 方式一:將系統(tǒng)分割成一系列可以獨立編譯、獨立部署的組件之后张抄,再把它們構(gòu)建成一個組件砂蔽。這樣可以省去多組件管理這部分的工作,比如版本號管理和發(fā)布管理等等欣鳖。

  • 方式二:單向邊界察皇。單側(cè)組件提供接口進(jìn)行隔離,而不是采用雙向反向接口泽台。

  • 方式三:門戶模式

  • 架構(gòu)師的職責(zé)之一就是預(yù)判未來哪里有可能需要設(shè)置架構(gòu)邊界什荣,并決定應(yīng)該以完全形式還是不完全形式來實現(xiàn)它們。

層次與邊界

  • 架構(gòu)邊界可以存在于任何地方怀酷,必須要小心審視究竟在什么地方才需要設(shè)計架構(gòu)邊界稻爬。另外,必須弄清楚完全實現(xiàn)這些邊界將會帶來多大的成本蜕依。
  • 權(quán)衡利弊桅锄,反復(fù)進(jìn)行

Main組件

  • Main組件是整個系統(tǒng)中的一個低層模塊琉雳,它處于整潔架構(gòu)的最外圈,主要負(fù)責(zé)為系統(tǒng)加載所有必要的信息友瘤,然后再將控制權(quán)轉(zhuǎn)交回系統(tǒng)的高層組件翠肘。

服務(wù):宏觀與微觀

  • 面向服務(wù)的“架構(gòu)”以及微服務(wù)“架構(gòu)”本身只是一種比函數(shù)調(diào)用方式成本稍高,分割應(yīng)用程序行為的一種形式辫秧,與系統(tǒng)架構(gòu)無關(guān)束倍。

  • 服務(wù)的一些謬論

  • 解耦合的謬論:服務(wù)強(qiáng)耦合于數(shù)據(jù)結(jié)構(gòu)

  • 獨立開發(fā)的謬論:大型系統(tǒng)一樣可以采用單體模式,或者組件模式來構(gòu)建盟戏,不一定非得服務(wù)化绪妹。

  • 系統(tǒng)的架構(gòu)是由系統(tǒng)內(nèi)部的架構(gòu)邊界,以及邊界之間的依賴關(guān)系所定義的柿究,與系統(tǒng)中各組件之間的調(diào)用和通信方式無關(guān)邮旷。

測試邊界

  • 測試代碼也是系統(tǒng)的一部分
  • 測試代碼始終都是向內(nèi)依賴于被測試部分的代碼,而且系統(tǒng)中沒有其他組件依賴于它們蝇摸。
  • 如果測試代碼與系統(tǒng)是強(qiáng)耦合的婶肩,它就得隨著系統(tǒng)變更而變更。修改以嘎通用的系統(tǒng)組件可能會導(dǎo)致成千上百個測試出現(xiàn)問題貌夕,我們通常將這類問題稱為脆弱的測試問題(fragile tests problem)狡孔。
  • 軟件設(shè)計的第一條原則:不要依賴于多變的東西

整潔的嵌入式架構(gòu)

  • 在軟件和固件之間添加硬件抽象層(HAL),使得硬件發(fā)生變化時蜂嗽,軟件代碼仍能使用

第6部分:實現(xiàn)細(xì)節(jié)

數(shù)據(jù)庫只是實現(xiàn)細(xì)節(jié)

  • 數(shù)據(jù)的組織結(jié)構(gòu)苗膝,數(shù)據(jù)的模型,都是系統(tǒng)架構(gòu)中的重要部分植旧,但是從磁盤上存儲/讀取數(shù)據(jù)的機(jī)制和手段卻沒那么重要辱揭。

web是實現(xiàn)細(xì)節(jié)

  • GUI只是一個實現(xiàn)細(xì)節(jié)。而Web則是GUI的一種病附,所以也是一種實現(xiàn)細(xì)節(jié)问窃。作為一名軟件架構(gòu)師,我們需要將這類細(xì)節(jié)與核心業(yè)務(wù)邏輯隔離開來完沪。

應(yīng)用程序框架是實現(xiàn)細(xì)節(jié)

  • 使用框架的風(fēng)險

  • 框架自身的架構(gòu)設(shè)計很多時候并不是特別正確

  • 隨著產(chǎn)品的成熟域庇,功能要求很可能超出框架所能提供的范圍

  • 框架本身可能朝著我們不需要的方向演進(jìn)

  • 未來我們可能會想要切換到一個更新、更好的框架上

  • 框架作為架構(gòu)最外圈的一個實現(xiàn)細(xì)節(jié)來使用覆积,不要讓它們進(jìn)入內(nèi)圈

拾遺

  • 本章由Simon Brown撰寫
  • 四種封裝方式的訪問限制(從左到右分別是按層封裝听皿、按功能封裝、端口和適配器宽档、按組件封裝)尉姨。
1660058599511-81314f11-48a2-4646-ab81-8a72a6e53895.png
  • Simon Brown對組件的定義是

在一個執(zhí)行環(huán)境(應(yīng)用程序)中的、一個干凈吗冤、良好的接口背后的一系列相關(guān)功能的結(jié)合又厉。

與Bob大叔的定義稍有不同

組件是部署單元九府。組件是系統(tǒng)中能夠部署的最小單位,對應(yīng)在java里就是jar文件覆致。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末侄旬,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子煌妈,更是在濱河造成了極大的恐慌勾怒,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件声旺,死亡現(xiàn)場離奇詭異,居然都是意外死亡段只,警方通過查閱死者的電腦和手機(jī)腮猖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來赞枕,“玉大人澈缺,你說我怎么就攤上這事】簧簦” “怎么了姐赡?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長柠掂。 經(jīng)常有香客問我项滑,道長,這世上最難降的妖魔是什么涯贞? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任枪狂,我火速辦了婚禮,結(jié)果婚禮上宋渔,老公的妹妹穿的比我還像新娘州疾。我一直安慰自己,他們只是感情好皇拣,可當(dāng)我...
    茶點故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布严蓖。 她就那樣靜靜地躺著,像睡著了一般氧急。 火紅的嫁衣襯著肌膚如雪颗胡。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天吩坝,我揣著相機(jī)與錄音杭措,去河邊找鬼。 笑死钾恢,一個胖子當(dāng)著我的面吹牛手素,可吹牛的內(nèi)容都是我干的鸳址。 我是一名探鬼主播,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼泉懦,長吁一口氣:“原來是場噩夢啊……” “哼稿黍!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起崩哩,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤巡球,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后酣栈,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡矿筝,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年棚贾,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片妙痹。...
    茶點故事閱讀 38,163評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖怯伊,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情耿芹,我是刑警寧澤,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布媚送,位于F島的核電站,受9級特大地震影響塘偎,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜吟秩,卻給世界環(huán)境...
    茶點故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望绽淘。 院中可真熱鬧涵防,春花似錦、人聲如沸沪铭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至椰憋,卻和暖如春厅克,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背橙依。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工证舟, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人窗骑。 一個月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓女责,卻偏偏與公主長得像,于是被迫代替她去往敵國和親创译。 傳聞我的和親對象是個殘疾皇子抵知,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,925評論 2 344

推薦閱讀更多精彩內(nèi)容

  • 1.設(shè)計與架構(gòu)究竟是什么: 軟件架構(gòu)的終極目標(biāo),用最小的人力成本來滿足構(gòu)建和維護(hù)該系統(tǒng)的需求昔榴。 2.架構(gòu)的兩個價值...
    飛天的龍王閱讀 565評論 0 0
  • 1、程序員的3個層次 1.1碘橘、普通程序員 a互订、編寫代碼:正確處理業(yè)務(wù)流程和數(shù)據(jù)計算;b痘拆、讓代碼跑起來 1.2仰禽、工程...
    wantao123閱讀 664評論 0 6
  • 本文是《架構(gòu)整潔之道》的讀書心得,作者將書中內(nèi)容拆解后再組織纺蛆,不僅加入了個人的獨到見解吐葵,而且用一張詳細(xì)的知識脈絡(luò)圖...
    程序員小2閱讀 198評論 0 1
  • 序 程序員的三個層次(1) 普通程序員編寫代碼,能夠讓程序跑起來的人桥氏。(2) 工程師有“潔癖”温峭、有工匠精神、有修養(yǎng)...
    nimw閱讀 1,650評論 0 3
  • 目錄 程序員的三個層次:普通程序員(會編寫代碼字支,即能讓程序跑起來凤藏,能正確地處理業(yè)務(wù)流程和對數(shù)據(jù)進(jìn)行計算)、工程師(...
    496f92d634c1閱讀 2,422評論 0 1