關(guān)于iOS軟件架構(gòu)設(shè)計模式的粗淺思考

前言

2018年底,對于已經(jīng)從事軟件開發(fā)工作了4年多的我,經(jīng)歷從輾轉(zhuǎn)深圳、流浪貴陽的顛簸,由于多年的開發(fā)經(jīng)驗,自我審視的時候發(fā)現(xiàn)自己業(yè)務(wù)能力不錯、項目經(jīng)驗豐富,但對計算機底層缺乏較深的認識,對設(shè)計模式也沒有深刻的理解。當(dāng)然,這是我接下來一段時間工作的重點。

為什么說這么多廢話,因為之前我并沒有打算在本文中探討太專業(yè)的東西,而本文目標(biāo)也是面向像我一樣深處迷茫探索中的小白,主要從宏觀上聊聊工程結(jié)構(gòu)、從微觀上聊聊類的設(shè)計。

本文構(gòu)思基礎(chǔ)
之前在公司開發(fā)遇到幾個問題

1.項目太大,運行調(diào)試太慢,感覺降低了開發(fā)效率
2.項目由于底層庫的原因不能模擬器調(diào)試,只能真機,進一步降低效率
3.工程文件結(jié)構(gòu)復(fù)雜,開發(fā)人員較多,相關(guān)模塊分離不明顯,難以尋找
4.類似滴滴打車這樣的項目,需要開發(fā)多個客戶端,但功能、網(wǎng)絡(luò)接口等基本相同,如果使用多個工程導(dǎo)致大量重復(fù)代碼,將來也不容易同步維護相同邏輯的代碼

探索思路

1.組件化探索、插件化設(shè)計思路
2.多target模塊設(shè)計思路,新建target包裝較復(fù)雜的模塊,一方面可以分離業(yè)務(wù)邏輯,另一方面也可以使得單個模塊運行速度更快、解決不能真機調(diào)試問題

新問題

1.公共模塊內(nèi)部引用了其它無關(guān)模塊的邏輯,當(dāng)分離出target以后發(fā)現(xiàn)target并不單純,還是需要引入編譯大量無關(guān)邏輯的代碼,為達到編譯效率最大化
2.如果需要開發(fā)一個項目多個客戶端,達不到邏輯清晰可辨,還是會帶來維護上的問題

最終

1.花了大量時間重構(gòu)了公共模塊代碼,分類模塊之間業(yè)務(wù)邏輯
2.基本類似的功能業(yè)務(wù)遷移重構(gòu),達到解耦復(fù)用目的
3.只做了項目中一小部分的工作,難以達到理想中的效果,不過:一直在路上

思考:不忘初心

  • 宏觀上最初的工程架構(gòu)
  • 微觀上具體到每個類的設(shè)計
  • 中觀上建立自己的公共代碼倉庫

關(guān)于工程結(jié)構(gòu)

在開發(fā)新項目前,你首先應(yīng)該有一個清晰的工程結(jié)構(gòu),無論做什么事情之前我們都應(yīng)該有一段長長的思考,多對自己提一些疑問,多像自己談?wù)劇盀槭裁??”?/strong>

iOS開發(fā)工程目錄結(jié)構(gòu)

在我們熟知的設(shè)計模式中,以MVC名頭最響,MVVM更像是另辟蹊徑或者說別出機杼,或許有人會說這是標(biāo)新立異、故意顯擺,關(guān)于孰優(yōu)孰劣再次不做討論,開發(fā)上的各種思路見仁見智,我個人更推薦MVVM。

根據(jù)個人習(xí)慣有所不同,有些人喜歡整個項目結(jié)構(gòu)中就是一個巨型MVC或者MVVM,即外層結(jié)構(gòu)+內(nèi)部模塊,然后再在“Models/”或者“Views/”、“Controllers/”等目錄下分模塊,如GitHub優(yōu)秀APP源碼Coding-iOS客戶端。

最外層MVC

