原文:https://herbertograca.com/2017/07/05/software-architecture-premises/
這篇文章是軟件架構(gòu)編年史(譯)的一部分闲询,這部編年史由一系列關(guān)于軟件架構(gòu)的文章組成寻行。在這一系列文章中掌测,我將寫下我對軟件架構(gòu)的學(xué)習(xí)和思考欣舵,以及我是如何運用這些知識的费奸。如果你閱讀了這個系列中之前的文章召耘,本篇文章的的內(nèi)容將更有意義般渡。
在這篇文章中国章,我將總結(jié)一些關(guān)于軟件架構(gòu)的最基本的概念具钥,了解它們才能更好地理解后續(xù)的文章。
沒有銀彈
無論你如何理解我在軟件架構(gòu)編年史(譯)中談到的內(nèi)容液兽,首先要理解的是沒有銀彈骂删,沒有“普適性”的解決方案。盡可能地了解不同的方法四啰,理解每一種方法的優(yōu)劣宁玫,和它們解決的特定技術(shù)問題。
然后柑晒,當(dāng)接受新的挑戰(zhàn)時欧瘪,先從理解業(yè)務(wù)和最終用戶的需求開始。在搞清楚這些需求之后匙赞,你才能思考應(yīng)該采用哪些架構(gòu)風(fēng)格和模式來更好地解決這些問題佛掖。
最后妖碉,自己做出選擇,是實現(xiàn)一種已知的解決方案芥被,還是創(chuàng)造適合自己的特定問題的獨特設(shè)計欧宜。
有些架構(gòu)風(fēng)格號稱是所有形式的軟件的“銀彈”。然而拴魄,優(yōu)秀的設(shè)計這應(yīng)該選擇最符合解決特定問題需要的風(fēng)格冗茸。——Roy Fielding, 2000 [1]
術(shù)語
在軟件開發(fā)的世界中使用的術(shù)語很多都模棱兩可匹中,因此夏漱,我必須澄清一些我使用的術(shù)語的含義,然后繼續(xù)职员。
功能性(Functional)
在應(yīng)用中純粹發(fā)揮技術(shù)作用的代碼片段麻蹋、方法、類焊切、類的組合扮授。它們和(業(yè)務(wù))領(lǐng)域無關(guān),僅僅代表應(yīng)用中的一種技術(shù)能力专肪。例如:
- 層次(Layer)
- 工廠(Factory)
- 資源庫(Repository)
- 值對象(Value Object)
- 視圖(View)
- 視圖模型(ViewModel)
概念性(Conceptual)
在應(yīng)用中標(biāo)識一個(業(yè)務(wù))領(lǐng)域概念的代碼片段刹勃、方法、類嚎尤、類的組合荔仁。它們和領(lǐng)域相關(guān),代表應(yīng)用中的一種業(yè)務(wù)能力芽死。例如:
- 用戶
- 產(chǎn)品
- 庫存管理
- 產(chǎn)品變體
- 結(jié)帳
- 銷售
這種劃分并不是說一個代碼單元不能同時具備兩種能力(功能性和概念性)乏梁。例如,“Money”對象可以表示一個領(lǐng)域概念关贵,同時也被設(shè)計成一個值對象遇骑。如果我把它當(dāng)成領(lǐng)域概念,我指的就是領(lǐng)域內(nèi)的金錢概念揖曾,但如果我涉及的是這個類中的功能性方面時落萎,我指的就是值對象的技術(shù)特性(沒有ID、可以是不變的等等)炭剪。
包(Package)
劃分在一起的類組成的集合练链,理想情況下遵循一組規(guī)則進(jìn)行劃分。
模塊(Module)
我使用Software Architecture in Practice[7]給出的定義奴拦,模塊就是一個功能性包媒鼓,它體現(xiàn)了應(yīng)用中的一種技術(shù)能力。它是解耦的并且能夠被其他的實現(xiàn)替換。我的理解是绿鸣,模塊即存在與較低的粒度級別瓷产,比如,“安全模塊”或者“ORM”枚驻,也可以存在于像客戶端和服務(wù)器這樣的應(yīng)用塊。模塊提供的是功能性內(nèi)聚株旷。
組件(Component)
我使用Software Architecture in Practice[7]給出的定義再登,作者將組件定義為一個代表業(yè)務(wù)能力的概念性包。理想情況下晾剖,它也是和其他組件和模塊解耦的锉矢。例如“用戶”、“產(chǎn)品”或“結(jié)帳”齿尽。
然而沽损,最重要的是要記住,理想情況下循头,它代表了一個限界上下文(Bounded Context)绵估。組件提供了概念性內(nèi)聚。
應(yīng)用(Application)
我將面向用戶的代碼即 UI 視為應(yīng)用卡骂,它建立在組件之上国裳。例如,我們可以基于一組組件構(gòu)建網(wǎng)絡(luò)商店全跨。不管怎樣缝左,這個網(wǎng)絡(luò)商店會提供一個(店面) UI 讓用戶瀏覽和購買商品和另一個(管理) UI 讓商店管理員管理商品、庫存浓若、支付供應(yīng)商渺杉,等等。這是在同樣的業(yè)務(wù)組件之上構(gòu)建的兩個獨立的應(yīng)用挪钓。
系統(tǒng)(System)
我認(rèn)為系統(tǒng)是一組以某種方式在一起工作是越,為各種企業(yè)必需品提供功能,形成一個企業(yè)范圍內(nèi)的系統(tǒng)诵原,即企業(yè)應(yīng)用英妓。這些應(yīng)用可能構(gòu)建在相同或不同的組件上。在之前網(wǎng)絡(luò)商店的例子中绍赛,系統(tǒng)就是作為一個整體的網(wǎng)絡(luò)商店蔓纠,包括兩個基于同樣業(yè)務(wù)組件構(gòu)建的兩個應(yīng)用(店面和管理),還有其他像支付供應(yīng)商或貨運供應(yīng)商這樣的第三方應(yīng)用吗蚌。
架構(gòu)(Architecture)
軟件架構(gòu)的簡單定義有很多腿倚,我覺得都不錯,但我認(rèn)為理解它是什么很簡單蚯妇,而更重要的是敷燎,定義架構(gòu)的產(chǎn)出暂筝,它應(yīng)該給項目帶來什么。
軟件架構(gòu)[…]是系統(tǒng)需要考慮的一組結(jié)構(gòu)硬贯,它們包括軟件元素和它們之間的關(guān)系焕襟,以及這些元素和關(guān)系的屬性》贡—— Clements et al, 2010 [6]
下面是我考慮架構(gòu)的方面:
- 橫跨所有特性開發(fā)的技術(shù)決策鸵赖,例如拄衰,框架、代碼標(biāo)準(zhǔn)茫打、文檔老赤、流程诗越,...嚷狞;
- 這是存在于項目中的一組很難在后期改變的技術(shù)決策 [3]床未;
- 它是系統(tǒng)的全景圖[5]:pp.2薇搁,粗略的描繪啃洋,結(jié)構(gòu)屎鳍,組件及其關(guān)系[4] [6];
- 它使項目做好變化的準(zhǔn)備[5]:pp.30逮壁,常常是將決策推遲到最后允許的時刻[5]:pp.32;
- 它讓項目做好重用組件和模塊的準(zhǔn)備[7]:pp.29–35卖宠;
- 它制定出結(jié)果的一致性標(biāo)準(zhǔn)并建立輕量的流程,比如編碼規(guī)范筷畦、開發(fā)階段刺洒、持續(xù)交付和持續(xù)部署作媚;
- 它不是某一個人的職責(zé)纸泡,而是由來自項目中不同特性團(tuán)隊的開發(fā)者組成的行會的職責(zé)女揭。
如果你不熟悉行會的概念吧兔,可以觀看下面關(guān)于Spotify 工程師文化的視頻:
架構(gòu)師(Architect)
他是由行會討論和決定的架構(gòu)的發(fā)起人和守護(hù)者。他是部門/團(tuán)隊中經(jīng)驗最豐富的開發(fā)者之一箍土,恰好承擔(dān)著分析高層次問題和解決方案的額外職責(zé)罐监。在做出架構(gòu)決策時弓柱,他還擁有“質(zhì)量票”(He also benefits from a “quality vote” when making an architectural decision.)沟堡。
可是矢空,有一點值得注意航罗,所有開發(fā)者某種程度上都是架構(gòu)師妇多,因為他們都要了解架構(gòu)伤哺,他們都會議某種形式參與架構(gòu),他們都適當(dāng)?shù)爻袚?dān)著維護(hù)架構(gòu)的職責(zé)立莉。
象牙塔架構(gòu)師(Ivory Tower Architect)
有一種架構(gòu)師會做出和架構(gòu)有關(guān)的所有決定绢彤,這種萬能的象牙塔架構(gòu)師是一種架構(gòu)師的反模式蜓耻。他對其他干系人對架構(gòu)的貢獻(xiàn)既不開放茫舶,也不輕易接收饶氏,而是閹割了這些貢獻(xiàn)。
Smells of a bad Architecture (and bad code) [8]
僵化(Rigidity)
如果軟件難以修改是因為修改會導(dǎo)致更多關(guān)聯(lián)修改喊崖,軟件就是僵化的。它就會變成兔子洞:當(dāng)我們以為修改快要完成時,突然發(fā)現(xiàn)還有更多的代碼需要修改节仿,把我們拉進(jìn)無止盡的輪回之中。
脆弱(Fragility)
脆弱的軟件在修改時掉蔬,總會出現(xiàn)意料之外的廊宪、毫無關(guān)聯(lián)的、無法預(yù)測的錯誤女轿。
牢固(Immobility)
如果設(shè)計包含一些可以在其它系統(tǒng)中使用的部分挤忙,但將這些部分從原系統(tǒng)中分離出來需要大量工作甚至帶來許多風(fēng)險,我們就說設(shè)計是牢固的谈喳。
粘滯(Viscosity)
在一個粘滯的系統(tǒng)中册烈,要做對困難重重,要做錯卻輕而易舉婿禽。這意味著通過正常開發(fā)實現(xiàn)變更不如用非常手段來得容易赏僧。
如果執(zhí)行單元測試和/或編譯需要耗費很長時間,開發(fā)很可能導(dǎo)跳過這些過程扭倾,不跑任何自動化測試就實現(xiàn)非常規(guī)的修改淀零,這就是系統(tǒng)范圍的粘滯。
不必要的重復(fù)(Needless repetition)
當(dāng)時間不夠或經(jīng)驗不足導(dǎo)致必要的抽象缺失時膛壹,就會產(chǎn)生不必要的重復(fù)驾中。這些代碼也許并不是直接復(fù)制粘貼造成的重復(fù)唉堪,而是由在不同地方重復(fù)定義的相同業(yè)務(wù)規(guī)則帶來的。
晦澀(Opacity)
代碼寫得混亂肩民,難以理解唠亚,我們需要深人方法實現(xiàn)的細(xì)節(jié)才能搞清楚代碼要干什么。
不必要的復(fù)雜(Needless complexity)
開發(fā)者采用了多種不同的抽象和未來潛在變化的應(yīng)對措施持痰,來積極地避免其他六種壞味道灶搜。良好的軟件設(shè)計是輕量靈活的,理解起來更容易工窍,最重要的是修改更容易割卖,因此不必預(yù)判所有未來的潛在變化。
引用來源
[1] 2000 – Roy Fielding – Architectural Styles and the Design of Network-based Software Architectures
[2] 2000 – Robert C. Martin – Design Principles and Design Patterns
[3] 2006 – Booch, in [5 pg.2]
[4] 2007 – IEEE1471 in [5 pg.2]
[5] 2010 – James Coplien, Gertrud Bjornvig – Lean Architecture
[6] 2010 – Paul Clements, Felix Bachmann, Len Bass – Documenting Software Architectures
[7] 2012 – Len Bass, Paul Clements, Rick Kazman – Software Architecture in Practice
[8] 2014 – M. H. Jongerius – THE SEVEN DESIGN SMELLS OF ROTTING SOFTWARE
[9] 2017* – Wikipedia – Software Architecture