業(yè)務邏輯應該清楚地分開并且獨立于框架
先看下我們熟悉的MVP架構
再看下我們熟悉的MVP+管理類
提前預覽下Clean的架構
再來看下真正的主題 Android Clean
?它也被稱為洋蔥架構竹祷,因為該圖看起來像一個洋蔥(當您意識到必須寫多少樣板時渴丸,它會讓您哭泣)订咸。或端口和適配器,因為如您所見,在右下角有一些端口处嫌。六角形架構是另一種相似的架構。
?清潔架構是先前提到的Bob叔叔的創(chuàng)意斟湃,他還撰寫了有關Clean Code和Clean Coder的書熏迹。這種方法的要點是,業(yè)務邏輯(也稱為域)位于宇宙的中心凝赛。
依賴規(guī)則
?外層應取決于內層注暗。紅場中的三個箭頭表示依賴性坛缕。與其說“依賴”,不如使用“看見”捆昏,“知道”或“知道”之類的詞赚楚。用這些術語,外層可以看到骗卜,知道和知道內層宠页,但是內層既看不到也不知道,也不知道外層寇仓。如前所述举户,內層包含業(yè)務邏輯,外層包含實現(xiàn)細節(jié)遍烦。結合依賴規(guī)則俭嘁,可以得出結論,業(yè)務邏輯既看不到也不知道服猪,也不知道實現(xiàn)細節(jié)供填。而這正是我們正在努力實現(xiàn)的目標。
抽象化
?以前已經暗示過抽象原理罢猪。它說近她,當您朝圖的中間移動時,內容變得更加抽象坡脐。這是有道理的:正如我們所說的泄私,內圈包含業(yè)務邏輯,外圈包含實現(xiàn)細節(jié)备闲。
?如圖所示,您甚至可以將相同的邏輯組件劃分在多個層之間捅暴√裆埃可以在內層中定義更抽象的部分,而在外層中定義更具體的部分蓬痒。
?您可以在該圖中看到標準三層體系結構中的所有依賴關系都進入了數(shù)據(jù)庫泻骤。這意味著抽象和依賴關系不匹配。從邏輯上講梧奢,業(yè)務層應該是應用程序的中心狱掂,但并不是,因為依賴關系會進入數(shù)據(jù)庫亲轨。
?在干凈的體系結構中趋惨,依賴項進入業(yè)務(內部)層,而抽象也向業(yè)務層發(fā)展惦蚊,因此它們匹配得很好器虾。
?這很重要讯嫂,因為抽象是理論,而依賴是實踐兆沙。抽象是應用程序的邏輯布局欧芽,而依賴關系是應用程序實際組合在一起的方式。在干凈的體系結構中葛圃,這兩個匹配千扔,而在標準的三層體系結構中,它們不匹配库正。如果您不小心昏鹃,可能很快導致各種邏輯上的不一致和混亂。
層間通訊
?現(xiàn)在诀诊,我們已經將應用程序劃分為模塊洞渤,將所有內容很好地分離了,將業(yè)務邏輯放在應用程序的中心属瓣,而實現(xiàn)細節(jié)則在郊區(qū)载迄,一切看起來都很棒。但是您可能很快就遇到了一個有趣的問題抡蛙。
?如果您的UI是實現(xiàn)細節(jié)护昧,互聯(lián)網(wǎng)是實現(xiàn)細節(jié),并且業(yè)務邏輯介于兩者之間粗截,那么我們如何從互聯(lián)網(wǎng)上獲取數(shù)據(jù)惋耙,通過業(yè)務邏輯傳遞數(shù)據(jù),然后將其發(fā)送到屏幕熊昌?
?業(yè)務邏輯位于中間绽榛,應該在Internet和UI之間進行調解,但它甚至不知道這兩個家伙是否存在婿屹。這是通信和數(shù)據(jù)流的問題灭美。
?我們只有兩層,綠色一層和紅色一層昂利。綠色的一個在外面届腐,知道紅色,紅色的一個在里面蜂奸,只知道自己犁苏。我們希望數(shù)據(jù)從綠色的一到紅色的一再回到綠色的一。解決方案之前已經暗示過扩所,并在下圖中顯示:
?右下角的圖部分顯示了數(shù)據(jù)流围详。數(shù)據(jù)從控制器輸入,通過用例(或用您選擇的組件替換用例)輸入端口碌奉,然后通過用例本身短曾,然后通過用例輸出端口返回到演示者寒砖。
?輸入端口是一個接口,實際的實現(xiàn)是用例:因此它在用例上調用了一個方法嫉拐,數(shù)據(jù)流到該用例哩都。用例做了一些事情,想將數(shù)據(jù)發(fā)送回去婉徘。它具有對輸出端口的引用(因為輸出端口是在同一層中定義的)漠嵌,因此它可以在其上調用方法。因此盖呼,數(shù)據(jù)進入輸出端口儒鹿。最后,演示者是或實現(xiàn)輸出端口几晤。那是神奇的部分约炎。當它實現(xiàn)輸出端口時,數(shù)據(jù)實際上流入其中蟹瘾。
?定義其輸入和輸出端口是內層的責任圾浅,以便外層可以使用它們與之建立通信。我們在內部層定義了一個通知接口憾朴,業(yè)務邏輯可以使用該接口向用戶顯示通知狸捕,但是在外部層也定義了一個實現(xiàn)。在這種情況下众雷,通知接口是業(yè)務邏輯的輸出端口灸拍,它用于與外部世界進行通信-在此示例中為具體實現(xiàn)。
Clean架構圖的模塊對應
?所有這些都按模塊級別砾省,包級別和類級別整齊地分開鸡岗。因此,應該滿足SRP
?我們已盡可能將Android和現(xiàn)實世界中的東西推向郊區(qū)纯蛾。業(yè)務邏輯不再直接接觸Android纤房。
?Clean可以更方便的進行分類測試
?Clean可以更清晰的對各個著重方向進行關注
依存關系
?依賴性規(guī)則定義具體模塊依賴于更抽象的模塊。
?UI(app)翻诉,DB – API(數(shù)據(jù))和Device(設備)東西在外圈中。意味著它們處于相同的抽象級別捌刮。那么我們如何將它們連接在一起碰煌?
?理想情況下,這些模塊將僅取決于域模塊绅作。在這種情況下芦圾,依賴項看起來有點像星星:
?但是,我們在這里使用Android時俄认,事情還不能完美个少。因為我們需要創(chuàng)建對象圖并初始化事物洪乍,所以模塊有時依賴于域以外的其他模塊。
?例如夜焦,我們正在為app模塊中的依賴項注入創(chuàng)建對象圖壳澳。這迫使應用程序模塊了解所有其他模塊。
?我們調整后的依賴關系圖:
Clean是一把雙刃劍
優(yōu)點
- 測試就變得更加容易
- 漏洞更容易被隔離
- 新功能也很容易添加
- 代碼更易讀和可維護
- 單向依賴茫经、數(shù)據(jù)驅動編程
缺點
- 結構復雜
- 粒度太細
- Usecase 的復用率極低
- 急劇的增加類和重復代碼
總結
?遵循這些準則巷波,我們創(chuàng)建了一個健壯且通用的體系結構。乍一看卸伞,它看起來像很多代碼抹镊,確實如此,但請記住荤傲,我們正在為將來的更改和功能構建體系結構垮耳。如果操作正確,將來您將心存感激遂黍。
個人感覺Clean架構更適合多人協(xié)同的大項目终佛,不然有點殺雞用牛刀的感覺。
?