務(wù)實(shí)的iOS App架構(gòu)

【原文】https://medium.com/@martinmitrevski/pragmatic-ios-app-architecture-f7d6334fd8e4

關(guān)于iOS App架構(gòu)的文章有很多,解決方案有很多,其中也不乏設(shè)計(jì)精巧的架構(gòu)。但是沒(méi)有一種架構(gòu)適合所有的場(chǎng)景。But,如何選擇、取舍呢?下面的評(píng)估中有幾條參考規(guī)范。


Evaluating architecture

app中的每個(gè)模塊都應(yīng)該精心的組織并解耦。模塊之間不需要知道彼此的內(nèi)部詳細(xì)情況。

架構(gòu)要表達(dá)出項(xiàng)目所屬的商業(yè)領(lǐng)域。這是新加入成員能夠快速?gòu)拇a中獲取到的信息。對(duì)于維護(hù)和擴(kuò)展一個(gè)產(chǎn)品,架構(gòu)能進(jìn)行“自我介紹”是至關(guān)重要的。特別是,在不斷地往里面添加人手的時(shí)候。

可擴(kuò)展性。是否容易往里面添加新的特性。擁有一個(gè)優(yōu)雅的解決方案可以在未來(lái)幫你節(jié)省大量的時(shí)間和金錢(qián)。

架構(gòu)是否滿(mǎn)足商業(yè)領(lǐng)域的需求。app是以大量數(shù)據(jù)驅(qū)動(dòng)的?還是有大量需要用戶(hù)填寫(xiě)的表單?app的復(fù)雜程度,是只有五個(gè)頁(yè)面還是有50個(gè)頁(yè)面?

開(kāi)發(fā)團(tuán)隊(duì)的工作效率。團(tuán)隊(duì)是否可以快速的理解新的架構(gòu)和不懂得概念?是否可以無(wú)障礙的獨(dú)立進(jìn)行開(kāi)發(fā)工作?可以想象你的架構(gòu)中只有一個(gè)storyboard,在多人協(xié)作并且都編輯storyboard的情況下,合并代碼的時(shí)候可能會(huì)掉進(jìn)坑里!

測(cè)試是選擇架構(gòu)的另一個(gè)重要因素。那個(gè)關(guān)鍵模塊是我們想要測(cè)試的?只對(duì)值得測(cè)試的部分進(jìn)行測(cè)試,不要為了代碼覆蓋率(code coverage)而進(jìn)行測(cè)試。你可能有90%的代碼覆蓋率但是卻沒(méi)有覆蓋到至關(guān)重要的部分。另一個(gè)極端的情況,完美的項(xiàng)目設(shè)計(jì),彼此分離的模塊,但是代碼覆蓋率卻是0。

現(xiàn)實(shí)情況——另一個(gè)至關(guān)重要的部分。項(xiàng)目的截止日期和預(yù)算情況如何?在質(zhì)量和交付日期之間如何取舍?工程師需要更多的時(shí)間用最優(yōu)的方式去設(shè)計(jì)和實(shí)現(xiàn)項(xiàng)目,但銷(xiāo)售人員追求的卻是快速。每個(gè)人都有自己的關(guān)注點(diǎn),我們需要有意識(shí)的在兩只之間的進(jìn)行平衡。低劣的產(chǎn)品不會(huì)持久,但是遲來(lái)的產(chǎn)品也會(huì)被市場(chǎng)所淘汰。

