最近跟一個朋友聊到關於App架構的問題, 其中就聊到一個App, 開發了很長時間, 一開始沒有去想框架的事兒, 迭代過程中, 由於時間緊, 任務重, 人員更替等原因, 也沒能保證代碼質量, 很多設計原則被拋之腦後, 代碼質量逐步下降, 以致難於閱讀, 難於維護. 進而導致迭代困難, 而形成惡性循環.
從而引申出如何重構App代碼的話題, 談點個人理解:
什麼情況下需要重構
1, 結構錯亂
代碼無法分出層次, 無法分清業務線.
各個業務模塊間/層次間的代碼互相夾雜.
由於多人協作導致的多種架構(MVP/MVVM/MVC等)並存.
規範性問題, 導致各個模塊內的代碼形式互相不一致, 風格迥異.
2, 可讀性差
超長函數, 超大類
代碼的格式不規範或不一致.
冗餘代碼, 無用代碼, 重複代碼.
過於高明, 使用一些不常用的小技巧而且沒有相關注釋.
濫用繼承, 接口實現等, 導致難以跟蹤.
3, 不能很好的適應產品的發展
維護困難, 前一發動全身.
不具備擴展靈活性, 無法很快引入系統版本更新時新特性.
不具備可變更性, 產品添加新功能或修改需求時需要修改大量的代碼.
重構的目標
重構的目的就是要提高代碼質量, 而高質量的代碼指標個人認爲有如下幾點, 當然其實也是老生常談的幾點.
排名分先後:
1, 可讀性
規範一致性.
結構, 層次明瞭.
命名有含義, 註釋要清晰.
邏輯簡短, 沒有長篇大幅的代碼塊.
方法提取, 類繼承關係合理.
不濫用設計模式.
聰明是可讀性的敵人.
2, 可維護性
杜絕魔鬼數字/字符串/尺寸值/顏色值等
代碼複用, 以便維護.
不寫死, 預測可能的變化(但不要提前設計).
3, 可擴展性
良好的分層結構, MVx模式運用.
通過一些設計模式的使用來提高可擴展性.
開閉原則: 修改關閉, 擴展開放.
如何重構
首先讓我們重溫下”重構“的含義:
<<重構 — 改善既有代碼的設計>> 這本大神作品強烈建議大家翻閱下~ 裏面對重構的定義, 以及如何從一個個小的Bad Smell開始重構等都有詳細的描述.
那麼作爲一個進行已久的Android工程, 我們應該如何重構呢?
其實這是一個對症下藥的問題, 針對爲什麼要重構提出的幾個代碼問題, 重構也可以分成以下幾步:
1, 架構選擇, 結構調整
根據App的業務場景(展示型, 交互型, 後臺工具型…)選擇合適的架構.
並不是說一定要選用一個架構, 比如說後臺工具型的App, 可能界面不多, 也服務器的交互也少, 基本是由Service組成, 可能直接用Android原生的結構就可以.
界面較多, 且與服務器交互較多的建議選用MVP架構. 可以通過P來做數據處理, 將數據源M與展示層V解耦, 便於替換數據源或是改變UI.
根據選用的架構以及業務模塊分包
2, 技術/開源庫選定
ListView/RecyclerView的選擇, Fragment/Activity的選擇等.
根據業務特點和選擇的架構, 選用相關技術/開源庫支持或對當前使用的進行整理.
例如HTTP請求庫, 緩存庫, 圖片加載庫等等.
3, 確定規範
制定編碼規範, 可以根據Google推薦的Java編碼規範, 適當定製.例如我的項目中的基本規範.
制定代碼提交規範, git flow管理流程規範等.
4, 自底而上, 由小至大
從底部開始, 也就是常說的Model層,數據層開始, 因爲這部分相對獨立, 可以通過提供接口與UI層隔離.
不要一下就大面積重構, 需要逐個小的case進行重構驗證, 保證當前運行.
5, 持續重構, 伴隨測試
持續進行小的重構, 每次重構需要伴隨測試, 保證重構結果.
提取方法, 去除重複代碼.
結構調整.
融入面向對象/接口編程思想, 注意SOLID原則.
多用組合, 少用繼承
……
最好有單元測試支持.
6, 重構而非重寫
不到萬不得已不要想重寫.
重寫會產生各種意想不到的問題, 諸如設計過度, 對於當前代碼把握不夠(例如現在看起來很不友好的代碼可能就是爲了解決一個架構無法解決的問題等).
附–關於架構重構的規則
寫完此文, 偶然機會在InfoQ上看到Uber的技術主管Raffi Krikorian在 O’Reilly Software Architecture conference上談及的關於架構重構的12條規則, 共勉之: