前段時間和一同事一起重構了兩個 APP,正好想寫一些重構心得,前天又在知乎上看到一前輩推薦《重構》這本書,據說是程序員的必讀書籍,于是就粗略的讀了一遍,對重構有了更深層次的認識了。這里結合 iOS 項目的重構,談談與重構相關的問題,做一下記錄及分享。
一、《重構》讀書筆記
1.1 重構的定義
- “重構”這個詞有兩種不同的定義:
- 第一個定義是名詞形式:
重構(名詞):對軟件內部結構的一種調整,目的是在不改變軟件可觀察行為的前提下,提高其可理解性,降低其修改成本。 - 第二個定義是動詞形式:
重構(動詞):使用一系列重構手法,在不改變軟件可觀察行為的前提下,調整其結構。
- 第一個定義是名詞形式:
重構的定義說明了兩點,第一,重構的目的是使軟件更容易被理解和修改;第二,重構不會改變軟件可觀察的行為——重構之后軟件功能一如既往。
1.2 為何重構?
-
重構可以幫你始終良好的控制自己的代碼,它可以用于以下幾個目的:
重構改進軟件設計
如果沒有重構,程序的設計會逐漸腐敗變質。當人們只為短期目的,或是在完全理解整體設計之前,就貿然修改代碼,程序將逐漸失去自己的結構,程序員越來越難通過閱讀源碼而理解原來的設計。
完成同一件事情,設計不良的程序往往需要更多代碼,這常常是因為代碼在不同的地方使用完全相同的語句做同樣的事情。因此改進設計的一個重要方向就是消除重復代碼。重構使軟件更容易理解
書的前面有這么一句話:“任何一個傻瓜都能寫出計算機可以理解的代碼,唯有寫出人類容易理解的代碼,才是優秀的程序員。”而重構可以使代碼結構更清晰,使代碼更容易被理解。重構幫助找到 bug
對代碼進行重構,可以深入理解代碼的作為,并恰到好處地把新的理解反饋回去,在重構的同時,我們可以發現某些代碼邏輯寫的不嚴謹或有問題。重構提高編程速度
良好設計師維持軟件開發速度的根本,重構可以幫你更快速地開發軟件,因為它阻止系統腐敗變質,它甚至還可以提高設計質量。
1.3 何時重構?
-
怎樣安排重構時間表?是不是應該每兩個月就專門安排兩個星期來進行重構呢?這里需要說明,重構不是一件應該特別撥出時間做的事情,重構應該隨時隨地進行。不應該為重構而重構,我們之所以重構,是因為想做別的事情,而重構可以幫助我們把那些事做好。
三次法則(事不過三,三則重構)
第一次做某件事時只管去做;第二次做類似的事情會產生反感,但還是可以去做;第三次再做類似的事情,就應該重構了。添加功能時重構
最常見的重構時機就是我們想給軟件添加新特性的時候,此時,重構的直接原因往往是為了幫助我們理解需要修改的代碼——這些代碼可能是別人寫的,也可能是自己寫的。修補錯誤時重構
調試過程中重構,多半是為了讓代碼更具有可讀性。復審代碼時重構
代碼復審對于編寫清晰代碼很重要,比如我的代碼也許對我自己來說很清晰,但對他人則不然,這是無法避免的,代碼復審會讓更多人有機會提出有用的建議,然后考慮是否可以通過重構來輕松的實現它們。
1.4 重構的基本技巧:
- 小步前進、頻繁測試
二、結合 iOS 項目重構心得
2.1 項目目錄結構
項目的目錄結構是開發中最基礎的,但也是很重要的,清晰的目錄結構能夠讓人一眼就看懂該項目的業務及功能,目錄結構也能反應一個開發者的經驗及架構水平。項目目錄結構比較常規的有兩種,第一種是按照業務分類,第二種是按照模塊分類。當然具體還得根據具體的業務需求來做,適合自己的才是最好的。
這里有一篇關于項目目錄結構的文章,有興趣的童鞋可以讀下:iOS 項目的目錄結構能看出你的開發經驗
2.2 業務與 UI
這里不討論 MVC 架構與 MVVM 架構,關于架構模式之間的爭論有很多,個人比較贊同一個觀點:不要局限于 MVC、MVVM、MVP 等等一些架構模式,萬變不離其宗,真正適用于項目的架構才是最好的架構。剛接手的舊項目在設計初期以及開發過程中,沒有進行合理的規劃,以至于一些控制器過于臃腫,代碼量很多都是超過了 1000 行,有的甚至超過了 1500 行,而且寫的很亂。重構的目的,就是提高代碼的可讀性以及便于以后的維護,我這里按照 MVC 的架構模式,將 UI 部分進行抽離,將工具代碼(比如計算球面兩點之間的距離)進行封裝,并放到了相關的工具類中,又對控制器中的冗余代碼進行了整理,使得控制器中的代碼減少至之前的三分之一以下。分享一張 cocoa 上的 MVC 架構圖:
2.3 代碼還是 xib、 storyboard?
寫 UI 界面用代碼還是用 xib 一直是 iOS 界的爭論,有的人傾向于使用代碼,有的人傾向于使用 xib,巧神之前在博客中也討論過這個問題,并給出了一些建議(個人比較贊同??):
- 對于復雜的、動態生成的界面,建議使用手工編寫界面。
- 對于需要統一風格的按鈕或 UI 控件,建議使用手工用代碼來構造。方便之后的修改和復用。
- 對于需要有繼承或組合關系的 UIView 類或 UIViewController 類,建議用代碼手工編寫界面。
- 對于那些簡單的、靜態的、非核心功能界面,可以考慮使用 xib 或 storyboard 來完成。
這里是巧神關于寫 UI 用代碼還是用 xib 的相關討論: iOS 開發中的爭議(二)
2.4 模塊化設計
什么是模塊化?比如我們剛開始碼代碼的時候,有一個經常用的方法(比如還是計算球面兩點之間的距離),由于這個方法經常用,我們會把這段代碼拿出來放到一個公共類里,以便實現代碼的復用,這就是簡單的模塊化。關于模塊化設計的原則,一位阿里大神的建議如下:
- 越底層的模塊,應該越穩定,越抽象,越具有高復用度。
- 不要讓穩定的模塊依賴不穩定的模塊, 減少依賴。
- 每個模塊只做好一件事情,不要讓 Common 出現(避免一大堆不相干的代碼放進一個模塊)。
- 按照架構的層數從上到下依賴,不要出現下層模塊依賴上層模塊的現象
業務模塊之間也盡量不要耦合。
對模塊化設計感興趣的童鞋可以看下這篇文章,絕對干貨!模塊化與解耦
2.5 代碼規范
關于代碼規范,每個程序員遵守的代碼規范多多少少都會有些不同(比如什么時候該空格,常量變量的命名方式等等),之前聽一前輩說過,盡量遵守那些“約定俗成”的代碼規范,另外在編碼時,要保證自己的代碼規范始終一致,別給人一種你寫的代碼是幾個人共寫的錯覺。
命名規范
iOS 命名主要注意兩個方面,第一是可讀性高,別人一看這個名字就知道它的含義及作用;第二是防止命名沖突,命名時應遵循駝峰式命名法則,另外要加前綴,比如常量命名一般會在前面加上字母 k。編碼規范
關于編碼規范有很多細節需要注意,比如函數方法一般不能過長;比如實例變量的修飾符要注意;再比如盡可能保證 .h 文件簡潔,API 盡量寫在實現文件里......編碼時還有其它一些應該注意的,比如寫 delegate 的時候類型應該為 weak,以避免循環引用;再比如經典的圓角問題,過多的使用 layer.masksToBounds 對系統的開銷非常大,會使頁面變的卡頓等等......這些編碼細節有很多需要注意,就不一一列舉了。寫注釋
寫注釋寫注釋寫注釋,重要的事情說三遍??。注釋可以幫助其他同事更好的理解你寫的代碼,還方便自己以后的閱讀。
代碼規范方面,這里也推薦一篇不錯的文章:iOS開發-代碼細節優化(長期更新)
再安利一本書,《編寫高質量 iOS 與 OS X 代碼的 52 個有效方法》,這本書對編碼時應注意的細節寫的很全面,之前讀過一遍,過幾天會再讀一遍,并記錄。