因此,實(shí)用、中立(neutrality、大局觀,正是這些方面驅(qū)動(dòng)著我決定采用什么樣的架構(gòu)。


The good old?MVC (經(jīng)典架構(gòu) - MVC)

相當(dāng)困惑,為什么那么多人都放棄實(shí)用MVC模式?有人說(shuō)它代表著復(fù)雜笨重的View Controllers,不適合大型項(xiàng)目。但是我們有很多概念和模式可以幫助減小View Controllers的大小。比如:?delegation(代理), composition, dependency injection, protocols(協(xié)議), pure functions(唇方法), service / utility classes, navigation centers等。這些技術(shù)手段使得測(cè)試并不是那么的困難。

MVC

Going reactive

當(dāng)然,這還要看app的類(lèi)型,像facebook這種數(shù)據(jù)驅(qū)動(dòng)的app就不適合使用MVC,fb里面有太多的cells和內(nèi)容,使用經(jīng)典的MVC幾乎不太可能。一個(gè)帶有數(shù)據(jù)流的更加被動(dòng)的方案更適合這種情況(A more reactive approach with uni-directional data flow is more suitable in such cases.)。有一個(gè)很棒的fb架構(gòu)演示可以在這里查看。


MVVM

區(qū)別于流行于iOS領(lǐng)域的其他模式,MVVM是另外一種有趣的設(shè)計(jì)模式。具有挑戰(zhàn)性的是它可能會(huì)讓你的項(xiàng)目更加依賴(lài)像RxSwift這樣的第三方框架。MVVM由Microsoft發(fā)明,而且由于他的本地?cái)?shù)據(jù)綁定使得它極為好用。有時(shí)你甚至?xí)羞@種感覺(jué):你通過(guò)它與iOS SDK fight。另外一個(gè)具有挑戰(zhàn)性的方面是團(tuán)隊(duì)的學(xué)習(xí)曲線,這是由于它不同以往的編程方式造成的。不管如何,它都是對(duì)MVC的一次升級(jí),是選擇架構(gòu)時(shí)的一個(gè)有價(jià)值的參考項(xiàng)。

MVVM

Clean Architecture with VIPER and Clean?Swift

Robert C. Martin,世界級(jí)軟件開(kāi)發(fā)大師,設(shè)計(jì)模式和敏捷開(kāi)發(fā)先驅(qū),敏捷聯(lián)盟首任主席,C++ Report 前主編,被后輩程序員尊稱(chēng)為“Bob大叔”。

有這樣一個(gè)有趣的引述:VIPER就是當(dāng)你允許java企業(yè)開(kāi)發(fā)者進(jìn)入iOS領(lǐng)域?qū)?huì)引發(fā)的一些事情(VIPER is what happens when you allow Java enterprise programmers into the iOS world.)。VIPER會(huì)最大限度的分離關(guān)注點(diǎn)且極易測(cè)試,這既符合Uncle Bob 的整潔架構(gòu)思想。但是,再帶來(lái)諸多好處的同時(shí),還存在著一些麻煩,比如:太多的模板代碼、太多不同的部分、可能過(guò)度的設(shè)計(jì)。有時(shí)應(yīng)用VIPER的項(xiàng)目看起來(lái)可能及其整潔,但是當(dāng)你進(jìn)行一個(gè)極小的改變的時(shí)候可能會(huì)影響到app的很多層(牽一發(fā)而動(dòng)全身)。那它還值得采納嗎?答案是,看上面討論的諸多因素而定。

VIPER

VIP或者Clean Swift是整潔架構(gòu)的另一端口,這和VIPER有相似之處。從表面上看它看起來(lái)挺好的,但是(我)沒(méi)有實(shí)際的經(jīng)驗(yàn)?,F(xiàn)在有很多不同的低耦合的組件來(lái)讓你的應(yīng)用變的更易測(cè)試、更加健壯。Xcode中也有模板綁住你從零開(kāi)始。


Plugin architecture

還有一種不同的方式,就是Eclipse鼓勵(lì)的插件架構(gòu)。

首先這種方式解決什么樣的問(wèn)題,以及為什么我們決定使用它?Well,有這樣一個(gè)項(xiàng)目——用戶(hù)并不知道最終產(chǎn)品應(yīng)該長(zhǎng)什么樣子。我們有一個(gè)創(chuàng)建靈活的框架的任務(wù),使用這個(gè)框架我們可以創(chuàng)建很多由幾個(gè)可組合的模塊組成的不同的應(yīng)用??蛻?hù)可以用他們來(lái)進(jìn)行A/B測(cè)試,找出用戶(hù)想要的關(guān)鍵特征。例如,在其中一個(gè)app中包含兩個(gè)模塊,而在另外一個(gè)app中則包含5個(gè)模塊。菜單是可插拔的,這意味著我們可以輕松地把tiles菜單替換成旋轉(zhuǎn)菜單、導(dǎo)航抽屜或者tab bar。超級(jí)靈活!最酷的事情是我們可以通過(guò)文件對(duì)app的外觀和感覺(jué)進(jìn)行配置。這意味著只要后臺(tái)的一點(diǎn)小小的改變我們就可以觸發(fā)一個(gè)完全不同的app。


