內容提綱:
- 樹立正確的職業觀
- 編碼與設計
- 編程價值觀
- 什么是好的代碼
- 代碼的壞味道
- 如何重構
一、樹立正確的職業觀
1)寫代碼這份工作,可以干多久?
問:是吃青春飯的玩意 答:我馬上就不編碼了,沒意思!
甲:你工作多久了? 乙:六年吧! 甲:靠,六年了,你還在寫代碼啊? 乙:汗。。。。。。
2)寫代碼的,就是軟件藍領?
甲:最近,混得怎么樣?聽說,你還在寫代碼啊? 乙:滾,你才在寫代碼呢,你全家都在寫代碼!
3)寫代碼的,路在何方?
- 不要被成為項目經理,不要被成為架構師
- 其實,我們可以一直在編碼!
二、編碼與設計
1)設計高於代碼?
甲(架構師):這個設計我已經全部完成了,你們編碼吧!這個星期完成! 乙們:大哥,一個星期搞不定啊! 甲:為什么? 乙們:這個設計,有點好像問題啊??按照你的設計,有很多細節,沒考慮到啊。 甲:細節?那是你們程序員的事情。我是做架構的! 乙們:無語了:cry::cry::cry:(再問就繼續被鄙視了)
2)最好的設計經常是在編碼階段產生的
編程前做設計這種思路是沒錯的 , 然而設計后不應該就認為該模型就是任務的最好設計 . 你會發現最好的設計是你在編碼階段 , 一步一步逐漸形成的 。
3)真正的牛人是怎么說的:
- 設計看做軟件開發的關鍵環節, 而把編程看做機械式的低級勞動 。設計就像畫工程圖紙而編碼就像施工 。但是這是錯誤的 !!!!! 軟件的可塑性更強 ,而且完全是思想產品。
- 一些項目中,設計也許可能會詳細到能夠讓編碼工作近乎機化,但很少有如此完整的設計 —— 程序員 ( 指編程 ) 通常也要部分程序進行設計,也許是正式的,也許不是。
- 有了設計 , 我可以編程更快 , 但其中充滿小漏洞 -Alistar Cockburn
- 什么是軟件設計? -- 代碼也是設計 © Jack W.Reeves , 1992
- 軟件系統源代碼是它的主要設計文檔 , 用來描述源代碼的圖示只是設計的附屬物而不是設計本身 . 你不應該認為設計就是一組和代碼分離的 UML 圖 .
三、 編程價值觀
1)評價標准的背后動機-----關注開發總成本
Costtotal=Costdevelop+Costmaintain
----Edward Yourdon&Larry L. Constantine
2)軟件系統維護工作量所占的比重超出想象!!!!!!!!
Costmaintain=Costunderstand+Costchange+Costtest+Costdeploy
Costmaintain>>Costdevelop
3)代碼要人能夠讀懂------Martion Fowler
任何一個傻瓜都能寫出機器能懂的代碼,好的程序員應該寫出人 能懂的代碼。
----Martin Fowler 《重構》
4)程序員要有這種意識------"寫爛代碼要遭報應!!!!!!!!!"
編程的時候,總是想着那個維護你代碼的人會是一個知道你住在 哪兒的有暴力傾向的精神病患者。
----Martin Golding
5)軟件代碼3項職責------Robert C Martin <敏捷軟件開發>
- 第1職責:運行起來所完成的功能,這是模塊存在的原因。
- 第2職責:要和閱讀它的人進行溝通,對模塊不熟悉的人員應該能夠比較容易理解。
- 第3職責:它要應對變化,因為軟件要變化,開發者保證應該盡可能的簡單。
6)價值觀是編程過程的統一支配性主題.有3個價值觀:
- 溝通:珍視與他人溝通的重要性
- 簡單:把多余的的復雜性去掉
- 靈活:保持開放,應對變化
——Kent Beck
7)整潔代碼------百家爭鳴
隨着年齡的增長,我逐漸意識到編程不僅僅是讓程序運行而已; 編程是創造一個易於理解的、可以維護的、高效的作品。一般來 說,干凈整潔的代碼,往往運行起來更快。這與流行觀點正好相 反。而且即使它們不快,也可以很容易地讓它們變快。正如人們 所說的,優化正確的代碼比改正優化過的代碼容易多了。
---- Google公司首席Java架構師Joshua Bloch
我喜歡優雅和高效的代碼。代碼邏輯應當直截了當,叫缺陷難 以隱藏;盡量減少依賴關系,使之便於維護;依據某種分層戰 略完善錯誤處理代碼;性能調至最優,省得引誘別人做沒規矩 的優化,搞出一堆混亂來。整潔的代碼只做好一件事。
----Bjarne Stroustrup, inventor of C++ and author of The C++
整潔的代碼簡單直接。整潔的代碼如同優美的散文。整潔的代 碼從不隱藏設計者的意圖,充滿了干凈利落的抽象和直截了當 的控制語句
----Grady Booch,Object Oriented Analysis and Design with Applications
p整潔的代碼應可由作者之外的開發者閱讀和增補。它應當有單 元測試和驗收測試。它使用有意義的命名。它只提供一種而非 多種做一件事的途徑。它只有盡量少的依賴關系,而且要明確 地定義和提供清晰、盡量少的API。代碼應通過其字面表達含 義,因為不同的語言導致並非所有必需信息均可通過代碼自身 清晰表達
----“老大”Dave Thomas,OTI公司創始人,Eclipse戰略教父
我可以列出我留意到的整潔代碼的所有特點,但其中有一條是根 本性的。整潔的代碼總是看起來像是某位特別在意它的人寫的。 幾乎沒有改進的余地。代碼作者什么都想到了,如果你企圖改進 它,總會回到原點,贊嘆某人留給你的代碼—全心投入的某人留 下的代碼。
----Michael Feathers,Working Effectively with Legacy Code
四、什么是好的代碼
1)為什么要寫好的代碼
幾種想法:
- 我馬上就離職了,反正,這塊代碼我不維護了
出來混遲早是要還的,你總有一天會維護到同樣的代碼
- 本來這個就不應該是我做的,我已經很疲憊了
軟件開發界的另外一個小秘密是:編寫優秀代碼和糟糕代碼所花費的時間是一樣多。一位訓練有素的工程師,他/她會從第一行代碼開始就考慮可維護性和代碼 的演化。沒有任何理由編寫“丑陋”的代碼、長達數頁的函數,或是稀奇古怪的變量名。
- 我就這水平,還不知道如何寫出好的代碼
看書、學習、多實戰
2)好代碼的重要性
- 降低維護成本
- 有助於程序員自身成長
- 有效促進團隊合作,加深小伙伴友誼
3)到底什么是好的代碼?
不壞的代碼就是好代碼-----這不是廢話
五、代碼的壞味道
第一級
- Duplicated Code(重復代碼)
- Long Method(過長函數)
- Large Class(過大類)
- Long Parameter List(過長參數)
- Comments(過多的注釋)
- Temporary Field(令人迷惑的暫時值域)
- Primitive Obsession(基本型別偏執狂)
- Switch Statements(Switch驚悚現身)
- Divergent Change(發散式變化)
- Shotgun Surgery(散彈式修改
第二級
- Data Clumps(數據泥團)
- Data Class(幼稚的數據類)
- Feature Envy(依戀情結)
- Refused Bequest(被拒絕的遺贈)
- Message Chains(過度耦合的消息鏈)
- Middle Man(中間轉手人)
- Inappropriate Intimacy(狎昵關系)
- Lazy Class(冗余類)
第三級
- Parallel Inheritance Hierarchies(平行繼承)
- Speculative Generality(理論上的一般性)
- Alternative Classes with Different Interfaces(異曲同工類)
- Incomplete Library Class(不完美的程序庫類)
六、如何重構
代碼的壞味道 | 一般重構方法 | 使用模式重構 |
---|---|---|
重復代碼 | 提煉方法 | 構造Template Method 以Composite取代一/多之分 引入Null Object 用Adapter統一接口 用Fatory Method引入多態創建 |
提取類 | ||
方法上移 | ||
替換算法 | ||
鏈構造方法 | ||
過長方法 | 提取方法 | 轉移聚集操作到Vistor 以Strategy取代條件邏輯 以Command取代條件調度程序 轉移聚集操作到Collecting Parameter |
組合方法 | ||
以查詢取代臨時變量 | ||
引入參數對象 | ||
保持對象完整 | ||
過長參數列 | 以方法取代參數 | |
引入參數對象 | ||
保持對象完整 | ||
條件邏輯過度復雜 | 分解條件式 | 以Strategy取代條件邏輯 轉移裝飾功能到Decorator 以State取代狀態改變條件語句 引入Null Object |
合並條件式 | ||
合並重復的條件片段 | ||
移除控制標記 | ||
以衛語句取代嵌套條件式 | ||
以多態取代條件式 | ||
引入斷言 | ||
分支語句 | 提取方法 | 以State/Strategy取代類型代碼 引入Null Object 以Command替換條件調度程序 轉移聚集操作到Visitor |
轉移方法 | ||
以子類取代類型代碼 | ||
以多態取代條件式 | ||
已明確方法取代參數 | ||
基本類型迷戀 程序代碼過於依賴基本類型(int,string,double,array等低層次語言要素) |
以對象取代數據值 | 以State取代狀態改變條件語句 以Strategy取代條件邏輯 以Composite取代隱含樹 以Interpreter取代隱式語言 轉移裝飾功能到Decorator 用Builder封裝Composite |
以類型取代類型代碼 | ||
以子類取代類型代碼 | ||
提取類 | ||
引入參數對象 | ||
以對象取代數組 | ||
數據泥團 在類的字段和參數列中,總是一起出現的數據 |
提取類 | |
引入參數對象 | ||
保持對象完整 | ||
令人迷惑的臨時字段 | 提取類 | 引入Null Object |
組合爆炸 許多段代碼使用不同種類或數量的數據 或對象做同樣的事情(例如使用特定條件和數據庫查詢) |
以Interpreter取代隱式語言 | |
過大類 | 提取類 | 以Command取代條件調度程序 以State取代狀態改變條件語句 以Interpreter取代隱式語言 |
提取子類 | ||
提取接口 | ||
復制被監視數據 | ||
冗贅類 不再做很多工作或沒有用的類 |
折疊繼承關系 | |
內聯Singleton | ||
不恰當的暴露 在客戶代碼中不應看到類的字段和方法,卻是公開可見的 |
封裝字段 | 用Factory封裝類 |
封裝群集 | ||
移除設置方法 | ||
隱藏方法 | ||
發散式變化 類經常因為不同的原因在不同方向上發生變化,顯然是違反了單一職責原則 |
提取類 | |
霰彈式修改 如果遇到變化,必須在不同的類中作出相應的修改 |
轉移方法 | 將創建知識搬移到Factory |
轉移字段 | ||
內聯類 | ||
依戀情結 方法對於某個類的興趣高過對自己所處的宿主類 |
轉移方法 | 引入Strategy 引入Visitor |
提取方法 | ||
平行繼承體系 當為一個類增加一個子類時,也必須在另一個類中增加一個相應的子類 |
轉移方法 | |
轉移字段 | ||
誇誇其談未來性 | 折疊繼承關系 | |
內聯類 | ||
移除參數 | ||
移除方法 | ||
過度耦合的消息連 不斷的向一個對象索求另一個對象 |
隱藏委托 | 使用抽象引入Chain Of Responsibility |
提取方法 | ||
轉移方法 | ||
中間轉手人 類之間彼此依賴於其private成員 |
移除中間轉手人 | |
內聯方法 | ||
以繼承取代委托 | ||
狎昵關系 類之間彼此依賴於其private成員 |
轉移方法 | |
將雙向關聯改為單向 | ||
提取類 | ||
隱藏委托 | ||
以繼承取代委托 | ||
異曲同工的類 | 重命名方法 | 用Adapter統一接口 |
轉移方法 | ||
提取超類 | ||
不完善的程序庫類 | 引入外加方法 | 用Adapter統一接口 用Facade封裝類 |
引入本地擴展 | ||
純稚的數據類 只擁有字段的數據類 |
封裝字段 | |
封裝集合 | ||
移除設置方法 | ||
轉移方法 | ||
隱藏方法 | ||
被拒絕的遺贈 繼承父類時,子類想要選擇繼承的成員 |
以委托取代繼承 | |
過多的注釋 為糟糕的代碼寫大量的注釋 |
使用一起重構方法,使方法本身達到自說明的效果,讓注釋顯得多余 | |
怪異解決方案 在同一系統中使用不同的方式解決同一問題 |
替換算法 | 用Adapter統一接口 |
介紹幾本好書:
- 《代碼整潔之道》----Robert C. Martin
- 《敏捷軟件開發:原則、模式與實踐》----Robert C. Martin
- 《代碼大全》 ----Steve McConnell
- 《重構——改善既有代碼的設計》 ----Martin Fowler