The Clean Architecture,cleanarchitecture
- 原文連結:The Clean Architecture
- 譯者:zimoguo
在過去的幾年中,我們已經看到了關於系統架構的一些想法 :
- Hexagonal Architecture(六角架構)(a.k.a. Ports and Adapters) 這種架構是由Alistair Cockburn提出的,並由Steve Freeman和Nat Pryce在他們的書Growing Object Oriented Software中提出。
- Onion Architecture(洋蔥架構) 提出者是Jeffrey Palermo。
- 尖叫架構(Screaming Architecture) 提出者是Uncle Bob(就是這篇文章的作者)。
- DCI架構 提出者是James Coplien和Trygve Reenskaug。
- BCE架構 提出者是Ivar Jacobson。在他的書《Object Oriented Software Engineering: A Use-Case Driven Approach》中有大量提及對這種架構的說明。
雖然這些文章在細節上有所不同,總體來說是非常相似的.它們關注點分離,通過將軟體劃分成層達到分離效果.每層最少包含一個業務規劃或者介面。
這些架構有以下特點:
- 獨立架構
這些架構不依賴某些特定庫的載入,允許你使用架構作為工具,不會限制你的系統;
- 可測試
業務規劃在沒有UI介面,資料庫,網頁伺服器或者其他外部元素的情況下進行測試;
- 獨立於UI
UI很容易改變,而不用改變系統的其他部分,網頁介面可以被控制台介面替換,同時還不用改變業務規劃; 4.獨立於資料庫
你可以切換到Oracle,SQL Server,Mongo,BigTable,CouchDB或者其他類型資料庫,商務規則不與資料庫綁定; 5.獨立於任何外部代理
事實上你的業務規劃根本不需要知道外面的世界
在這篇文章頂部的圖表是將這些架構的理念整合在一起。
依賴規則
同心圓代表軟體的不同地區,一般情況下,越接近中心位置軟體的層級會變得越來越高,外圓圈是機制,內圓圈是策略。
覆蓋規則使得架構遵循依賴規則,這條規則表明,原始碼只能向內依賴,內側圓環不瞭解關於外側圓環的一起,原則上,外圈圓環聲明的名稱不需要在內側圓環中提到,其中包括函數,類,變數或者其他軟體實體的名字
出於同樣的原因,在外圓圈中使用的資料格式不應該使用在內圓圈,特別是格式是由外圓圈的架構產生的情況,我們不希望外圓圈影響內圓圈的內容
實體
實體封裝專案範圍內的商務規則,一個實體可以是一個對象的方法,或者是一組資料結構和功能.只要在項目中實體被不同的應用所使用即可。
如果你沒有項目,只是單純的寫一個應用程式,那麼這些實體就是應用程式的業務對象.它們封裝的最普通,最進階的規則.當外部變化時,它們最有可能改變,例如,你不希望這些對象被一個更改的頁面導航或者安全影響,改變特定應用程式的操作不應該影響實體層。
用例
在此層應用的商務規則包含應用特定的商務規則,他封裝並實現了所有的系統用例,這些用例編排資料的流入和流出的實體,指示這些實體用在它們專案範圍內的商務規則到達用力的目標。
我們不希望改變層時影響實體,也不希望層被外部的改變所影響,例如資料庫,使用者介面或者任何的共同架構的改變,此層與這部分是隔離開的。
我們這樣做,不過是希望改變應用程式的操作時影響軟體層的用例,用例詳細資料改變時,這一層的代碼也會受到影響。
介面適配器
這層軟體是一個轉化數位適配器,從格式最方便的用例和實體轉化為格式最方便的一些外部機構,如資料庫或者網頁,這一層完全包含GUI的MVC架構,代理者,視圖,控制器都屬於這一層,該模型可是只是從控制器傳回到用例,然後從用例到代理和視圖的資料結構。
同樣的,在這一層資料被轉換,從形式最方便的實體和用例轉化成形式最方便的使用持久架構,即資料庫.內圈裡的任何代碼不應該知道關於資料庫的任何事情.如果這個資料庫是SQL資料庫,所有的SQL應該被限制在這一層,尤其是在這層對資料庫的操作。
另外,在這一層其他適配器需要將資料從外部形勢(如外部服務)轉化成內部形式的用例和實體。
架構和驅動程式
最外層一般由架構和工具組成,如資料庫,web架構等.一般來說,你不會在這一層寫太多代碼,而是貼代碼傳達到內層圓圈內。
這一層有很多細節,網頁是一個細節,資料庫是一個細節,我們保持外層的這些細節收到更少的破壞。
只有四個圓環?
不,圓圈只是傳達意思,你可能會發現你使用到的不僅僅是這四個,沒有規定你必須使用這四個圓環,然後,依賴規則始終適用,原始碼始終向內依賴.越往圓圈內側抽象水平越高,最外面的圓圈為低一級的具體細節.越往圓圈內側抽象和封裝的層次更高,最內側圓層次最高,最普通.
跨越邊界
該圖的右下方是一個我們如何穿越邊界的例子,它展示了控制器和代理者與下一層用例進行通訊.注意控制流程,開始於控制器,通過用例移動,結束於代理者的執行.還要注意原始碼的依賴關係,指向內側用例。
我們通常使用依賴倒置原則解釋這個明顯的矛盾,像java語言,例如,我們會編排介面和繼承的關係,使原始碼在跨越邊界的右側點依賴反對控制流程.
例如,考慮用例需要調用的代理.然而不需要直接調用,因為這將違反相關性規則:在外圈中的名稱不需要在內圈中提及.因此,我們在內側圓環中調用介面(這裡顯示的用例輸出連接埠),在外側圓環實現它.
相同的技術應用在跨越邊界的系統結構中,無論控制流程會在什麼方向,我們以動態多態性的優勢建立原始碼依賴性,反對控制流程,使得我們能夠符合依賴規則。
什麼是資料跨越邊界
通常跨越邊界的資料是一種單純的資料結構,可以使用基本的結構或者簡單的資料進行傳輸.或者資料可以單純的在函數中調用,或者你可以打包成一個hashMap,或構造成一個對象,重要的是分離,操作簡單,通過資料結構跨越邊界.我們不想通過實體和資料作弊,不希望資料結構有任何一種依賴違反依賴規則.
例如,很多資料庫架構響應查詢返回一個方便的資料格式,我們稱之為行結構.我們不希望向內跨越行結構,這將違反依賴規則,因為這會迫使內側圓環瞭解外側圓環的一些東西。
因此,當我們跨越邊界傳輸資料時,它總是使用最方便內圓環的格式。
結論
符合這些簡單的規則並不難,並會為你省掉很多前進過程中頭疼的問題,通過軟體分層,順應依賴規則,建立一個系統在本質上是可以檢測的,意味著擁有其本身的好處.當任何一個系統的外部組件過時時,如資料庫或者web架構,你可以使用最少的憂慮替換掉那些過時的元素。