Plugin Architecture

App容器知道如何為app讀取配置信息、展示模塊。但它不知道應(yīng)該展示那個(gè)模塊,抑或模塊是如何實(shí)現(xiàn)的(原生,混合)。

各個(gè)模塊是彼此獨(dú)立的,因此開(kāi)發(fā)者可以完全的進(jìn)行獨(dú)立開(kāi)發(fā)。為了與各模塊進(jìn)行交互,開(kāi)發(fā)者需要在容器中實(shí)現(xiàn)一些必不可少的方法。模塊需要提供擴(kuò)展點(diǎn),在這里你可以注入其他模塊的功能。

做到這些需要大量使用協(xié)議(protocols)。這個(gè)架構(gòu)能很好的滿(mǎn)足你的需求。然而,這樣還存在一些挑戰(zhàn),例如:模塊間的通信難問(wèn)題和代碼復(fù)用問(wèn)題(因?yàn)槟K之間是彼此獨(dú)立的)。


Uni-directional data?flow(單向數(shù)據(jù)流)

配合著單向數(shù)據(jù)流使用還有一種有趣的架構(gòu)。受到Redux、Flux、ReSwift及其他相似架構(gòu)的項(xiàng)目的啟發(fā),可以使用單一的數(shù)據(jù)結(jié)構(gòu)展示app的狀態(tài)。在這個(gè)數(shù)據(jù)結(jié)構(gòu)保存著app使用中的的UI和models的狀態(tài)。Views訂閱并對(duì)任何的狀態(tài)改變進(jìn)行相應(yīng)的相應(yīng)——他們是觀察者。只能通過(guò)向保存app狀態(tài)的存儲(chǔ)器發(fā)送消息才能改變狀態(tài)。通過(guò)使用減速器(reducers)展示狀態(tài)的改變。這種類(lèi)型的架構(gòu)可以更容易的幫助你解釋程序的狀態(tài)。當(dāng)需要恢復(fù)之前的狀態(tài)的時(shí)候(例如:撤銷(xiāo)功能),它們的用處的真很大。然而,時(shí)間將會(huì)告訴你這個(gè)架構(gòu)是否適用于更復(fù)雜的app。


Conclusion

應(yīng)該選擇什么樣的架構(gòu)呢?當(dāng)然,并沒(méi)有直截了當(dāng)?shù)拇鸢?。如果答案很明顯的話就不會(huì)出現(xiàn)那么博客和討論了。大家總是能夠選擇最好的(最合適的)其中一個(gè)。誠(chéng)然,不同的架構(gòu)在給定的問(wèn)題領(lǐng)域中可能會(huì)有不俗的表現(xiàn)。對(duì)于這個(gè)話題你是如何想的?有沒(méi)有一個(gè)完美的app架構(gòu)?

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 第一篇文章對(duì)VIPER進(jìn)行了簡(jiǎn)單的介紹,這篇文章將從VIPER的源頭開(kāi)始,比較現(xiàn)有的幾種VIPER實(shí)現(xiàn),對(duì)VIPE...
    黑超熊貓zuik閱讀 13,187評(píng)論 11 76
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,160評(píng)論 25 708
  • “愛(ài)熄滅了燈心圍一座城” (一) 日光婆娑清風(fēng)微醺悸動(dòng)的目光搜索空氣里你留下的芳香“香樟樹(shù)下 歡聲細(xì)語(yǔ)校園之聲 相...
    長(zhǎng)脖子叔叔閱讀 175評(píng)論 0 0
  • 早上5:00鬧鐘,貞爸蹲著讀經(jīng)典: 《周易?說(shuō)卦傳》; 《詩(shī)經(jīng)》208楚茨~210信南山; 《黃帝內(nèi)經(jīng)?靈樞》根結(jié)...
    育心經(jīng)典包志剛閱讀 530評(píng)論 0 1
  • 舞臺(tái)魅影盛歌鐘,籠里老仙翁。 錦布翩飛張蓋,虛揚(yáng)幾許春風(fēng)。 驀然揭去,盈盈笑語(yǔ),美女其中。 流轉(zhuǎn)云煙明滅,凝眸一片...
    高十一妹閱讀 265評(píng)論 6 20

友情鏈接更多精彩內(nèi)容