前言:
每次準備寫新的項目,特別是需要重構(gòu)以前經(jīng)外包人員或者N任開發(fā)人員的手寫的項目的時候,總會不自覺的看看當年所學(xué)習的關(guān)于架構(gòu)方面的知識:每次看感覺都不一樣!
文末附自己研究并實踐的新的架構(gòu)模式——MVCH模式:
友情提示:本篇重點旨在供iOS開發(fā)者參考使用的,其他程序猿(媛)可跳過!
一.總侃架構(gòu):
1.不要用Common 和Core等文件夾:
這個問題,一定要避免,因為可能一不小心,后期就會出現(xiàn)無法維護的災(zāi)難!
這個核心處理就在于減小類似Common類內(nèi)部代碼的聯(lián)系和耦合性,從而其他App想要什么就你可以直接拿什么。
2.盡可能考慮項目的可移植性:
就是類與類之間的關(guān)系不要太緊密了,造成緊密的方式主要有以下幾種情況:
過多的繼承關(guān)系;
橫向依賴過多;
以及MVC中各模塊功能不清不楚等。
3.關(guān)于業(yè)務(wù)邏輯內(nèi)部分層:
不要一上來就分層,說要用MVC架構(gòu)或者MVVM架構(gòu)等,應(yīng)該對整體框架處理好了之后,發(fā)現(xiàn)某一塊可能特別大,這個時候再考慮應(yīng)該分幾層,應(yīng)該用什么架構(gòu)更合適些!
可能一個項目中每個業(yè)務(wù)邏輯模塊用的架構(gòu)其實都不一定一樣哦,但是大部分業(yè)務(wù)應(yīng)該是以MVC架構(gòu)為主的!
二.View層的組織和調(diào)用方案
View層常見的問題如下:
View層的組織和調(diào)用方案,更改最頻繁;
濫用繼承的關(guān)系;
橫向依賴比較多;
View展示與數(shù)據(jù)處理未分隔清楚。
解決辦法要從以下幾個方面處理:
1.View層代碼結(jié)構(gòu)方面:
重點強調(diào)? Private Method 的方法中要考慮其他地方是不是也要用,如日期換算,圖片裁剪等就需要單獨再寫個分類
記住一個原則,當一段代碼需要在2個以上地方cmd +c,cmd +v的時候,就要考慮是否單獨分割一個類來處理。
但是View的純粹界面創(chuàng)建不在這里討論范圍內(nèi),因為View的布局或者排版對于產(chǎn)品經(jīng)理來說是有可能經(jīng)常變動的,所以就不要那么懶了,該初始化還初始化,該懶加載就加載。
2.View層的布局做法:
View層的布局,代碼層面用的Masonry,是否可以考慮用用UIView+LayoutMethods和 UIView+AEBHandyAutoLayout感受下。
3.StoryBoard,Xib,Code孰優(yōu)孰劣:
Code替代StoryBoard更好些,偶爾用下StoryBoard,比方TabBar下的子控制器分類與跳轉(zhuǎn),可以讓每個主模塊的界面與界面之間關(guān)系更清晰一些,也未嘗不可!
4.繼承層級多少,度的把控問題:
項目的速度方向成也繼承,敗也繼承!
我沒有作者那么排斥繼承,但我的意思是繼承關(guān)系最多不超過3層,一般為2層。
比方說像我以前的空項目:空項目的準備,統(tǒng)一Nav的定制就是2層關(guān)系。
還有比方:有時候的繼承是要我們的項目繼承某個第三方庫的某個類,這個時候如果只繼承一次,那么就繼承唄;而如果比方說A為某第三方的類,B要繼承A進行界面方面(比方環(huán)信的聊天界面),而C要繼承B的部分真正聊天的功能方面,這個時候我的建議是對B和C分別繼承A,然后用一個枚舉定義,來分別標識B和C界面。一定要打破B和C的關(guān)聯(lián)性!
因為比方說這個時候有另外一個項目:需要用到C中的界面和數(shù)據(jù)處理方面,那么我只需要拿走A和C即可,如果濫用繼承的話,我要拿走A,B,C,這還不算,如果我要改某些地方,我是該在B中改好呢,還是C中改好呢?
所以說,繼承的層數(shù)最多3層,超過了后面就是代碼維護的災(zāi)難!
當然,最重要的是,新來工程師學(xué)習的成本也很大!
好了,重點來了,引入我的MVCH模式:
三.從N種架構(gòu)模式中創(chuàng)造MVCH模式:
常見的架構(gòu)模式有以下幾種
MVC、MVVM、MVCS、VIPER,加一種自己發(fā)明的MVCH(MVC +Helper)模式。
為何引入MVCH架構(gòu)模式目的在于:對于無論以上那種設(shè)計模式中,都對于業(yè)務(wù)邏輯的耦合性降低了不少,但是比方在首頁中的一個地圖類,只需要顯示當前位置,以及定位當前位置,那么在導(dǎo)航模塊中需要真正的地圖,這種情況下,傳統(tǒng)的來說,要么把地圖功能處理類直接放到最外層去整體協(xié)調(diào)我們業(yè)務(wù)邏輯的代碼,但這樣好像不是太合適,因為畢竟還是屬于我們業(yè)務(wù)方的代碼,為何還要放在外面呢?
怎么辦呢?
我的處理辦法是,在導(dǎo)航類中加入一個Helper文件夾,里面加入 LoctionManager,然后用不同的比方Bool值,比方枚舉等來判斷是哪個模塊的VC調(diào)用了讓我的LoctionManager 提供具體位置(經(jīng)緯度)還是要只提供省市區(qū)這種情況!這樣就可以發(fā)現(xiàn)加深了不同業(yè)務(wù)邏輯中相同功能的交流(好像有點繞口),減少相同功能寫過多重復(fù)代碼的問題!
以上不管種架構(gòu)模式,核心基礎(chǔ)都是MVC架構(gòu),但是在實際開發(fā)中,開發(fā)中的業(yè)務(wù)無非就分以下三種情況,由簡單到復(fù)雜模式:
首先按照業(yè)務(wù)邏輯來分,先分幾個模塊:之后每個模塊再采用相應(yīng)的架構(gòu)模式(不一定全是MVC哦)去設(shè)計!
1.最簡單的(比方登錄注冊,我的,設(shè)置等模塊):
此類單一模塊,基本MVC就可以搞定,一般直接用MVC架構(gòu)模式去處理,甚至來說,有時候一個C(Controller)文件就可以,比方設(shè)置常見的TableView界面;
2.大部分的業(yè)務(wù)(如首頁,發(fā)現(xiàn),朋友圈等模塊):
一般設(shè)計的業(yè)務(wù)邏輯不算復(fù)雜,比較常用,功能相對單一,這個時候就還用MVC架構(gòu)模式,對于對應(yīng)的功能,需要一個Manager管理類來進行協(xié)調(diào),可能也有一些只有當前業(yè)務(wù)模塊使用的工具類等,把這2個放到Helper類中即可!
3.當然還有極個別的模塊(如之前比較火的視頻直播功能為一個模塊):
這樣的業(yè)務(wù)一般就比較復(fù)雜了,傳統(tǒng)的MVC或者MVVM等架構(gòu),要么還沒徹底分開,造成胖Controller,要么分的太多,不好管理,建議嘗試使用MVC +Helper模式。其中Helper里面可以包含如:VideoManager(視頻播放類),網(wǎng)絡(luò)請求類(RequestManger),ChatManger(聊天類)等,每個復(fù)雜功能拆分后放到Helper中去管理!
如果還是覺得不太合適,無法很好解決這個復(fù)雜模塊那就繼續(xù)拆唄,試試VIPER架構(gòu)模式,這是他的中文鏈接:使用 VIPER 構(gòu)建 iOS 應(yīng)用
拿走不謝!
總之:侃了那么多,引入MVCH架構(gòu)模式的目的是為讓各個不同業(yè)務(wù)邏輯模塊之間(特別是VC)總要有那么一丁點聯(lián)系,就是Helper了!
好了后面幾篇就談?wù)勱P(guān)于架構(gòu)的其他方面:
數(shù)據(jù)存儲,網(wǎng)絡(luò)鏈接,乃至最后的組件化方案等,歡迎捧場!
最后附上:
一直在學(xué)習架構(gòu)的參考資料:
當年自己學(xué)習架構(gòu)知識的成果展示:
iOS架構(gòu)漫談1---架構(gòu)入門和Controller的內(nèi)部布局
有問題:加QQ:1824496534,備注:架構(gòu),歡迎指導(dǎo)!