而有些人喜歡這樣分,外層模塊+內(nèi)部結(jié)構(gòu),如下圖方式

模塊內(nèi)MVC

具體宏觀上用什么目錄結(jié)構(gòu)見仁見智,記住沒有最好只有更好,對我來說我推薦第一種,可能是習(xí)慣亦或是對大神的仰慕。

不管什么方式,只要在自己心目中設(shè)計的時候按照清晰的MVC或者MVVM設(shè)計,就非常容易理清邏輯,但對于一個工程來說,微觀上的架構(gòu)可能才是最重要的,因為我們在花幾天時間建立好工程后,接下來的所有日志都主要集中在微觀邏輯架構(gòu)的開發(fā)維護上,因此我說微觀上的架構(gòu)更重要,而最初的架構(gòu)設(shè)計確實無與倫比的,將決定了項目未來的代碼如何發(fā)展、是否易于擴展、開發(fā)和維護等。

關(guān)于類的設(shè)計

我們常說到低耦合、高內(nèi)聚思想,基本任何開發(fā)人員都知道這個概念,但在設(shè)計上卻鮮有人能熟練駕馭。我們總在不知不覺中被方便的思想左右,不愿意去寫接口協(xié)議、不愿意去做回調(diào)hook處理,這都是通病,以下通過實例談?wù)効捶?/strong>

1.設(shè)計一個通用類:圖片展示器 ImageBrowser

// ImageBrowser應(yīng)該向外提供如下接口

- images/imageURLs接收方法
- show方法(打開)
- close方法(關(guān)閉)
- block/delegate回調(diào)

// 注意事項
// 1.該類不應(yīng)該使用項目中定義的一些Define、Models、Views等
// 2.該類不應(yīng)該引用項目中某些類的頭文件,不應(yīng)該和項目中某些類的邏輯相關(guān)聯(lián),只能向外提供訪問接口
// 3.該類的總體思路應(yīng)該是單向的,即項目中類可以訪問它,而它不能直接訪問項目中的類
// 4.設(shè)計為插件式模塊,引入和抽離只需少量代碼,大量初始化工作應(yīng)在內(nèi)部完成,向外提供的應(yīng)該是非常簡潔的接口

2.第三方庫橋接文件,我們在項目中接入第三方庫的時候一般不會直接使用,應(yīng)該是簡歷橋接文件去和第三方庫對接,將來如果第三方庫更換也不用變動項目代碼,只需維護橋接文件即可。如設(shè)計一個AFNetworking的管理類

// 應(yīng)該向外提供如下接口
- get:(參數(shù)) block:(回調(diào)結(jié)果)
- post:(參數(shù)) block:(回調(diào)結(jié)果)
- upload:(參數(shù)) progressBlock:(回調(diào)進度) block:(回調(diào)結(jié)果)
...

// 注意事項
// 1.該類只與AFNetworking關(guān)聯(lián),不應(yīng)該關(guān)聯(lián)項目中的Define、Models、Views等
// 2.遵循單向訪問邏輯原則
// 3.遵循接口簡介原則

3.設(shè)計UITableViewCell

// 1.向外暴露需要變動展示數(shù)據(jù)的property
@property (nonatomic, weak) UILabel *titleLabel;
@property (nonatomic, weak) UIImageView *imageView;
...

// 向外提供hook接口
- block/delegate回調(diào)

// 注意事項
// 1.該類不應(yīng)該引直接引用Model,不應(yīng)該在內(nèi)部處理交互事件,應(yīng)hook到controller處理
// 2.該類若必須處理大量內(nèi)部邏輯,考慮綁定viewModel或者為其添加分類Category
// 3.該類不應(yīng)該引用其他模塊的頭文件

4.此外設(shè)計Tools、Category、Helper等工具類的時候也盡量保持相互間的獨立性

好處

1.不同模塊角色明晰,代碼均衡分布于這些模塊上
2.由第1點帶來的可測試性
3.易用性,維護成本低
4....

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

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

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