以前做個人項目的時候,簡歷上寫過重構(gòu)了三次,后來在扇貝面試的時候,面試官問三次分別重構(gòu)了什么,仔細想想那時候的重構(gòu)并不算重構(gòu),第一次是 UI 改版,但是項目結(jié)構(gòu)沒什么大的變化,第二次是整體遷移到了 CocoaPods,這次勉強能算重構(gòu),第三次僅僅是變量名方法名空行這些地方的風格統(tǒng)一而已。 在現(xiàn)在工作的地方,接手這些項目之后,主要工作做的是重構(gòu),而重構(gòu)工作,本來想寫成一行,結(jié)果發(fā)現(xiàn)挺多,我列個列表吧:
關(guān)于刪除代碼,在某個項目里,Pods 文件夾那些第三方庫的代碼刪了 9 萬多行(那個目錄沒有被 git ignore 掉),項目里面刪除了大約 4 萬行,其中大量代碼是該項目之前的項目里面留下來的東西,只不過沒人清理。在刪了 4 萬行之后,程序仍然能完整的跑。 接下來是做了部分重構(gòu),把一些第三方庫刪掉,自己造輪子,在這個過程中,累計刪除了 1.2 萬行代碼,增加了 1100 行左右。 整個重構(gòu)工作下來,編譯速度從 2-3 分鐘減小到了 40 多秒,warning 從 70 多減少到了 0,第三方庫的數(shù)量從 51 個減少到了 13 個,安裝包從 22.1M 減小到了 3.7M,功能反而比之前還要多。 內(nèi)存泄露方面,因為沒人在意這件事,有一個功能使用一次,就會增加好幾百 kb 內(nèi)存,那部分代碼是用 C 寫的,所以及時釋放內(nèi)存,并且優(yōu)化下調(diào)用方式,內(nèi)存泄露的問題就完美解決。 循環(huán)引用方面,是因為有人把 Xcode 的 warning 關(guān)了,后來打開的時候,發(fā)現(xiàn)了四個循環(huán)引用 + 幾十個 warning,并且測試過程中發(fā)現(xiàn)那個頁面不斷打開退出,程序會 crash。 籠統(tǒng)的就這么多,我再來分享幾個具體的點。 避免濫用單例單例用著確實爽,但是程序退出之前是不會被回收的,如果是整個生命周期基本用不到的模塊做成單例,那么只會浪費內(nèi)存而已。 避免無用的層級具體是什么意思呢,用網(wǎng)絡層舉例子,封裝 AFN 是一層,API 的后綴字符串放一層,構(gòu)造請求放一層,OAuth 授權(quán)放一層,發(fā)普通請求又是一層。增加一個 API,至少要修改 6 個文件。寫著也很痛苦,看著也很痛苦啊。 網(wǎng)絡層就只設計一層,封裝 AFN,發(fā)請求的函數(shù)也在里面,API 地址直接用字符串寫進去,搞那么多層沒實際意義,在這么小的一個項目里面。 除此之外,關(guān)于項目文件結(jié)構(gòu),一兩個文件的建議不要新建文件夾放進去,這個主要是個人習慣,其實無大礙。 合理設計方法名不留隱患
和
之前這樣設計的目的是 param 放 form data 類型數(shù)據(jù),object 放 json 格式,顯然不合理,同一個 API 不應該允許同時存在 form data 和 json,如果采用第一種,新來的同事可能會認為這兩個都可以填數(shù)據(jù),這是不符合我們期望的。 甚至再極端一點,某天我們需要傳文件過去,是不是還得再擴充字段。 如果采用第二種,param 是 id 類型,如果是 json,type 傳入 json 枚舉類型,如果是二進制,type 傳入二進制枚舉類型,只留一個字段暴露給開發(fā)者更合理。 避免耦合我們的項目中有一條漸變顏色的線要到處用到,這條線我們放在了 UIImage+XXUtil.h 里面,之前的設計是這樣的:
在 .m 的實現(xiàn)中,還把 UIColor+XXTheme 耦合進去了,并且這個方法已經(jīng)脫離了類名 Util 的實質(zhì),他已經(jīng)不是一個通用的工具了,重構(gòu)之后的命名是這樣的:
這樣就很符合 Util 這個 category 名字。 避免濫用繼承繼承確實很好用,帶來的后果就是子類會把父類的方法挨個執(zhí)行一遍,乍一看沒什么,但是如果這個方法很消耗性能呢。 我們這個項目就遇到了,app 經(jīng)??ㄋ溃弥弥?,就 freeze 了,點哪里都沒反應。因為所有頁面都繼承自基類的一個設計,恰好基類里面有一個比較耗時的操作,每個頁面都會執(zhí)行至少三次,就導致了頁面假死。 重構(gòu)后的做法是設計成一個 category,只是給 UIViewController 添加了幾個方法,按需調(diào)用,不需要在每個頁面都調(diào)用,于是解決了這個詭異的 bug。 合理選擇第三方庫如果有一個功能,迫于各種原因,不得不采用第三方庫,至少也要選一個 GitHub 上 star 比較多的吧,其次是看看 issue 列表有沒有什么很嚴重的 bug 沒修好,以及兼容性問題,多養(yǎng)成好習慣,慢慢就能篩選出來最合適的庫了。 避免濫用第三方庫我們的項目之前有用到 YYText 這個庫,就為了一段文字里面加一張圖片,活動當天 iOS9 設備出現(xiàn)好幾百次 crash,實際上這段代碼用 NSAttributedString attributedStringWithAttachment 寫一下,七行就夠了,七行替代掉一個不穩(wěn)定的第三方庫,還是很劃算的。 不知道因為什么原因,可能是更舊的項目里面用了 PSCollectionView,能跑就沒去重構(gòu),這類庫也是屬于完全沒必要的,系統(tǒng)自帶的足夠好用,并且更安全。 各司其職數(shù)據(jù)的處理,比如字符串進行 UTF8 編碼,時間戳轉(zhuǎn)成 YYYY-MM-DD 字符串,這些都放在 Model 層來處理,各司其職,Model 層就是做數(shù)據(jù)處理的。 結(jié)合實際需求后端把各種 ID 用 long 型來記錄,是因為他們要做索引,為了索引速度。而客戶端完全沒這個需求,直接用 string 就好,還不用擔心長度不夠的溢出,做展示的時候還不用轉(zhuǎn)類型。 同樣的,金額按理說應該用雙精度浮點型,因為 float 的精度不夠,結(jié)合我的開發(fā)經(jīng)驗看,金額很少要客戶端做加減,直接用 string 即可,需要計算的時候再轉(zhuǎn)換,只轉(zhuǎn)換一次,避免丟失精度。 關(guān)于命名規(guī)范蘋果的 UIKit 就是最好的例子,寫什么組件不知道名字怎么起的時候,就想想蘋果有沒有類似的組件,去找找靈感。 避免無意義的注釋OC 的方法名本身就很長很清晰了,只是給方法名中間加幾個空格,然后作為注釋,跟沒寫一樣吧。 不用的代碼刪掉Git 的作用就是隨時回溯以前版本,代碼都是能找到的,把代碼注釋掉,再寫一行類似的,除了增加閱讀成本,容易引起歧義,應該沒什么用了。一個文件一共一兩百行,打開之后發(fā)現(xiàn)七八十行代碼被注釋了,這種感覺相當操蛋,影響閱讀。 重構(gòu)祖?zhèn)鞔a真的會有一種活久見的感覺,上面提到的那些是印象比較深刻的,還有一些小問題已經(jīng)悄悄解決了,希望我寫的代碼不會讓后面的同學也這樣認為吧。 |
|