Android代碼重構實戰
本文是《誰都忍不了爛代碼,如何用重構的方式讓它整潔起來?》的實戰篇,在上文里,筆者從理論和實際案例的角度對重構進行了分析,包括為什麼需要重構、重構的作用、重構的時機、如何進行重構等內容,推薦提前閱讀。
接下來筆者將從實踐的角度去分享,即在平時開發 Android 工程中,我們如何高效去做重構,重構和開發怎麼比較好的有效結合起來。
Long Method 實戰
Long Method 是筆者前面提到的「代碼壞味道」之一,這也是開發者一般經常容易犯的典型錯誤。
接下來筆者介紹在 Android 平台中如何去解決這個「bad taste」,實際上我們可以通過計算函數的圈複雜度(cyclomatic complexity)來判斷函數是否過長, 一般 cyclomatic complexity > 11 , 就可以認為函數過長,需要進行重構優化,那麼關於函數重構的優化技巧在前面幾章我也有重點提到。
在解決圈複雜度過大這個問題,首先我們要去發現你的工程哪裡存在問題,這一步我們可以通過工具或者第三方插件幫我們去解決,比如打開 Android studio 工具欄 Analyze –> Run inspection by name, 如下圖 8 所:
圖 8 Analyze 工具示意圖
如圖 8 所示,選擇 Run inspection by name , 打開如下圖 9 所示界面:
圖 9 Overly long method 界面示意圖
如圖 9 所示,輸入 long 出現 Overly long method , 選擇如上圖所示,點擊會打開一個新的界面如圖 10 所示:
圖 10 Run 『Overly long method』
如圖 10 所示,可以選擇對當前工程,當前 File, 當前 Module 或者其他 Module 進行分析,等待運行一段時間分析結果如下圖 11 所示:
圖 11 Run 『Overly long method』 結果
得到圖 11 分析結果之後,我們就可以有針對性的去進行優化重構了,知道哪些類哪些函數需要去優化,具體重構優化是一般可以將過長的函數拆分成幾個不同的小函數,拆分原則:一個函數的功能要保持職責單一,查詢和修改職責分開;所以可以通過不同類型的功能業務邏輯處理或者查詢、修改功能去拆分大函數。
Too many parameters 實戰
函數參數過多,也是典型的「代碼壞味道」之一,同理打開如上圖 8 所示的界面,然後輸入 too many pa 關鍵字打開如下圖 12 所示的界面:
圖 12 Analyze too many pa 關鍵字界面
選擇圖中所示的 「Method with too many parameters」, 會出現如上圖 10 所示的界面,然後選擇「Whole Project」, 運行之後,分析得到的結果如下圖 13 所示:
圖 13 「Too many parameters」結果分析圖
Redundant local variable 實戰
冗餘的局部變數,同樣是造成代碼壞味道的源頭,輸入 「Redudant 關鍵字」,同理執行得出分析結果如下圖 14 所示,然後我們根據分析後的結果有針對性的去重構優化:
圖 14 冗餘局部變數分析結果
Unused Declaration –無用函數實戰
無用函數是「代碼壞味道」來源之一,很多函數因為歷史遺留的原因,需求已經下線了但是代碼還在遺留在工程裡面,或者因為重構,歷史遺留代碼沒有完全刪除或者想暫時留著下個版本使用,這些都是不好的習慣,不用的代碼應該立即刪除,而不應該保留在工程項目中。
同理打開如上圖 8 所示的界面,然後輸入 Unused declaration 關鍵字打開如下圖 15 所示的界面:
圖 15 Unused declaration
分析結果能得出你整個工程中沒有被使用的函數,我們都可以刪除掉。
無用函數參數 - 實戰
同理,輸入關鍵字 Unused method parameter, 如下圖 16 所示, 執行可以分析出工程中有哪些函數存在無用參數,可以針對性的進行優化。
圖 16 unused method parameter
infer 實戰
Infer 是 Facebook 開源的靜態代碼檢查工具,可檢查 Android 和 Java 代碼中的 NullPointException 和 資源泄露。除了以上,Infer 還可發現 iOS 和 C 代碼中的內存泄露,內存泄露,內存泄露。
Android studio 已經將 infer 集成到工具欄裡面,點擊 Analyze->infer Nullity, 執行分析得出的界面類似如下圖 17 所示:
圖 17 infer Nullity 分析結果圖
點擊圖 17 所示的分析結果具體項,可以定位到具體的代碼文件,然後我們去手動判斷 或者直接點擊「Infer Nullity Annotations」, 工具直接幫我去完成改造結果。
第三方插件與 Android studio 的集成
FindBugs 集成
FindBugs 是一個開源的靜態代碼分析工具,基於 LGPL 開源協議,無需運行工程就能對代碼進行分析的工具。它不注重 style 及 format,注重檢測真正的 bug 及潛在的性能問題 ,以 bytecode(*.class、*.jar)為對象進行檢查。除了單獨運行,還可以用作 Android-studio 和 Eclipse 的 Plug-in,以及嵌入 Ant 或者 Maven 作為 task 之一進行運行。
Findbugs 自帶 60 余種 Bad practice,80 余種 Correntness,1 種 Internationalization,12 種 Malicious code vulnerability,27 種 Multithreaded correntness,23 種 Performance,43 種 Dodgy。它可以檢測檢測 java programing 中容易陷入的 bug pattern,比如實現時的一般規約違反 Null pointer 的參照 ,Method 的返回值的 check 遺漏 ,初始化前 field 的訪問, Multi-thread 的正確性,無條件的 wait,Code 的脆弱性 ,可以變更的靜態 object ,內部數列參照的 return 等。
Android Studio 可以通過插件的方式安裝,具體是打開 Android Studio->Preference –>搜索 plugin 選擇 Plugins Tab , 打開界面如下圖 17 所示:
圖 17 搜索 FindBugs-IDEA 界面
如上圖 17 中,點擊 install ,downloading plugin install , 然後重啟 Android studio , 會有提示界面如下圖 18 所示:
圖 18 Android FindBugs Enable
點擊「Enable Android FindBugs」, 會打開界面,在見面中添加 Plugin For Android FindBugs 即可。
然後在 Android Studio 工具欄上,打開如下圖 19 所示的界面:
圖 19 FindBugs 入口界面
如上圖 19 所示,可以分析對前的文件,可以分析一個 Module files ,也可以分析一個工程文件,選擇一項會得出分析結果如下圖 20 所示:
圖 20 FindBugs 分析結果圖
根據圖 20 所示的結果,我們可以查看具體的 Bug details , 存在什麼問題,然後具體跟蹤到對應的代碼,根據對應的建議去修改。
MetricsReloaded 集成
MetricsReloaded 是一個計算代碼複雜度即圈複雜度的 Jetbrain 開源開發的第三方插件。關於代碼複雜度,有個維度的衡量,在這裡需要普及下軟體複雜度的相關知識:基本複雜度(Essential Complexity (ev(G))、模塊設計複雜度(Module Design Complexity (iv(G)))、Cyclomatic Complexity (v(G)) 圈複雜度。
ev(G) 基本複雜度是用來衡量程序非結構化程度的,非結構成分降低了程序的質量,增加了代碼的維護難度,使程序難於理解。因此,基本複雜度高意味著非結構化程度高,難以模塊化和維護。實際上,消除了一個錯誤有時會引起其他的錯誤。
Iv(G) 模塊設計複雜度是用來衡量模塊判定結構,即模塊和其他模塊的調用關係。軟體模塊設計複雜度高意味模塊耦合度高,這將導致模塊難於隔離、維護和復用。模塊設計複雜度是從模塊流程圖中移去那些不包含調用子模塊的判定和循環結構後得出的圈複雜度,因此模塊設計複雜度不能大於圈複雜度,通常是遠小於圈複雜度。
v(G) 是用來衡量一個模塊判定結構的複雜程度,數量上表現為獨立路徑的條數,即合理的預防錯誤所需測試的最少路徑條數,圈複雜度大說明程序代碼可能質量低且難於測試和維護,經驗表明,程序的可能錯誤和高的圈複雜度有著很大關係。
同理,如上圖 17 所示一樣去安裝 MetricsReloaded 插件,安裝成功後執行 Analyze->Calculate Metrics, 打開如下圖 21 所示的界面:
圖 21 Calculate Metrics 界面
如上圖所示,選擇 Complexity metrics, 執行分析結果如下圖 22 所示:
圖 22 Calculate Metrics 分析結果圖
如上圖 22 所示界面中的紅顏色部分,代表需要去重構優化的,點擊當前行,會定位到源代碼,然後我們針對性去優化函數。上圖中,可以分析出方法的圈複雜度、類的圈複雜度、包的圈複雜度、模塊的圈複雜度、工程的圈複雜度。
Sonar 集成
對於 Android(Java)工程,Sonar 官方提供了 Java Plugin 和 Java-specific Plugins,這些插件可以實現大部分 Findbugs、PMD、Checkstyle、Android Lint 等的檢查規則。主要可以從以下幾個方面檢測代碼質量:
(1)複雜度:項目中方法、類、文件的複雜度分布情況;
(2)重複:展示代碼中重複嚴重的地方;
(3)單元測試覆蓋率:統計並展示單元測試覆蓋率(主要用於 java 工程);
(4)代碼標準:通過 PMD、CheckStyle 等代碼規則檢測工具規範代碼編寫;
(5)代碼注釋:沒有注釋或者過多的注釋都不是一個良好的編程習慣;
(6)潛在的 bug: 通過 PMD、Findbugs 等代碼檢測工具檢測出潛在的 bug;
(7)架構設計:可以檢測耦合、依賴關係、架構規則、管理第三方的 jar 包等。
集成 Sonar 之後,我們需要著種解決的就是代碼重複率問題,這也是「代碼壞味道」最典型的問題,開發者最容易犯這個問題,特別是不少開發者喜歡偷懶,容易拷貝來拷貝去,造成工程代碼的重複率比較高。一次構建運行之後,我們可以得出分析結果,類似如下圖 23 所示:
圖 23 sonar 構建運行結果
點擊重複率,我們可以看出哪些文件之間的代碼是重複的,然後針對性使用抽取工具類、合并類、合并分解函數等技術重構手段去優化。
SonarLint 集成
前面我們所講到的 Sonar 之前的提供的本地工具是需要依賴 SonarQube 伺服器的,這樣導致其運行速度緩慢。 新出的 SonarLint 的掃描引擎直接安裝在本地,速度超快,實時探測代碼技術債務,給程序員最快速的反饋,排除代碼異味的絕佳利器,幫助程序員獲得 Clean code。 新版 SonarLint 也能鏈接 SonarQube 伺服器,但這並不必要。本地安裝 SonarLint 來做代碼本地掃描,本地發現本地修改,而且能快速看到修改結果,快速處理代碼臭味,有效控制技術債務。
按照如上圖 17 所示一樣去安裝 SonarLint 插件,安裝之後重啟 Android Studio , 即可動態掃描出結果如下圖 24 所示:
圖 24 SonarLint 掃描結果圖
重構技巧實戰 - 小結
本文我們講述了在 Android 程序開發過程中如何結合工具去幫助我們做重構優化的各種技能包括 Android Studio 自己已經集成的插件 Code Inspection 、infer Nullity 以及 FindBugs、MetricsReloaded、Sonar、SonarLint 等第三方插件工具,其實還有很多類似著名的插件比如 QAPlugin、PMD、Hammurapi 、Lint4j 等工具,大家可以自行嘗試使用,在這裡我不一一說明。
所謂工欲善其事必先利就是這個道理,我們如果需要去做重構優化,首先我們要知道我們做的不好的地方 - 代碼的壞味道在哪裡,這種工作如果靠人為手動的去發現,那麼效率和產出將會及其低下,所以我們需要藉助於集成插件工具幫我們自動去掃描發現問題,然後再去針對性的重構優化,產出 Clean code 。
活動推薦:
推薦一個不可錯過的會議:ArchSummit全球架構師峰會,邀請了上百位國內外頂尖技術專家前來分享各業務的核心架構設計,從Web協議底層優化到超級App的系列魔改,這裡只談最優秀的架構實踐。


TAG:移動開發前線 |
※Canon Medical 將人工智慧用於CT掃描的重構
※Mozilla推出Pathfinder,為AR/VR重構圖像文本渲染,解決顆粒鋸齒效果
※Facebook 正式公開 React Native 重構細節!
※FashionET:重構區塊鏈版的Insragram
※Python之父考慮使用 PEG Parser 重構Python解釋器
※趣圖:用 Python 重構 PHP 代碼
※Python之父考慮重構Python解釋器
※FB大規模重構React Native,Airbnb宣布回歸原生,前端巨變來臨?
※MAD? x adidas膠囊系列: 手織重構機能風
※React Native重構路線圖發布!
※微軟正重構Windows組件以支持下一代產品
※Nat Commun:新技術幫助實現大腦三維重構
※利用Capsule重構過程,Hinton等人實現對抗樣本的自動檢測
※KEGGgraph:根據kgml 文件從pathway中重構出基因互作網路
※簡化鞋面再度重構!低幫版本 Air Jordan 33 即將發售!
※GitHub 改版,重構頁面移除了 jQuery?
※把雜誌「演」出來!一票難求的《Pop-Up Magazine》 用多媒體表演形式重構「閱讀」體驗
※重構傳統金融基礎設施:火幣Prime4期為什麼是De-fi?
※做 Python 代碼重構,竟發現這些「潛規則」!
※讓IT變為業務的支撐者 Ivanti的重構與創新