您好,登錄后才能下訂單哦!
代碼質量和產出是衡量一個程序員是否優秀最直接的標準。如何提高代碼質量和產出?這就要從軟件重構和review入手。市面上有很多關于重構和review的書籍,但是看完之后,代碼能力并不能立竿見影顯著提升,只能幫助我們解決表面的bug和規范點,無法幫助我們發現更深層次的設計問題。
從設計角度來考慮review,識別代碼壞味道可以可以有效減少技術債務。技術債務是指有意或無意的做出錯誤的或非最優的設計決策所引發的債務。債務越積越多,最后只能重新徹底重構項目才能解決問題,這也叫做技術破產。如何解決技術債務問題,就要從根源上明確引起技術債務的重要的原因——設計壞味和重構認識不足。
抽象原則:通過精簡和概括來簡化實體:精簡指的是刪除不必要的細節,概括是找出并定義重要的通用特征。
非循環依賴原則:包之間的關系不可形成循環。
不自我重復原則:在詳細設計中,設計實體和代碼和重復可能表現為類型名重復和實現重復。
封裝原則:通過隱藏抽象的實現細節和隱藏變化等方法實現關注點分離和信息隱藏。
信息隱藏原則:找出棘手或可能變化的設計決策,并創建合適的模塊或類型來對其他模塊或類型隱藏這些決策。
保持簡單原則:簡潔是軟件系統設計的重要目標,應避免引入不必要的復雜性。
里氏替換原則:所有的子類型都必須至少提供超類型承諾的行為且對每個超類型的引用都可替換成子類型實例。
層次接口原則:使用分類、概括、替換、排序等方法以層次方式組織對抽象。
模塊化原則:通過集中和分解等手法創建高內聚、低耦合的抽象。
開閉原則:類型應對擴展開放,對修改關閉。具體是模塊應該能夠在不修改代碼情況下支持新需求。
單一職責原則:絕不應有多個導致類需要修改的原因,如修改一個成員可能影響類的其他不相關職責,導致類難以維護。
變化封裝原則:倡導一種信息隱藏方式,建議將可能發生變化的概念封裝起來。很多設計模式都體現了這種設計原則,如策略模式、橋梁模式、觀察者模式。
我們從設計的角度來看代碼時,要遵循六要素:
了解完設計原則和六要素后,我們再來看設計壞味。
本文中每種壞味我們只選其中一例做具體說明。
抽象原則倡導通過精簡和概括來簡化實體:精簡指的是刪除不必要的細節,而概括指的是找出并定義通過的重要特征。交通標志是用于交流的抽象示例,而數字符號和編程語言是用于解決問題的抽象示例。
使用一系列數據或者編碼字符串,而不創建類或者接口時會產生這種壞味
概念
應用抽象原則的一種實現手法是創建概念邊界清晰,身份唯一的實體。由于沒有創建抽象來表示實體,而是使用基本數據類型或編碼字符串等原始數據來表示它,這違反了抽象原則,將這種壞味稱為缺失抽象(Missing Abstraction)。不必要的抽象也違反了模塊化原則。
潛在原因
未做重復的設計分析
未重構
錯誤的將重點放在細微的性能改善上
示例
在JDK1.0中方法printStackTrace()以字符串的方式將棧跟蹤打印到標準錯誤流。
在需要以編程方式訪問棧跟蹤元素的客戶程序中,必須要編程代碼來獲取數據,如行號等,由于客戶程度依賴這種字符串格式,JDK設計人員只能在后續版本中兼容這種格式了。
重構建議:從Jdk1.4起對JAVA的API進行了改進,StackTraceElement類就是原來設計中缺失的對象。
別名
基本類型偏執:使用基本類型對日期、金額進行編碼,而不創建類時,將引發這種壞味。
數據泥團:在很多地方同事使用一系列數據項,而不創建類時,將引發這種壞味。
現實考慮
避免過度設計:有時候,實體只是數據元素,沒有任何相關聯的行為。這種情況下使用類或者接口來表示它們可能導致過度設計。
封裝原則倡導通過隱藏抽象的實現細節和隱藏變化等手法實現關注的分離和信息隱藏。比如開車必須知道發動機原理嗎?
對于抽象的一個或多個成員,聲明的訪問權限超過了實際需求時,將導致這種壞味。例如,將字段聲明為公有的類就存在「不充分封裝」壞味。
概念
封裝的原則是將接口和實現分離,以便能獨立修改。這種關注點分離,讓客戶程序只依賴抽象的接口,而對它們隱藏具體實現。修改實現不影響客戶程序。對抽象的內部隱藏的不充分稱為不充分的封裝(Deficient Encapsulation)。
潛在原因
為方便測試
在面向對象中采用過程思維
快速交付
示例
來看看java.lang.System,in、out、err都被聲明成final,但可以通過java.lang.System的setIn、setOut、setErr分別賦值。任何代碼都能很方便的使用它們,比如System.out.println();
PrintStream是java 1.0就有的,只支持8位的ASCII值,Java1.1出的PrintWriter支持Unicode,然而就是因為應用程序都能直接使用PrintStream來訪問PrintStream的方法,根本不能摒棄PrintStream類。
重構建議:Java 1.6引入了java.io.Console類,他提供了用于訪問基于字符的控制臺的方法。reader()、writer()來獲取Console相關的Writer和Reader對象。
別名
可隱藏的公有屬性、方法
未封裝的類
包含未參數化方法的類
現實考慮
嵌套或匿名類中過于寬松的訪問性
性能考慮:比如前面說的java.lang.System
模塊化原則倡導利用集中和分解等手法創建高內聚、低耦合的抽象。
應集中放在一個抽象中的數據和方法分散在多個抽象中時,將導致這種壞味。表現為類被用作數據容器沒有任何方法、類的方法更多的被其他類的成員調用。
概念
一種重要的模塊化實現手法是「將相關的數據和方法集中在一起」。如果抽象中只包含數據成員,而操作這些數據成員的方法位于其他抽象中,它就違反了這種實現手法,存在「拆散的模塊化」壞味。稱為拆散的模塊化(Broken Modularization)。
潛在原因
以過程思維使用面向對象語言
不熟悉既有設計
重構建議
對于包含大量數據類的過程型設計,可采用重構手法“將過程型設計轉換為對象”。
別名
被動地存儲數據的類
數據類
數據記錄
記錄類
數據容器
錯位的操作
依戀情結
錯位的控制
現實考慮
自動生成的代碼
數據傳輸對象
層次型壞味
層次結構原則倡導采用分類、歸并、替換和排序等手法以層次方式組織抽象。比如地球上的870萬種生物。
代碼片段使用條件邏輯來顯式管理行為變化,而原本可以創建一個層次目錄,并使用它來封裝這些變化,會產生這種壞味
概念
基于類型碼的switch語句(或串接的if-else語句)是最著名的設計壞味之一。
使用類型碼來處理行為變化表明沒有進行有意義的分類,導致設計中缺少相應的層次結構。稱為缺失層次結構(Missing Hierarchy)。
潛在原因
錯誤的采用過于簡單的設計
過程型設計思維
忽視了繼承也是一種設計手法
示例
串接的if else語句顯示的檢查類型AbstractButton,JToolBar和JTextCompont并在各種條件下調用方法getMargin(),這種造成的情況是將來可能在代碼中的其他地方也會出現。
重構建議
如果條件檢查中的多個實現調用方法相同,可引入相關的接口來抽象共同的協議。
如果代碼中包含可轉換為類的條件語句,可采用重構手法“提取層次結構”來創建一個類層次結構,其中每個類都表示條件檢查中的一種情形。
別名
標記類
繼承缺位
緊縮的類型層次結構
內嵌功能
現實考慮
與外部交互
——————————————————分割線——————————————————
我是小微,專注微服務技術分享,致力挖掘更多“高、精、全”的微服務知識分享給大家。
我的微信:weiweiweiblack (備注:51CTO )
微信公號:黑少微服務,“分享技術,熱愛生活”,歡迎關注
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。