偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

軟件架構(gòu)編年史:包和命名空間

開發(fā) 架構(gòu)
一個(gè)系統(tǒng)的架構(gòu)是它的高層級(jí)的視圖,是系統(tǒng)的大局觀,是粗線條的系統(tǒng)設(shè)計(jì)。架構(gòu)的決策就是系統(tǒng)結(jié)構(gòu)上的決策,這些決策影響著全部代碼,決定了系統(tǒng)中其它部分的基礎(chǔ)。

[[397015]]

本文轉(zhuǎn)載自微信公眾號(hào)「逸言」,作者覃宇 。轉(zhuǎn)載本文請(qǐng)聯(lián)系逸言公眾號(hào)。  

 一個(gè)系統(tǒng)的架構(gòu)是它的高層級(jí)的視圖,是系統(tǒng)的大局觀,是粗線條的系統(tǒng)設(shè)計(jì)。架構(gòu)的決策就是系統(tǒng)結(jié)構(gòu)上的決策,這些決策影響著全部代碼,決定了系統(tǒng)中其它部分的基礎(chǔ)。

除了其它用處以外,架構(gòu)決定了系統(tǒng)的:

  • 組件
  • 組件之間的關(guān)系
  • 指導(dǎo)對(duì)組件以及及其之間關(guān)系進(jìn)行設(shè)計(jì)和演進(jìn)的原則

換句話說,這些設(shè)計(jì)決策在系統(tǒng)演進(jìn)的過程中更難改變,它們是支撐特性開發(fā)的基礎(chǔ)。

意大利面架構(gòu)

我參與的有些項(xiàng)目結(jié)構(gòu)完全是隨意的,又不能體現(xiàn)架構(gòu)也不能反映領(lǐng)域。如果我的問題是“這個(gè)值對(duì)象應(yīng)該放在哪里?”,答案就是“隨便放在 src 目錄里就好了”。如果我的問題是“完成這個(gè)邏輯的服務(wù)在哪里”,答案是“用 IDE 搜索吧”。這意味著完全沒有思考該如何組織代碼。

這里的隱患很大,因?yàn)橥耆珱]有使用包來實(shí)現(xiàn)模塊化,高級(jí)別的代碼關(guān)系和流向完全不遵守任何邏輯結(jié)構(gòu),將導(dǎo)致高耦合低內(nèi)聚的模塊,實(shí)際上可能根本就沒有模塊劃分,本來應(yīng)該屬于某個(gè)模塊的代碼散落在整個(gè)代碼庫中。這樣的代碼庫就是所謂的意大利面代碼,或者是意大利面架構(gòu)!

可維護(hù)的代碼庫

擁有可維護(hù)的代碼庫意味著我們能以最小的代碼修改獲得最大的概念變化。換句話說,如果我們需要修改一個(gè)代碼單元,其它代碼單元的修改應(yīng)該盡可能地少。

這帶來了明顯的優(yōu)勢(shì):

  • 因?yàn)橛绊懙拇a少,修改會(huì)更容易;
  • 因?yàn)橛绊懙拇a少,修改會(huì)更快;
  • 因?yàn)樾薷牡拇a少,出現(xiàn)問題的幾率會(huì)降低;

封裝 、低耦合和高內(nèi)聚是保持代碼隔離的核心原則,使可維護(hù)的代碼庫成為可能。

封裝

封裝是隱藏一個(gè)類的內(nèi)部表示和實(shí)現(xiàn)的過程。

也就是說,實(shí)現(xiàn)被隱藏了,這樣類的內(nèi)部結(jié)構(gòu)可以隨意的改變,而不會(huì)影響使用這個(gè)類的其它類的實(shí)現(xiàn)。

低耦合

耦合涉及代碼單元之間的關(guān)系。如果一個(gè)模塊的修改會(huì)導(dǎo)致另一個(gè)模塊的修改,我們就說這兩個(gè)模塊高度耦合。如果一個(gè)模塊可以獨(dú)立于其它任何模塊,我們就說它是松耦合的。通過提供穩(wěn)定的接口來有效地對(duì)其它模塊隱藏實(shí)現(xiàn),可以達(dá)成松耦合的目標(biāo)。

低耦合的優(yōu)點(diǎn)

  • 可維護(hù)性 - 修改被限制在一個(gè)模塊中
  • 可測試性 - 單元測試涉及的模塊盡可能地少
  • 可讀性 - 需要仔細(xì)分析的類盡可能地少

高內(nèi)聚

內(nèi)聚指的是對(duì)模塊內(nèi)的功能相關(guān)性有多強(qiáng)的度量。低內(nèi)聚指的是模塊擁有一些不同的不相關(guān)的職責(zé)。高內(nèi)聚指的是模塊所擁有的功能在許多方面很相似。

高內(nèi)聚的優(yōu)點(diǎn)

  • 可讀性 - (緊密) 相關(guān)的功能包含在一個(gè)模塊中
  • 可維護(hù)性 - 只用在一個(gè)模塊內(nèi)調(diào)試代碼
  • 可重用 - 類的功能十分聚焦,不會(huì)充斥許多無用的函數(shù)

對(duì)結(jié)構(gòu)的影響

上述這些原則適用于類,然而,它們一樣適用于類的組合。類的組合通常被叫做包,但我們可以分得更細(xì)一些,如果分組是出于純粹功能方面的考慮(如ORM)我們會(huì)稱之為模塊,如果是出于領(lǐng)域方面的考慮(如AccountManagement)則稱之為組件。這些定義與 Bass、Clements 和 Kazman 在他們的著作 Software Architecture in Practice 里的描述一致。

我們能夠并且應(yīng)該讓包做到高內(nèi)聚和低耦合,因?yàn)檫@樣我們才能做到:

  • 修改一個(gè)包而不會(huì)影響其它的包,減少出現(xiàn)的問題;
  • 修改一個(gè)包而不需要修改其它的包,加快交付的節(jié)奏;
  • 讓團(tuán)隊(duì)專注于特定的包,帶來更快、更健壯和設(shè)計(jì)更優(yōu)的變化;
  • 團(tuán)隊(duì)開發(fā)活動(dòng)之間的依賴和沖突更少,提升產(chǎn)能。
  • 更仔細(xì)地斟酌組件之間的關(guān)系,讓我們更好地將應(yīng)用作為一個(gè)整體建模 ,交付質(zhì)量更高的系統(tǒng)。

概念封裝

我覺得如果我們的項(xiàng)目結(jié)構(gòu)能以某種方式既體現(xiàn)出架構(gòu)也體現(xiàn)出領(lǐng)域的話,我們的代碼庫的可維護(hù)性可以得到極大地提升。實(shí)際上現(xiàn)在我敢篤定這也是唯一可行的方式(當(dāng)我們面對(duì)大中型企業(yè)應(yīng)用時(shí))。

代碼庫如果組織得當(dāng),特定代碼單元只有一處位置可供它存放。我們可能并不知道到具體的位置,但一定只有一條邏輯路徑可以讓我們順藤摸瓜找到它。

包的定義

將類劃分成包可以讓我們?cè)诟叩某橄蠹?jí)別來思考設(shè)計(jì)。其目標(biāo)是將你的應(yīng)用中的類按照某種條件進(jìn)行分片,然后將這些分片分配到包中。這些包之間的關(guān)系表達(dá)出了應(yīng)用高級(jí)別的組織方式。—— Robert C. Martin 1996, Granularity pp. 3

將概念上相關(guān)的代碼定義成包,我們需要達(dá)成的目標(biāo)。這些包十分重要,因?yàn)樗鼈兌x了概念上相關(guān)且獨(dú)立于其它包的代碼單元,還有這些包之間的關(guān)系。

這樣做的目的是:

  • 理解代碼單元之間的關(guān)系
  • 維護(hù)代碼單元之間的邏輯關(guān)系
  • 實(shí)現(xiàn)高內(nèi)聚低耦合的代碼包
  • 在不影響/極少影響應(yīng)用的情況下重構(gòu)代碼包
  • 在不影響/極少影響應(yīng)用的情況下替換代碼包的實(shí)現(xiàn)

