陳禹樵,隋 浩
(中移互聯網有限公司云產品事業部 廣東 廣州 510000)
截至2021年2月,全球約70.46%的手機和平板搭載了Android操作系統,在Google Play商店中,可以下載到的Android應用數量達到295萬個。為了獲得更多的用戶,Android應用開發市場面臨著激烈的競爭。許多企業和開發者為了快速實現功能,忽視了架構的設計,隨著版本的迭代,功能添加和修改,應用越做越復雜,開發和維護的效率降低,應用質量也出現下滑。為了提升代碼的質量,提高應用的運行效率,代碼重構成為開發者面臨的現實問題。本文從設計模式的角度出發,結合案例討論其在代碼重構過程中的應用。
重構是指在不改變軟件可觀察行為的前提下,對軟件內部結構進行修改,使得軟件更容易理解,更容易修改[1]。在軟件開發的迭代過程中,基于以下因素,代碼重構過程是必不可少的:(1)代碼架構設計的不足;(2)軟件功能的疊加和修改;(3)開發技術的發展和進步;(4)開發規范的執行和變化。人們不可能實現一份適配所有變化的系統,保證后續的需求都不偏離最初的設計。代碼重構是糾正這些偏離,實現架構進步的一種手段。
代碼重構的主要目的包括:(1)優化代碼結構,降低軟件結構的復雜性,使得代碼結構清晰,閱讀、維護和拓展簡單;(2)提升軟件運行的效率,通過重構簡化復雜的邏輯判斷、重復的執行過程、過時的方法架構,優化速度;(3)提高軟件的健壯性,解決軟件迭代過程中積累的潛在問題;(4)控制代碼規范,統一不同人員的代碼風格和習慣,適配行業和企業制定的規范等。
代碼重構的主要方法有:(1)不良代碼的識別與監測;(2)基于搜索的重構方法;(3)基于UML模型的重構方法;(4)基于代碼異味的重構方法;(5)基于測試驅動的重構方法;(6)自動化重構工具[2]。
代碼重構的時機選擇:(1)添加新功能時一并重構;(2)修補錯誤時一并重構;(3)代碼審查時進行重構;(4)代碼設計完全錯誤時,應當重寫;(5)重構工作應安排入主版本發布計劃,有序實施。
設計模式是指經過眾多的軟件開發人員在長期的開發工作中,總結出的解決軟件開發過程中面臨的一般性問題的模板化的設計方法。這些方法通常為了更簡單方便的改進或者復用以往成功的設計和體系機構,又能有效地處理需求的變更,某些模式可以減少類之間的耦合與依賴[3]。這些設計模式被軟件開發人員在后續的代碼設計過程中反復實踐和驗證。
Gamma等[4]于1995年出版的《設計模式:可復用面向對象軟件的基礎》一書中收錄了23種設計模式。這些設計模式在 Java、C++、Object-C、Kotlin等多種面向對象的編程語言都得到了實現,成為不同語言共用的模板方式。近年來,在解決復雜的軟件架構設計問題上,MVC、MVP、MVVM等設計模式在Android軟件開發過程中,也得到了廣泛的應用。
將設計模式思想應用于軟件重構中,可以解決提升代碼復用率,降低代碼耦合度,使得代碼結構更加清晰,進而提高代碼的可維護性,提高軟件健壯性、擴展性和規范化。
不同的設計模式面向解決不同場景下的設計問題。在軟件重構過程中,應當根據問題選擇最優的設計模式,保證重構效果。在Android應用開發和Android系統源碼中,常用的設計模式約有7~8種,這些設計模式有著不同的變體,但其基本思想是一致的。熟悉這些常用的設計模式,可以解決重構過程中的大部分問題。下面將結合具體問題,討論5種常用設計模式在代碼重構工作中的應用。
單例模式適合用于內存常駐、信息配置、公用方法或者全局管理等職責單一的任務。例如:Android應用經常會使用到設備信息,作為運行設備的唯一標識,對于設備信息的獲取和管理,在重構過程中可以構建DeviceInfo Manager單例對象,實現一次獲取,多次使用的目的。Android應用開發常會用到多線程技術,對于子線程和線程池的管理,可以在重構過程中構建Common Executor單例對象,統一管理子線程數量,管控子線程的運行、同步和結束。需要注意的是,在單例對象實例化時,需要注意線程同步問題,可采用雙重鎖的方式,避免異步線程產生空指針異常。單例模式不利于擴展,對象常常需要常駐內存,因此也不可濫用。
觀察者模式適用于消息通知和事件傳遞等場景,在Android源碼和一些優秀的Android開源框架中,例如:ListView、RecyclerView、RxJava、OKHttp等,有著廣泛的應用。近兩年發展的ViewModel、LiveData等框架也是由觀察者模式思想發展而來。在重構過程中,可以應用于以下場景,例如:Android應用常會用到推送功能,在與服務端交互的過程中,新消息的到達會導致數據和狀態的改變。此類場景的重構,可以用Observable定義消息數據的更新與處理,將視圖層定義為Observer,訂閱數據處理類,在數據處理后,通過Observer通知視圖的刷新,解耦數據與視圖代碼的耦合。
在開發過程中,經常會遇到這樣的場景:產品經理要求在某些行為函數前加入功能、日志或者數據統計。在不改變現有設計的情況下,代理模式是一種友好的選擇。代理模式可以控制對象的間接訪問,修飾和操作對象的輸入輸出。例如:對于數據訪問的權限判斷重構場景中,可以隱藏數據訪問類的visit方法,加入VisitorProxy類,在調用visit函數時,通過VisitorProxy類先調起權限判斷功能,根據其返回結果判斷是否繼續調用visit方法。這樣可以將權限判斷和數據訪問的代碼有效解耦,降低代碼混亂。
責任鏈模式的設計起源于工廠生產中的流水線思想,符合面向對象設計的單一職責原則。責任鏈模式的設計思路為:將一項任務分解成多個子任務步驟,對于子任務設計隔離開的接口和實現,再將子任務銜接成完整的任務流水。責任鏈模式在開源框架Glide、OKHttp、Gson中都得到了應用。例如:在郵箱應用中,新郵件數據的同步和顯示,該過程包括:新郵件通知→同步郵件頭→解析郵件頭→解析郵件結構→存儲郵件結構→刷新郵件列表→下載郵件正文→存儲郵件正文→下載郵件附件→存儲郵件附件,在重構過程中,可以選用責任鏈模式來實現。將以上過程抽象成Chain,每個階段的任務實現Chain中的process方法,并指定下一階段任務,依次傳遞,直到郵件同步和顯示任務處理完畢。
工廠模式可以歸為三類:簡單工廠模式、工廠方法模式和抽象工廠模式。簡單工廠模式通常以靜態代碼的形式,預先定義“工廠類”所能生成的“產品類”。工廠方法模式實現了對工廠角色的抽象,定義包含必須的工廠行為的接口類,在生產具體產品時,定義實現抽象工廠接口的具體工廠來實現,提高了對于產品生產行為的拓展性。抽象工廠模式,不僅工廠角色是抽象的,產品角色也是抽象的,適用于產品屬性未產生本質變化的生產行為。例如:對于圖像的處理工作的重構。圖像處理包括色調、飽和度、亮度、大小、旋轉等操作,這些行為可定義為抽象的Abstract Image Process Fatory,根據具體操作實現為Tone Process Fatory、Saturation Fatory、Brightness Fatory、Size Factory、Rotate Factory。其中Tone Process Fatory用于實例化具體的Abstract Tone Effect類。色調可能有暖色調、冷色調、懷舊效果等不同的需求,但其有著共同的抽象方法,可以定義繼承Abstract Tone Effect實現具體的處理邏輯。
關于Android應用重構過程中設計模式的選擇,應該充分考慮軟件設計和開發過程中可能會發生的潛在變化因素,考慮實現設計模式對軟件運行和架構產生的負擔,衡量應用該設計模式所帶來的價值與成本負擔。其基本過程如下:(1)理解任務需求,保證產品需求和功能表象不發生本質變化;(2)梳理現有代碼的基本框架,列出其需要重構的原因;(3)研究當前任務未來可能發生變化和添加的潛在需求;(4)匹配任務屬性及潛在需求與設計模式的匹配度;(5)衡量使用設計模式修改代碼的效率成本和時間成本;(6)安排分工,使用設計模式重構現有代碼;(7)將重構后的代碼使用在部分模塊,通過測試比較其于重構前的運行差異;(8)完善重構代碼的不足;(9)將重構后的代碼全量應用,移除舊代碼;(10)測試及上線。
隨著Android應用日益激烈的競爭,代碼重構成為了提高其軟件質量、可維護性、可復用性、保證軟件開發可持續發展的重要手段。本文從設計模式角度出發,探討了設計模式與代碼重構目的的一致性,以及其在Android代碼重構方面的應用。代碼重構和框架設計是彼此互補又相互聯系的環節,在軟件設計、開發及維護階段,都有必要借助科學合理的設計模式,以提升代碼的質量,進而加強應用的競爭力。