寫得不好的代碼有各種各樣的問題,會給讀者帶來不好的閱讀體驗,並且如果代碼寫得不夠好,文檔和代碼不一致,注釋和代碼不一致,那么對維護人員來說,理解代碼和進入項目組都是有困難的。如果代碼寫得不夠好,就需要擴展功能,修改Bug時所需要花費的時間也較長。自表達代碼是一種採用接近於自然語言的方式書寫代碼的主張。代碼可讀性、可擴展性、可測試性是關聯代碼質量的重要參考指標。本書從各個角度來分析產生劣質代碼的原因,並從代碼的命名、注釋、風格、結構、架構等方面著手,對提高設計能力、熟悉開發環境、了解程式語言、提高英語能力等諸多方面提出了具體的改善建議。
基本介紹
- 書名:會說話的代碼:書寫自表達代碼之道
- 出版社:電子工業出版社
- 頁數:188頁
- 開本:16
- 品牌:電子工業出版社
- 作者:王洪亮
- 出版日期:2013年8月1日
- 語種:簡體中文
- ISBN:7121208768
基本介紹,內容簡介,作者簡介,圖書目錄,序言,
基本介紹
內容簡介
《會說話的代碼:書寫自表達代碼之道》從各個角度來分析產生劣質代碼的原因,並從代碼的命名、注釋、風格、結構、架構等方面著手,對提高設計能力、熟悉開發環境、了解程式語言、提高英語能力等諸多方面提出了具體的改善建議。
作者簡介
王洪亮 從事軟體開發工作12年,有豐富的架構設計經驗和項目管理經驗,熟知英語和日語,熟悉多種平台的開發。曾在多家國際化企業工作。致力於代碼可讀性、可擴展性、可變性、可測試性方面的研究。是敏捷開發的支持者和實踐者,曾作為敏捷開發獨立諮詢師為多家企業服務,幫助企業建立相關的開發團隊,並為其改進工作方式。也對測試驅動開發、演進式設計有一定經驗實踐。
圖書目錄
第1章劣質代碼帶來的劣質體驗1
1.1代碼的可讀性問題1
1.1.1命名類問題2
1.1.2注釋類問題6
1.1.3風格類問題8
1.1.4結構類問題11
1.1.5架構類問題18
1.2代碼的可測試性問題22
1.3代碼的可維護性問題22
1.3.1需求變更難以應對23
1.3.2糾纏不清的Bug23
第2章劣質代碼是怎么產生的25
2.1理論知識匱乏25
2.2對程式語言不熟悉29
2.3對開發環境不熟悉31
2.4對設計方法不了解32
2.5編程習慣不佳32
2.6英語能力不足35
2.7管理人員誤導36
第3章自表達代碼39
第4章理論知識的補充41
4.1面向對象的基礎知識41
4.1.1封裝41
4.1.2繼承42
4.1.3多態44
4.2設計的基本原則45
4.2.1單一職責原則45
4.2.2開放封閉原則46
4.2.3里氏代換原則48
4.2.4接口分離原則48
4.2.5依賴倒置原則49
4.2.6迪米特法則50
4.2.7不要重複你自己51
4.3圈複雜度52
第5章編程環境的熟悉53
5.1保存動作與自動格式化53
5.2快速修復58
5.2.1缺少類59
5.2.2缺少方法60
5.2.3缺少變數61
5.2.4類型不匹配62
5.3重構63
5.3.1改名64
5.3.2改變方法簽名68
5.3.3提取方法69
5.3.4移動73
5.3.5引入參數對象76
5.3.6引入接口77
5.3.7向上提取78
5.3.8提取常量81
5.3.9局部變數變為域變數82
5.3.10引入工廠82
5.4自動完成83
5.5大綱84
5.6Eclipse快捷鍵86
第6章程式語言的學習88
6.1註解88
6.2異常94
6.3反射97
6.4泛型100
第7章設計方法的學習101
7.1設計模式101
7.2依賴注入102
7.3Map的妙用103
7.4採用位掩碼減少類的個數107
7.5List處理Z—Order110
第8章英文能力的提升113
8.1詞性113
8.2時態115
8.3語法116
8.4否定詞117
8.5成對詞119
8.6近義詞120
8.7前綴、擴展名120
8.8縮寫122
8.9正確用詞122
第9章編程習慣的改進124
9.1命名方面的改進124
9.1.1命名的基本原則124
9.1.2包的命名125
9.1.3接口的命名125
9.1.4類的命名125
9.1.5註解的命名126
9.1.6枚舉的命名126
9.1.7方法的命名127
9.1.8變數129
9.1.9常量的命名130
9.1.10相似的命名130
9.2注釋方面的改進131
9.2.1JavaDoc131
9.2.2TODO、FIXME和XXX132
9.2.3其他注釋133
9.2.4方法的注釋133
9.2.5類的注釋133
9.2.6著作權聲明134
9.3風格方面的改進135
9.3.1縮進與對齊135
9.3.2空格與空行138
9.3.3行長與換行140
9.4結構方面的改進140
9.4.1縮短長判定140
9.4.2縮短長分支144
9.4.3減少參數個數148
9.4.4減少嵌套的層數150
9.4.5去掉重複代碼152
9.4.6分離曖昧關係155
9.4.7多維度變化156
9.4.8縮短長方法158
9.4.9正則表達式158
9.4.10自相似對象160
9.4.11同質化處理161
9.5架構方面的改進162
9.5.1MVC162
9.5.2包含關係164
9.5.3繼承關係164
9.5.4包的劃分165
9.5.5內部類、內部接口及內部枚舉166
9.5.6匿名類167
9.5.7有限取值範圍168
第10章測試代碼的自表達改進174
10.1測試代碼的可讀性175
10.2測試代碼的可維護性179
10.3測試代碼的可擴展性179
10.4測試語法180
第11章Lambda表達式182
11.1filter183
11.2for Each183
11.3find Any與find First184
11.4sorted184
11.5unique Elements185
附錄186
1.1代碼的可讀性問題1
1.1.1命名類問題2
1.1.2注釋類問題6
1.1.3風格類問題8
1.1.4結構類問題11
1.1.5架構類問題18
1.2代碼的可測試性問題22
1.3代碼的可維護性問題22
1.3.1需求變更難以應對23
1.3.2糾纏不清的Bug23
第2章劣質代碼是怎么產生的25
2.1理論知識匱乏25
2.2對程式語言不熟悉29
2.3對開發環境不熟悉31
2.4對設計方法不了解32
2.5編程習慣不佳32
2.6英語能力不足35
2.7管理人員誤導36
第3章自表達代碼39
第4章理論知識的補充41
4.1面向對象的基礎知識41
4.1.1封裝41
4.1.2繼承42
4.1.3多態44
4.2設計的基本原則45
4.2.1單一職責原則45
4.2.2開放封閉原則46
4.2.3里氏代換原則48
4.2.4接口分離原則48
4.2.5依賴倒置原則49
4.2.6迪米特法則50
4.2.7不要重複你自己51
4.3圈複雜度52
第5章編程環境的熟悉53
5.1保存動作與自動格式化53
5.2快速修復58
5.2.1缺少類59
5.2.2缺少方法60
5.2.3缺少變數61
5.2.4類型不匹配62
5.3重構63
5.3.1改名64
5.3.2改變方法簽名68
5.3.3提取方法69
5.3.4移動73
5.3.5引入參數對象76
5.3.6引入接口77
5.3.7向上提取78
5.3.8提取常量81
5.3.9局部變數變為域變數82
5.3.10引入工廠82
5.4自動完成83
5.5大綱84
5.6Eclipse快捷鍵86
第6章程式語言的學習88
6.1註解88
6.2異常94
6.3反射97
6.4泛型100
第7章設計方法的學習101
7.1設計模式101
7.2依賴注入102
7.3Map的妙用103
7.4採用位掩碼減少類的個數107
7.5List處理Z—Order110
第8章英文能力的提升113
8.1詞性113
8.2時態115
8.3語法116
8.4否定詞117
8.5成對詞119
8.6近義詞120
8.7前綴、擴展名120
8.8縮寫122
8.9正確用詞122
第9章編程習慣的改進124
9.1命名方面的改進124
9.1.1命名的基本原則124
9.1.2包的命名125
9.1.3接口的命名125
9.1.4類的命名125
9.1.5註解的命名126
9.1.6枚舉的命名126
9.1.7方法的命名127
9.1.8變數129
9.1.9常量的命名130
9.1.10相似的命名130
9.2注釋方面的改進131
9.2.1JavaDoc131
9.2.2TODO、FIXME和XXX132
9.2.3其他注釋133
9.2.4方法的注釋133
9.2.5類的注釋133
9.2.6著作權聲明134
9.3風格方面的改進135
9.3.1縮進與對齊135
9.3.2空格與空行138
9.3.3行長與換行140
9.4結構方面的改進140
9.4.1縮短長判定140
9.4.2縮短長分支144
9.4.3減少參數個數148
9.4.4減少嵌套的層數150
9.4.5去掉重複代碼152
9.4.6分離曖昧關係155
9.4.7多維度變化156
9.4.8縮短長方法158
9.4.9正則表達式158
9.4.10自相似對象160
9.4.11同質化處理161
9.5架構方面的改進162
9.5.1MVC162
9.5.2包含關係164
9.5.3繼承關係164
9.5.4包的劃分165
9.5.5內部類、內部接口及內部枚舉166
9.5.6匿名類167
9.5.7有限取值範圍168
第10章測試代碼的自表達改進174
10.1測試代碼的可讀性175
10.2測試代碼的可維護性179
10.3測試代碼的可擴展性179
10.4測試語法180
第11章Lambda表達式182
11.1filter183
11.2for Each183
11.3find Any與find First184
11.4sorted184
11.5unique Elements185
附錄186
序言
自表達代碼的由來
我們曾經閱讀過很多閱讀體驗很糟糕的代碼,其中有滑鼠滾輪測試程式(指長檔案、長方法)、腦筋急轉彎程式(指邏輯判定複雜、關係混亂)、記憶力測驗程式(指一大堆變數或者常量)、眼神測驗程式(指命名類似,但意思不一樣)、邏輯思維測試程式(指循環引用式包含關係),等等。這些劣質代碼給我們帶來各種各樣的劣質閱讀體驗。
我們也曾經苦於一個偶然出現的Bug再也無法重現,好不容易重現,卻發現其必要步驟達三十多步,重現以後卻找不到問題的根本原因,也無從下手解決,鋪天蓋地地插入了幾十條log語句後終於能夠定位Bug的原因,卻又不敢動手修改。十分小心地分析,慢慢地修改,改掉這個Bug之後卻發現它又引起了新的Bug。
需求變更可能是令程式設計師最頭疼的事情之一了,它引起了一個新的流程,需要分析、修改和測試。更困難的還在於,如果這個需求實現了,另外一個已經完成的功能必須被破壞掉,而用戶卻想魚和熊掌兼得。
當新進入一個既有的開發項目時,常常面臨代碼和設計文檔不一致、代碼和注釋不一致、代碼結構混亂、代碼風格不統一等問題,不得不花大量的時間來學習。面對體積龐大有效信息卻很少的代碼庫是一件痛苦的事情,讓人產生一種要推翻重寫的衝動。可是開發時項目經理卻總是在催促:時間很緊,放棄文檔,放棄注釋。
到底是什麼問題導致這些痛苦的體驗?為什麼會產生這些痛苦的體驗?如何才能避免這些痛苦的體驗?本書第1章以這個為切入點,從代碼的可讀性、可測試性和可擴展性三方面入手,對劣質代碼產生的原因進行分析,分別從命名、注釋、風格、結構、架構五方面進行總結,並依次提出相應的改進方案。
“自表達代碼”(Self-Expressive Code)這一名詞為筆者原創。在此之前,曾經出現過“自文檔代碼”(Self-Documenting Code)和“自描述代碼”(Self-Describing Code)。筆者認為“自表達代碼”比後面二者更具表現力。根據“代碼是軟體的唯一文檔”這一理論,代碼應該是能夠自我表達的,是能夠讓讀者看到代碼就知道軟體是做什麼工作的,這就是自表達代碼一詞的由來。如其名字,讓代碼能夠自我表達的書寫方式就是自表達代碼。書寫自表達代碼的方式應該像書寫文章一樣。如果代碼書寫出來後都像文章一樣讀起來朗朗上口,那么對代碼的理解將不必再依靠繁雜的注釋和厚厚的文檔,代碼本身就可以表明其作用。而維護人員也不必擔心代碼和文檔或者注釋不一致這個問題了。
比較糟糕的代碼的寫法如:
scene.fight(hero, enemy, Kongfu.FIST);都不知道誰打了誰。
普通方式書寫的代碼如:
hero.fight(enemy, Kongfu.FIST);知道代碼的意思,但是閱讀體驗還不夠好。
而自表達的方式書寫的代碼如:
hero.fight(enemy).with(“FIST”);如果不看那些符號,讀起來這就是一句話。
本書第3章對如何採用接近自然語言的方式書寫代碼進行了詳細闡述,並推出“自表達代碼”概念。
看到條件就是if,看到循環就是for,這樣“直抒胸臆”的代碼堆砌起來,相互影響,使代碼的複雜度變得很大。然而,形成這一問題的原因是由於缺乏理論知識,代碼書寫者並不了解代碼的複雜度應該如何表征,耦合度應該如何降低。本書第4章就一些面向對象常用的理論知識進行講解,以幫助程式設計師初步掌握這些理論知識。
當看到不少有經驗的程式設計師也在用連續按方向鍵的方式對游標進行定位時,我深感對集成開發環境的不熟悉也是代碼質量低劣的原因之一。對於一個提升到主選單地位的Refactor選單熟視無睹的程式設計師不乏其人。而利用Outline快速定位代碼,利用Debugger工具、Task List管理技術債務等方法也是這些人同時存在的盲點。因此,本書第5章以Eclipse為例,專門就一些常用的對編程幫助很大的集成開發環境功能進行講解。
Java 8就快推出了,然而很多程式設計師還被限制在只能使用Java 1.4的條件下,至於中間的若干個版本有什麼新特性,程式設計師根本就沒能了解。當程式設計師看到採用新特性書寫的更為簡練的代碼時,會不明白、不理解,而自己又寫不出,因此錯過了很多可以改進代碼的機會。本書第6章就一些Java 1.5以後推出的新特性進行講解,並對其中的一些使用技巧進行闡述,以幫助讀者更好地理解這些新特性。
以往的代碼類書籍都來自美國,可能由於使用英語對於美國人不算是什麼問題,在這些書中很少提到英語這一話題。但是在亞洲一些國家,英語可能是程式設計師的一個重大障礙。由於單詞量不夠、語法不明確、詞性不會用等原因造成很多代碼書寫上的問題,也帶來了很多閱讀上的苦惱。其實,書寫代碼時所需要的英語並不是多么高深,並不需要IELTS成績達到某個分數線,只要掌握一些基本英語技巧,就可以使代碼變得更加易讀好懂。本書第8章從正確用詞、詞性、語法、時態等多個角度對英語進行淺析,以幫助程式設計師更好地命名。並且本書也給出了一個可用的關於前綴、後綴、成對詞、近義詞等的列表,成為書寫自表達代碼技巧的有益補充。
書寫代碼不是一種體力勞動,而是一種腦力勞動。把書寫代碼當成體力勞動就難以確保程式設計師的水平提升,也難以確保軟體的質量可靠,更逞論代碼的可讀性、可測試性乃至可擴展性。書寫代碼也不僅是個技術工作,更是一個藝術工作,在代碼的書寫過程中需要不斷地調整和修飾,不是把代碼寫得簡練些就夠了。代碼應該能夠讓讀者快速閱讀,能夠很容易地進行測試,很容易地進行擴展。本書第9章就如何培養良好的編程習慣進行講解。
形上學的規章制度並不能夠促成高質量代碼的書寫,編碼的規範也應該與時俱進,管理者也應該隨時拋棄那些陳舊的做法和規則。任何一個好方法的套用都離不開管理者的支持。本書就劣質代碼產生的管理層面原因進行了分析和總結。但是如何提升管理水平是個龐大的話題,由於它不是本書的主要討論話題,所以本書對此部分割愛。
作為下一代語言的特性,Lambda表達式已經被加入到若干高級程式語言中去了。但是Java還沒有加入Lambda表達式,Java 8已經聲明要加入Lamda表達式了,本書第11章通過對Java 8的前瞻版進行體驗,以了解Java中Lambda表達式的特性。
願本書能夠為讀者帶來有益的幫助。
王洪亮
2013年4月
於北京
我們曾經閱讀過很多閱讀體驗很糟糕的代碼,其中有滑鼠滾輪測試程式(指長檔案、長方法)、腦筋急轉彎程式(指邏輯判定複雜、關係混亂)、記憶力測驗程式(指一大堆變數或者常量)、眼神測驗程式(指命名類似,但意思不一樣)、邏輯思維測試程式(指循環引用式包含關係),等等。這些劣質代碼給我們帶來各種各樣的劣質閱讀體驗。
我們也曾經苦於一個偶然出現的Bug再也無法重現,好不容易重現,卻發現其必要步驟達三十多步,重現以後卻找不到問題的根本原因,也無從下手解決,鋪天蓋地地插入了幾十條log語句後終於能夠定位Bug的原因,卻又不敢動手修改。十分小心地分析,慢慢地修改,改掉這個Bug之後卻發現它又引起了新的Bug。
需求變更可能是令程式設計師最頭疼的事情之一了,它引起了一個新的流程,需要分析、修改和測試。更困難的還在於,如果這個需求實現了,另外一個已經完成的功能必須被破壞掉,而用戶卻想魚和熊掌兼得。
當新進入一個既有的開發項目時,常常面臨代碼和設計文檔不一致、代碼和注釋不一致、代碼結構混亂、代碼風格不統一等問題,不得不花大量的時間來學習。面對體積龐大有效信息卻很少的代碼庫是一件痛苦的事情,讓人產生一種要推翻重寫的衝動。可是開發時項目經理卻總是在催促:時間很緊,放棄文檔,放棄注釋。
到底是什麼問題導致這些痛苦的體驗?為什麼會產生這些痛苦的體驗?如何才能避免這些痛苦的體驗?本書第1章以這個為切入點,從代碼的可讀性、可測試性和可擴展性三方面入手,對劣質代碼產生的原因進行分析,分別從命名、注釋、風格、結構、架構五方面進行總結,並依次提出相應的改進方案。
“自表達代碼”(Self-Expressive Code)這一名詞為筆者原創。在此之前,曾經出現過“自文檔代碼”(Self-Documenting Code)和“自描述代碼”(Self-Describing Code)。筆者認為“自表達代碼”比後面二者更具表現力。根據“代碼是軟體的唯一文檔”這一理論,代碼應該是能夠自我表達的,是能夠讓讀者看到代碼就知道軟體是做什麼工作的,這就是自表達代碼一詞的由來。如其名字,讓代碼能夠自我表達的書寫方式就是自表達代碼。書寫自表達代碼的方式應該像書寫文章一樣。如果代碼書寫出來後都像文章一樣讀起來朗朗上口,那么對代碼的理解將不必再依靠繁雜的注釋和厚厚的文檔,代碼本身就可以表明其作用。而維護人員也不必擔心代碼和文檔或者注釋不一致這個問題了。
比較糟糕的代碼的寫法如:
scene.fight(hero, enemy, Kongfu.FIST);都不知道誰打了誰。
普通方式書寫的代碼如:
hero.fight(enemy, Kongfu.FIST);知道代碼的意思,但是閱讀體驗還不夠好。
而自表達的方式書寫的代碼如:
hero.fight(enemy).with(“FIST”);如果不看那些符號,讀起來這就是一句話。
本書第3章對如何採用接近自然語言的方式書寫代碼進行了詳細闡述,並推出“自表達代碼”概念。
看到條件就是if,看到循環就是for,這樣“直抒胸臆”的代碼堆砌起來,相互影響,使代碼的複雜度變得很大。然而,形成這一問題的原因是由於缺乏理論知識,代碼書寫者並不了解代碼的複雜度應該如何表征,耦合度應該如何降低。本書第4章就一些面向對象常用的理論知識進行講解,以幫助程式設計師初步掌握這些理論知識。
當看到不少有經驗的程式設計師也在用連續按方向鍵的方式對游標進行定位時,我深感對集成開發環境的不熟悉也是代碼質量低劣的原因之一。對於一個提升到主選單地位的Refactor選單熟視無睹的程式設計師不乏其人。而利用Outline快速定位代碼,利用Debugger工具、Task List管理技術債務等方法也是這些人同時存在的盲點。因此,本書第5章以Eclipse為例,專門就一些常用的對編程幫助很大的集成開發環境功能進行講解。
Java 8就快推出了,然而很多程式設計師還被限制在只能使用Java 1.4的條件下,至於中間的若干個版本有什麼新特性,程式設計師根本就沒能了解。當程式設計師看到採用新特性書寫的更為簡練的代碼時,會不明白、不理解,而自己又寫不出,因此錯過了很多可以改進代碼的機會。本書第6章就一些Java 1.5以後推出的新特性進行講解,並對其中的一些使用技巧進行闡述,以幫助讀者更好地理解這些新特性。
以往的代碼類書籍都來自美國,可能由於使用英語對於美國人不算是什麼問題,在這些書中很少提到英語這一話題。但是在亞洲一些國家,英語可能是程式設計師的一個重大障礙。由於單詞量不夠、語法不明確、詞性不會用等原因造成很多代碼書寫上的問題,也帶來了很多閱讀上的苦惱。其實,書寫代碼時所需要的英語並不是多么高深,並不需要IELTS成績達到某個分數線,只要掌握一些基本英語技巧,就可以使代碼變得更加易讀好懂。本書第8章從正確用詞、詞性、語法、時態等多個角度對英語進行淺析,以幫助程式設計師更好地命名。並且本書也給出了一個可用的關於前綴、後綴、成對詞、近義詞等的列表,成為書寫自表達代碼技巧的有益補充。
書寫代碼不是一種體力勞動,而是一種腦力勞動。把書寫代碼當成體力勞動就難以確保程式設計師的水平提升,也難以確保軟體的質量可靠,更逞論代碼的可讀性、可測試性乃至可擴展性。書寫代碼也不僅是個技術工作,更是一個藝術工作,在代碼的書寫過程中需要不斷地調整和修飾,不是把代碼寫得簡練些就夠了。代碼應該能夠讓讀者快速閱讀,能夠很容易地進行測試,很容易地進行擴展。本書第9章就如何培養良好的編程習慣進行講解。
形上學的規章制度並不能夠促成高質量代碼的書寫,編碼的規範也應該與時俱進,管理者也應該隨時拋棄那些陳舊的做法和規則。任何一個好方法的套用都離不開管理者的支持。本書就劣質代碼產生的管理層面原因進行了分析和總結。但是如何提升管理水平是個龐大的話題,由於它不是本書的主要討論話題,所以本書對此部分割愛。
作為下一代語言的特性,Lambda表達式已經被加入到若干高級程式語言中去了。但是Java還沒有加入Lambda表達式,Java 8已經聲明要加入Lamda表達式了,本書第11章通過對Java 8的前瞻版進行體驗,以了解Java中Lambda表達式的特性。
願本書能夠為讀者帶來有益的幫助。
王洪亮
2013年4月
於北京