分包的原則

我們要遵循 Robert C. Martin 在 1996 年和 1997 年提出的包劃分原則以及其他的一些原則來達(dá)成目標(biāo),主要有 CCP (Common Closure Principle,共同封閉原則), the CRP (Common Reuse Principle,共同重用原則) 和 SDP (Stable Dependencies Principle,穩(wěn)定依賴原則)。

Robert C. Martin 提出的包劃分原則:

包內(nèi)聚原則

  • REP – 重用發(fā)布等價(jià)原則:重用的粒度等價(jià)于發(fā)布的粒度
  • CCP – 共同封閉原則:一起被修改的類應(yīng)該放在一個(gè)包里
  • CRP – 共同重用原則:一起被重用的類應(yīng)該放在一個(gè)包里

包耦合原則

  • ADP – 無環(huán)依賴原則:包的依賴圖中不能出現(xiàn)循環(huán)
  • SDP – 穩(wěn)定依賴原則:依賴應(yīng)該朝著穩(wěn)定的方向前進(jìn)
  • SAP – 穩(wěn)定抽象原則:抽象的級(jí)別越高,穩(wěn)定性就越高

要想合理地運(yùn)用 SDP,我們應(yīng)該定義出代碼的概念單元(組件)和組件的分層,這樣我們才能搞清楚那些組件應(yīng)該了解(依賴)其它組件。

然而,如果這些組件的邊界不夠清晰,我們就會(huì)把本該互不相干的代碼代碼單元混在一起,讓它們耦合在一起變成意大利面式代碼,最后將無法維護(hù)。

要讓這些邊界能清楚地呈現(xiàn)出來,我們需要把概念上相關(guān)的類放在同一個(gè)包中,就像我們把概念上相關(guān)的方法放在同一個(gè)類中一樣。在包這個(gè)級(jí)別,我們只能用一些名字在領(lǐng)域中有一定含義(例如,UserManagement、Orders、Payments 等)的文件夾來區(qū)分它們。在最底層的級(jí)別,即包內(nèi)的葉子節(jié)點(diǎn),我們才會(huì)在必要時(shí)按照功能作用區(qū)分類(例如,Entity、Factory、Repository 等)。

下面這個(gè)問題可以幫助我們反思如何設(shè)計(jì)出低耦合的組件:

“如果我想去掉一個(gè)業(yè)務(wù)概念,是不是刪除掉它的組件根目錄就能把這個(gè)業(yè)務(wù)概念的所有代碼刪除而且應(yīng)用的剩余部分還不會(huì)被破壞?”

如果答案是肯定的,那么我們就有了一個(gè)解耦得不錯(cuò)的組件。

例如,在命令總線架構(gòu)中,命令和處理器離開對(duì)方就無法工作,它們?cè)诟拍钌虾凸δ苌隙冀壎ㄔ谝黄穑虼?,如果我們需要去掉該邏輯就要將它們一起去掉。如果它們?cè)谕粋€(gè)位置,我們只用刪除一個(gè)文件夾就好(我們并非真的要?jiǎng)h除代碼,只是借助這種思維方式來幫我們得到解耦和內(nèi)聚的代碼)。所以,遵循 CCP 和 CRP 原則,命令應(yīng)該和它的處理器放在同一個(gè)文件夾中。

任何代碼只能存在于一個(gè)邏輯上的位置,即使對(duì)項(xiàng)目中的新手和初級(jí)開發(fā)者來說,這個(gè)位置也是十分明了的。這能避免自相矛盾、令人費(fèi)解、重復(fù)的代碼和開發(fā)者的挫敗感。如果因?yàn)闊o法在代碼本該在的位置找到它,和/或難以理解哪些代碼和手頭上正在處理的代碼有關(guān),而導(dǎo)致我們需要去搜尋這些代碼...那么我們的項(xiàng)目結(jié)構(gòu)就很糟糕,甚至是更壞的情況,架構(gòu)很糟糕。

