APP超過5年的產(chǎn)品或者公司業(yè)務(wù)幾何倍增長的產(chǎn)品,不可避免的會需要重構(gòu)來保證APP的性能和穩(wěn)定性,可維護(hù)性。
從一個業(yè)務(wù)一個人完成變成了一個業(yè)務(wù)N個人協(xié)同合作完成。在代碼層面就是去耦合模塊化的過程。經(jīng)歷過一些過程留下一部分經(jīng)驗(yàn)供大家參考。下邊說的是個人感觸,也許你不太理解,我會備注相關(guān)的工作場景一一舉例。
1.減少對象的public屬性
簡單說,可讀性,可維護(hù)性。復(fù)雜說,你能減少各種風(fēng)險和坑,特別是多人協(xié)作的團(tuán)隊(duì)。
用一個工作場景說明:
一個VIewController(VC),早期1需求1.0版本:
VC:1.支持右滑關(guān)閉手勢 ?2. 右上角帶有詳情按鈕固定顯示,3.一個webview可以通過sckem交互4.統(tǒng)計用戶行為信息。你自己初步作出的類沒有問題。
之后A同事來了2需求:
需要同樣功能的VC,但要添加一個跳轉(zhuǎn)二級頁的按鈕,并且和你的詳情按鈕互斥。時間緊,B稍微懶一點(diǎn),拿你的VC用,.h里添加一個public BOOL類型,來解決這個互斥,并且把跳轉(zhuǎn)二級頁面的邏輯頁加入你VC里,一大堆業(yè)務(wù)邏輯也在你這扎根。沒有大改你的,他也OK。
之后B同事又來3需求:
需要同樣功能的VC,他的業(yè)務(wù)邏輯是需要彈出一個彈窗,能直接進(jìn)行支付,依然時間緊,還不敢大改你和B同事的代碼,只添不改,肯定不會影響你們的邏輯,很快整上了,開發(fā)過程中它的業(yè)務(wù)邏輯出現(xiàn)一個幺蛾子,整了一個特殊邏輯,比如又需要詳情按鈕,但是點(diǎn)擊詳情按鈕和你的邏輯完全不一樣,這時候,你覺得B同事會怎么做?在加一個public枚舉或者bool來區(qū)分你和他的邏輯啊。
之后CDE同事。。。他們只增加不修改源代碼,肯定沒有那么問題
?突然你來了來個需求,之前需求2.0版本,你是不是要哭,稍微大動點(diǎn)就要兼容她們的邏輯是不,想直接抽取出一個VC,讓他們繼承,但是幾個人開發(fā)任務(wù)也緊,都動也來不及,你怎么整尼。
工作教訓(xùn)告訴我們:當(dāng)public屬性多的時候,這里必是骯臟之地,也必會在不經(jīng)意造成不必要的BUG,代碼是種藝術(shù)需要被坑過無數(shù)次你才能明白,如果當(dāng)時的B就抽出來一個基本功能VC,還有后邊的坑嗎?如果你的APP超過2年絕對有此問題,當(dāng)APP初期都在趕業(yè)務(wù)的時候更明顯。找一個維護(hù)同一APP3年以上的架構(gòu)或者高級開發(fā)好處就在于他能提前避坑,保證你程序的健壯性,并且保證其擴(kuò)展性。
2.基于自適配的 復(fù)雜的UI界面引用contenView區(qū)分上(左)下(右)
不要把所有的view都直接加在backgroundView上,特別是一些和業(yè)務(wù)邏輯緊密相關(guān)的View,把其上subviews獨(dú)立出來,如果感覺delegate多,就使用block,可讀性極高!
另外就算改動一個subview,其適配只僅限于contenView的范圍內(nèi),影響小,維護(hù)成本低!
3.能用block解決的問題,不要單獨(dú)去通過delegate來中轉(zhuǎn),
想象一下 一個VC既有request的回調(diào),又有action回調(diào),還有第三方庫回調(diào),日積月累,雞毛一地!@weakify(self),@strongify(self)避免循環(huán)引用:__block。
4.UI開發(fā)中,創(chuàng)建view最好用getter/setter方法
簡單明了,可讀性高,代碼整潔,無論你看別人 ,別人看你都是爽心悅目!使用GCC Code Block Evaluation C Extension ({…})語法,結(jié)構(gòu)化局部變量初始化和處理的邏輯(如上圖)
5. one method do one thing(一個函數(shù)只做一件事)
工作實(shí)例:今天又踩了一個坑,什么樣的坑尼,原有的函數(shù)有兩個
-(BOOL)showGuide;//顯示引導(dǎo)圖(當(dāng)版本版本顯示一次) ?并且返回顯示結(jié)果
-(BOOL)showAD;//里邊的代碼其實(shí)顯示廣告圖,并返回顯示結(jié)果
第一次安裝肯定沒有廣告數(shù)據(jù),原有邏輯是:首先判斷是否有廣告數(shù)據(jù),如果沒有廣告數(shù)據(jù)顯示引導(dǎo)圖,如果有廣告數(shù)據(jù)則判斷是否此版本的第一次打開,如果第一次打開,依然顯示引導(dǎo)圖。這塊代碼已經(jīng)2年沒有動過,也沒有詳細(xì)產(chǎn)品文檔來說明這塊,目前出來一個BUG,如果版本升級,覆蓋安裝,上版本APP有緩存廣告數(shù)據(jù),這時候就出現(xiàn)先出廣告再出引導(dǎo)圖,體驗(yàn)有問題。
我就這么改的:
if(FirstLaunch){
[self showGuide]}
else{
[self showAD]}
結(jié)果踩上地雷了,因?yàn)槭裁茨幔?請求廣告的數(shù)據(jù)的邏輯放進(jìn)了showAD中,請求廣告的數(shù)據(jù)的策略是只要啟動,請求下次的廣告數(shù)據(jù)和廣告角標(biāo)。原有邏輯沒有問題是啟動就執(zhí)行[self showAD]返回當(dāng)前是不是有廣告數(shù)據(jù),所以再返回BOOL的同時去請求下次的廣告數(shù)據(jù),沒有問題,但是修改BUG后邏輯明確,但是缺造成了第一次啟動就不會請求廣告數(shù)據(jù),我的天啊,沒有廣告老板不殺了我,幸好發(fā)現(xiàn)的及時。
一方面是自己不細(xì)心,另一方面這得多坑人啊,你把showAD返回BOOL也就算了,你把請求的廣告的函數(shù)放入這個函數(shù),并且沒有任何的注釋說明,坑我的爽歪歪了。心有余悸!
保持健康的心態(tài),相信當(dāng)時同事可能想著開機(jī)廣告的邏輯都放一起,言歸正傳由此得到的教訓(xùn)是一個“功能”函數(shù)極可能的只做一件事(此處不要一偏概全,不是說viewDidLoad內(nèi)只放view加載,相關(guān)的統(tǒng)計就不能放入)。
自己親自拆分其中的函數(shù),把-(BOOL)showAD拆分成-(BOOL)checkShowAD,-(void)showAD,-(void)requestADData;