尖叫架構(gòu)

尖叫架構(gòu)是 Robert C. Martin 的想法,它基本上表明了這樣一個(gè)觀點(diǎn),架構(gòu)應(yīng)該清楚地告訴我們系統(tǒng)是做什么的:即它的主要領(lǐng)域。那么源代碼文件夾里出現(xiàn)的第一級(jí)目錄自然就應(yīng)該和領(lǐng)域概念有關(guān),即最頂層的限界上下文(例如,患者、醫(yī)生、預(yù)約等)。它們應(yīng)該和系統(tǒng)使用的工具(例如,Doctrine、MySQL、Symfony、Redis 等)無關(guān),和系統(tǒng)的功能塊(例如,資源庫、制圖、控制器等)無關(guān),和傳達(dá)機(jī)制無關(guān)(HTTP、控制臺(tái)等)。

你的架構(gòu)應(yīng)該呈現(xiàn)給人的應(yīng)該是系統(tǒng),而不是系統(tǒng)使用的框架。如果你構(gòu)建的是一個(gè)醫(yī)療保健系統(tǒng),那么新程序員看到源代碼倉庫后的第一映像應(yīng)該是:“哦,這是一個(gè)醫(yī)療保健系統(tǒng)”。—— Robert C. Martin 2011, Screaming Architecture

這實(shí)際上是一種更簡單地理解他十五年前發(fā)表的包劃分原則的方法,這些原則之前我已經(jīng)闡述過了。這種分包的風(fēng)格又叫做“按特性分包”。

延伸閱讀

  • 2008 – Johannes Brodwall – Package by feature
  • 2012 -Johannes Brodwall – How Changing Java Package Names Transformed my System Architecture
  • 2012 – sivaprasadreddy.k – Is package by feature approach good?
  • 2013 – Lahlali Issam – Lessons to Learn from the Hibernate Core Implementation
  • 2013 – Manu Pk – Package your classes by Feature and not by Layers
  • 2015 – Simon Brown – Package by component and architecturally-aligned testing
  • 2015 – César Ferreira – Package by features, not layers
  • 2017* – javapractices.com – Package by feature, not layer

 引用來源

  • 1996 – Robert C. Martin – Granularity
  • 1997 – Robert C. Martin – Stability
  • 2009 – 500internalservererror – What do low coupling and high cohesion mean? What does the principle of encapsulation mean?
  • 2011 – Robert C. Martin – Screaming Architecture

 

[[397016]]

覃宇,Android開發(fā)者/ThoughtWorks技術(shù)教練//譯者,熱衷于探究軟件開發(fā)的方方面面,從端到云,從工具到實(shí)踐。喜歡通過翻譯來學(xué)習(xí)和分享知識(shí),譯作有《Kotlin實(shí)戰(zhàn)》、《領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)精粹》、《Serverless架構(gòu):無服務(wù)器應(yīng)用與AWS Lambda》和《云原生安全與DevOps保障》。

 

責(zé)任編輯:武曉燕 來源: 逸言
相關(guān)推薦

2021-06-09 08:09:05

架構(gòu)軟件整潔

2021-03-26 07:47:18

單體架構(gòu)程序

2021-04-12 09:48:50

MVCHTMLCSS

2012-06-11 15:29:14

OpenStack

2015-07-17 13:27:06

2012-12-21 15:32:32

Linux Deepi

2019-01-23 17:37:58

華為

2011-07-20 09:19:47

SQL Server

2014-10-29 14:43:05

2014-05-20 17:26:06

2012-03-30 11:34:52

Linux Deepi

2014-12-12 14:55:42

移動(dòng)惡意代碼移動(dòng)安全

2011-08-08 09:25:55

2013-10-31 14:31:09

2025-01-23 09:07:51

2015-12-16 10:11:14

2020-08-21 13:54:24

瀏覽器程序員內(nèi)核

2023-09-06 06:46:40

顯卡接口RTX 4060

2014-05-09 11:19:38

iOS移動(dòng)互聯(lián)網(wǎng)

2009-09-22 08:14:23

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)