《程式師修煉之道》之所以在全球範圍內廣泛傳播,被一代代開發者奉為圭臬,蓋因它可以創造出真正的價值:或編寫出更好的軟體,或探究出程式設計的本質,而所有收穫均不依賴於特定語言、框架和方法。
時隔20年的新版,經過全面的重新選材、組織和編寫,覆蓋哲學、方法、工具、設計、解耦、併發、重構、需求、團隊等務實話題的最佳實踐及重大陷阱,以及易於改造、複用的架構技術。
本書極具洞察力與趣味性,適合從初學者到架構師的各階層讀者潛心研讀或增廣見聞。
目錄
序 XVII
新版前言 XXI
第一版前言 XV
提示1:關注你的技藝 XVII
如果你不關心怎麼做好,為什麼還要花時間去開發軟體呢?
提示2:思考!思考你的工作 XVII
關掉輔助駕駛,由自己掌控,持續不斷地評估所做的工作。
第1章 務實的哲學 1
1 人生是你的 2
提示3:你有權選擇 3
人生是自己的。把握住人生,讓它如你所願。
2 我的源碼被貓吃了 3
提示4:提供選擇,別找藉口 5
提供選擇而不是去找理由。不要只說做不到;解釋一下都能做些什麼。
3 軟體的熵 6
提示5:不要放任破窗 7
只要看到不好的設計、錯誤的決策、糟糕的代碼,就趕緊去糾正。
4 石頭做的湯和煮熟的青蛙 9
提示6:做推動變革的催化劑 10
你無法強迫人們去改變,但可以展示美好未來,並幫助他們參與創造。
提示7:牢記全景 10
不要過度沉浸於細枝末節,以免察覺不到周圍正在發生的事情。
5 夠好即可的軟體 11
提示8:將品質要求視為需求問題 12
讓用戶參與對專案真實品質需求的確定。
6 知識組合 14
提示9:對知識組合做定期投資 16
養成學習的習慣。
提示10:批判性地分析你讀到和聽到的東西 18
不要受供應商、媒體炒作或教條的影響,根據自身和專案的實際情況來分析資訊。
7 交流! 20
提示11:英語就是另一門程式設計語言 20
將英語視作一門程式設計語言。寫文檔和程式設計一樣要遵循 DRY 原則、ETC、自動化等。
提示12:說什麼和怎麼說同樣重要 23
如果無法有效交流,任何偉大的想法都是沒有意義的。
提示13:把文檔嵌進去,而不要栓在表面 24
與代碼隔離的文檔,很難保持正確並及時更新。
第2章 務實的方法 27
8 優秀設計的精髓 28
提示14:優秀的設計比糟糕的設計更容易變更 28
適合使用者的事物,都已經過良好設計。對代碼來說,這意味著必須適應變化。
9 DRY——邪惡的重複 30
提示15:DRY——不要重複自己 31
系統中的每一條知識,都必須有單一且無歧義的權威陳述。
提示16:讓複用變得更容易 39
只要複用方便,人們就會去做。創建一個支持複用的環境。
10 正交性 40
提示17:消除不相關事物之間的影響 41
設計的元件,需要自成一體、獨立自主,有單一的清晰定義的意圖。
11 可逆性 48
提示18:不設最終決定 50
不要把決定刻在石頭上,而要將其視為寫在沙灘上的東西,時刻準備應變。
提示19:放棄追逐時尚 50
尼爾·福特說過:“昨日之最佳實踐,即明日之反模式。”要基於基本原則去選擇架構,而不應盲從於流行。
12 曳光彈 51
提示20:使用曳光彈找到目標 53
通過不斷嘗試並看清著彈點,曳光彈可確保你最終擊中目標。
13 原型與便簽 57
提示21:用原型學習 58
製作原型旨在學習經驗,其價值不在於過程中產生的代碼,而在於得到的教訓。
14 領域語言 60
提示22:靠近問題域程式設計 61
用問題領域的語言來做設計和程式設計。
15 估算 67
提示23:通過估算來避免意外 67
開始之前做估算,能提前發現潛在問題。
提示24:根據代碼不斷反覆運算進度表 72
利用實施過程中獲得的經驗來精細化項目的時間尺度。
第3章 基礎工具 74
16 純文字的威力 75
提示25:將知識用純文字保存 76
純文字不會過時。它能夠讓你的工作事半功倍,並能簡化調試和測試工作。
17 Shell遊戲 79
提示26:發揮 Shell 命令的威力 80
當圖形化介面無法勝任時,使用 Shell。
18 加強編輯能力 82
提示27:遊刃有餘地使用編輯器 82
既然編輯器是至關重要的工具,不妨瞭解一下如何用它更快更準確地實現需求。
19 版本控制 85
提示28:永遠使用版本控制 87
版本控制為你的工作創造了一個時間機器,可以用它重返過去。
20 調試 90
提示29:去解決問題,而不是責備 91
Bug 到底來自你的失誤還是別人的失誤真的不重要——它終究是你的問題,需要你來修復。
提示30:不要恐慌 91
不管是對銀河系搭車客,還是對開發者來說,都應這樣。
提示31:修代碼前先讓代碼在測試中失敗 93
在你修 Bug 前,先創建一個聚焦於該 Bug 的測試。
提示32:讀一下那些該死的出錯資訊 93
大多數異常都能告訴失敗之物與失敗之處。如果足夠幸運,你甚至能得到具體的參數值。
提示33:“select”沒出問題 97
在作業系統或編譯器中發現 Bug 非常罕見,甚至在協力廠商產品或庫中也是如此。Bug 大多出現在應用程式中。
提示34:不要假設,要證明 97
在真實環境中證實你的假設——要依賴真實的資料及邊界條件。
21 文本處理 99
提示35:學習一門文本處理語言 99
既然每天都要花大量的時間與文本打交道,何不讓電腦幫你分擔一二?
22 工程日記 101
第4章 務實的偏執 103
提示36:你無法寫出完美的軟體 103
軟體不可能是完美的。對於在所難免的錯誤,要保護代碼和用戶免受其影響。
23 契約式設計 104
提示37:通過契約進行設計 107
代碼是否不多不少剛好完成它宣稱要做的事情,可以使用契約加以校驗和文檔化。
24 死掉的程式不會說謊 113
提示38:儘早崩潰 114
徹底死掉的程式通常比有缺陷的程式造成的損害要小。
25 斷言式程式設計 115
提示39:使用斷言去預防不可能的事情 115
如果一件事情不可能發生,那麼就用斷言來確保其的確不會發生。斷言在校驗你的假設,要使用斷言在不確定的世界中將你的代碼保護起來。
26 如何保持資源的平衡 119
提示40:有始有終 119
只要有可能,對資源進行分配的函數或物件就有責任去釋放該資源。
提示41:在局部行動 122
將易變的變數維持在一個範圍內,打開資源的過程要短暫且明顯可見。
27 不要衝出前燈範圍 127
提示42:小步前進——由始至終 127
永遠小步前進,不斷檢查回饋,並且在推進前先做調整。
提示43:避免占卜 129
只在你能看到的範圍內做計畫。
第5章 寧彎不折 130
28 解耦 131
提示44:解耦代碼讓改變更容易 132
耦合使事物緊緊綁定在一起,以至於很難只改變其中之一。
提示45:只管命令不要詢問 133
不要從物件中取出值,在加以變換後再塞回去,讓物件自己來完成這些工作。
提示46:不要鏈式調用方法 135
當訪問某事物時,使用的點號不要超過一個。
提示47:避免全域資料 137
最好給每個方法增加一個額外的參數。
提示48:如果全域唯一非常重要,那麼將它包裝到API 中 137
……但是,僅限於你真的非常希望它是全域的。
29 在現實世界中拋球雜耍 139
30 變換式程式設計 149
提示49:程式設計講的是代碼,而程式談的是資料 151
所有的程式都在變換資料——將輸入轉換為輸出。開始用變換式方法來設計吧!
提示50:不要囤積狀態,傳遞下去 156
不要把資料保持在函數或模組的內部,拿出來傳遞下去。
31 繼承稅 162
提示51:不要付繼承稅 165
考慮一下能更好滿足需求的替代方案,比如介面、委託或mixin。
提示52:儘量用介面來表達多態 167
無需繼承引入的耦合,介面就能明確描述多態性。
提示53:用委託提供服務:“有一個”勝過“是一個” 167
不要從服務中繼承,應該包含服務。
提示54:利用 mixin 共用功能 169
mixin 不必承擔繼承稅就可以給類添加功能,而與介面結合可以讓多態不再令人痛苦。
32 配置 170
提示55:使用外部配置參數化應用程式 170
如果代碼對一些在應用程式發佈後還有可能改變的值有所依賴,那麼就在應用外部維護這些值。
第6章 併發 174
33 打破時域耦合 175
提示56:通過分析工作流來提高併發性 176
利用用戶工作流中的併發性。
34 共用狀態是不正確的狀態 179
提示57:共用狀態是不正確的狀態 180
共用狀態會帶來無窮的麻煩,而且往往只有重啟才能解決。
提示58:隨機故障通常是併發問題 186
或許時間和上下文的變化能暴露併發Bug,但併發Bug無法始終保持一致,也很難重現。
35 角色與進程 187
提示59:用角色實現併發性時不必共用狀態 188
使用角色來管理併發狀態,可以避免顯式的同步。
36 黑板 193
提示60:使用黑板來協調工作流 195
使用黑板來協調不相關的事實和代理人,能同時保持參與者之間的獨立性和孤立性。
第7章 當你編碼時 198
37 聽從蜥蜴腦 199
提示61:傾聽你內心的蜥蜴 201
當程式設計舉步維艱時,其實是潛意識在告訴你有什麼地方不對勁。
38 巧合式程式設計 204
提示62:不要依賴巧合程式設計 207
只能依賴可靠的事物。注意偶然事件的複雜性,不要混淆快樂的巧合與有目的的計畫。
39 演算法速度 210
提示63:評估演算法的級別 214
在開始程式設計前,對這件事情大概會花多長時間要有概念。
提示64:對估算做測試 214
針對演算法的數學分析無法說明所有問題,嘗試在目標環境中測試一下執行代碼的耗時。
40 重構 216
提示65:儘早重構,經常重構 219
像除草和翻整花園那樣,只要有需要就對代碼進行重新編寫、修訂和架構,以便找到問題的根源並加以修復。
41 為編碼測試 220
提示66:測試與找 Bug 無關 221
測試是觀察代碼的一個視角,可以從中得到針對設計、介面和耦合度的回饋。
提示67:測試是代碼的第一個用戶 222
用測試的回饋來引導工作。
提示68:既非自上而下,也不自下而上,基於端對端構建 225
創建一小塊端到端的功能,從中獲悉問題之所在。
提示69:為測試做設計 228
寫下代碼之前先從測試角度思考。
提示70:要對軟體做測試,否則只能留給用戶去做 230
無情地測試,不要等用戶來幫你找 Bug。
42 基於特性測試 231
提示71:使用基於特性的測試來校驗假設 231
基於特性的測試將會進行你從未想過的嘗試,並會以你不曾打算採用的方式操練你的代碼。
43 出門在外注意安全 238
提示72:保持代碼簡潔,讓攻擊面最小 241
複雜的代碼給 Bug 以滋生之沃土,給攻擊者以可趁之機。
提示73:儘早打上安全補丁 243
攻擊者會盡可能快地部署攻擊,你必須快上加快。
44 事物命名 245
提示74:好好取名;需要時更名 249
用名字向讀者表達你的意圖,並且在意圖改變時及時更名。
第8章 專案啟動之前 251
45 需求之坑 252
提示75:無人確切知道自己想要什麼 252
他們或許知道大概的方向,但不會瞭解過程的曲折。
提示76:程式師幫助人們理解他們想要什麼 253
軟體發展更像是一種由用戶和程式師協同創造的行為。
提示77:需求是從回饋迴圈中學到的 254
理解需求需要探索和回饋,因此決策的結果可以用來完善最初的想法。
提示78:和用戶一起工作以便從用戶角度思考 255
這是看透系統將如何被真正使用的最佳方法。
提示79:策略即中繼資料 256
不要將策略硬編碼進系統,而應該將其表達為系統的一組中繼資料。
提示80:使用專案術語表 259
為專案的所有特定詞彙創建一張術語表,並且在單一源頭維護。
46 處理無法解決的難題 260
提示81:不要跳出框框思考——找到框框 261
在面對無法解決的難題時,識別出真正的約束。可以問自己:“必須這樣做才能搞定嗎?必須搞定它嗎?”
47 攜手共建 264
提示82:不要一個人埋頭鑽進代碼中 267
程式設計往往困難又費力,找個朋友和你一起幹。
提示83:敏捷不是一個名詞;敏捷有關你如何做事 267
敏捷是一個形容詞,有關如何做事情。
48 敏捷的本質 267
第9章 務實的項目 271
49 務實的團隊 272
提示84:維持小而穩定的團隊 272
團隊應保持穩定、小巧,團隊中的每個人都應相互信任、互相依賴。
提示85:排上日程以待其成 274
如果你不把事情納入日程表,它們就不會發生。反思、實驗、學習、提高技能,這些事都應放入日程表。
提示86:組織全功能的團隊 276
圍繞功能而不是工作職能組織團隊。不要將 UI/UX 設計者從程式師中分離出去,也不要分開前端和後端;不要區分資料建模者和測試人員,以及開發和設計。構建一個團隊,這樣你就可以漸進地不斷反覆運算端到端的代碼。
50 椰子派不上用場 277
提示87:做能起作用的事,別趕時髦 279
不要僅僅因為別的公司正在那麼幹就採納一項技術或採用一個開發方法,而是要採用自己所處環境中對團隊有效的東西。
提示88:在使用者需要時交付 281
不要卡著流程要求,刻意等到幾周甚至幾個月後才交付。
51 務實的入門套件 281
提示89:使用版本控制來驅動構建、測試和發佈 282
利用提交或推送來觸發構建、測試、發佈,利用版本控制的標籤來進行生產部署。
提示90:儘早測試,經常測試,自動測試 283
每次構建都跑一下的測試,要比束之高閣的測試計畫有效得多。
提示91:直到所有的測試都已運行,編碼才算完成 283
無須多言。
提示92:使用破壞者檢測你的測試 285
在一個單獨的源碼副本中特意引入 Bug,驗證測試能否將其捕獲。
提示93:測試狀態覆蓋率,而非代碼覆蓋率 286
要識別並測試重要的程式狀態,只測試一行行的代碼是不夠的。
提示94:每個 Bug 只找一次 286
只要人類測試者找到一個 Bug ,就應該是該 Bug 最後一次被人類發現。從此之後,自動化測試完全可以發現它。
提示95:不要使用手動程式 287
電腦能一次又一次,按照同樣的次序,執行相同的指令。
52 取悅用戶 288
提示96:取悅用戶,而不要只是交付代碼 289
為用戶開發能夠帶來商業價值的解決方案,並讓他們每天都感到愉快。
提示97:在作品上簽名 290
過去的工匠在為他們的作品簽名時非常自豪,你也應該這樣。
53 傲慢與偏見 290
跋 292
提示98:先勿傷害 293
犯錯在所難免,確保犯錯後沒人會因此受難。
提示99:不要助紂為虐 294
因為這樣做你也有變成紂王的風險。
參考文獻 295
練習的參考答案 297
譯者跋 312
新版前言 XXI
第一版前言 XV
提示1:關注你的技藝 XVII
如果你不關心怎麼做好,為什麼還要花時間去開發軟體呢?
提示2:思考!思考你的工作 XVII
關掉輔助駕駛,由自己掌控,持續不斷地評估所做的工作。
第1章 務實的哲學 1
1 人生是你的 2
提示3:你有權選擇 3
人生是自己的。把握住人生,讓它如你所願。
2 我的源碼被貓吃了 3
提示4:提供選擇,別找藉口 5
提供選擇而不是去找理由。不要只說做不到;解釋一下都能做些什麼。
3 軟體的熵 6
提示5:不要放任破窗 7
只要看到不好的設計、錯誤的決策、糟糕的代碼,就趕緊去糾正。
4 石頭做的湯和煮熟的青蛙 9
提示6:做推動變革的催化劑 10
你無法強迫人們去改變,但可以展示美好未來,並幫助他們參與創造。
提示7:牢記全景 10
不要過度沉浸於細枝末節,以免察覺不到周圍正在發生的事情。
5 夠好即可的軟體 11
提示8:將品質要求視為需求問題 12
讓用戶參與對專案真實品質需求的確定。
6 知識組合 14
提示9:對知識組合做定期投資 16
養成學習的習慣。
提示10:批判性地分析你讀到和聽到的東西 18
不要受供應商、媒體炒作或教條的影響,根據自身和專案的實際情況來分析資訊。
7 交流! 20
提示11:英語就是另一門程式設計語言 20
將英語視作一門程式設計語言。寫文檔和程式設計一樣要遵循 DRY 原則、ETC、自動化等。
提示12:說什麼和怎麼說同樣重要 23
如果無法有效交流,任何偉大的想法都是沒有意義的。
提示13:把文檔嵌進去,而不要栓在表面 24
與代碼隔離的文檔,很難保持正確並及時更新。
第2章 務實的方法 27
8 優秀設計的精髓 28
提示14:優秀的設計比糟糕的設計更容易變更 28
適合使用者的事物,都已經過良好設計。對代碼來說,這意味著必須適應變化。
9 DRY——邪惡的重複 30
提示15:DRY——不要重複自己 31
系統中的每一條知識,都必須有單一且無歧義的權威陳述。
提示16:讓複用變得更容易 39
只要複用方便,人們就會去做。創建一個支持複用的環境。
10 正交性 40
提示17:消除不相關事物之間的影響 41
設計的元件,需要自成一體、獨立自主,有單一的清晰定義的意圖。
11 可逆性 48
提示18:不設最終決定 50
不要把決定刻在石頭上,而要將其視為寫在沙灘上的東西,時刻準備應變。
提示19:放棄追逐時尚 50
尼爾·福特說過:“昨日之最佳實踐,即明日之反模式。”要基於基本原則去選擇架構,而不應盲從於流行。
12 曳光彈 51
提示20:使用曳光彈找到目標 53
通過不斷嘗試並看清著彈點,曳光彈可確保你最終擊中目標。
13 原型與便簽 57
提示21:用原型學習 58
製作原型旨在學習經驗,其價值不在於過程中產生的代碼,而在於得到的教訓。
14 領域語言 60
提示22:靠近問題域程式設計 61
用問題領域的語言來做設計和程式設計。
15 估算 67
提示23:通過估算來避免意外 67
開始之前做估算,能提前發現潛在問題。
提示24:根據代碼不斷反覆運算進度表 72
利用實施過程中獲得的經驗來精細化項目的時間尺度。
第3章 基礎工具 74
16 純文字的威力 75
提示25:將知識用純文字保存 76
純文字不會過時。它能夠讓你的工作事半功倍,並能簡化調試和測試工作。
17 Shell遊戲 79
提示26:發揮 Shell 命令的威力 80
當圖形化介面無法勝任時,使用 Shell。
18 加強編輯能力 82
提示27:遊刃有餘地使用編輯器 82
既然編輯器是至關重要的工具,不妨瞭解一下如何用它更快更準確地實現需求。
19 版本控制 85
提示28:永遠使用版本控制 87
版本控制為你的工作創造了一個時間機器,可以用它重返過去。
20 調試 90
提示29:去解決問題,而不是責備 91
Bug 到底來自你的失誤還是別人的失誤真的不重要——它終究是你的問題,需要你來修復。
提示30:不要恐慌 91
不管是對銀河系搭車客,還是對開發者來說,都應這樣。
提示31:修代碼前先讓代碼在測試中失敗 93
在你修 Bug 前,先創建一個聚焦於該 Bug 的測試。
提示32:讀一下那些該死的出錯資訊 93
大多數異常都能告訴失敗之物與失敗之處。如果足夠幸運,你甚至能得到具體的參數值。
提示33:“select”沒出問題 97
在作業系統或編譯器中發現 Bug 非常罕見,甚至在協力廠商產品或庫中也是如此。Bug 大多出現在應用程式中。
提示34:不要假設,要證明 97
在真實環境中證實你的假設——要依賴真實的資料及邊界條件。
21 文本處理 99
提示35:學習一門文本處理語言 99
既然每天都要花大量的時間與文本打交道,何不讓電腦幫你分擔一二?
22 工程日記 101
第4章 務實的偏執 103
提示36:你無法寫出完美的軟體 103
軟體不可能是完美的。對於在所難免的錯誤,要保護代碼和用戶免受其影響。
23 契約式設計 104
提示37:通過契約進行設計 107
代碼是否不多不少剛好完成它宣稱要做的事情,可以使用契約加以校驗和文檔化。
24 死掉的程式不會說謊 113
提示38:儘早崩潰 114
徹底死掉的程式通常比有缺陷的程式造成的損害要小。
25 斷言式程式設計 115
提示39:使用斷言去預防不可能的事情 115
如果一件事情不可能發生,那麼就用斷言來確保其的確不會發生。斷言在校驗你的假設,要使用斷言在不確定的世界中將你的代碼保護起來。
26 如何保持資源的平衡 119
提示40:有始有終 119
只要有可能,對資源進行分配的函數或物件就有責任去釋放該資源。
提示41:在局部行動 122
將易變的變數維持在一個範圍內,打開資源的過程要短暫且明顯可見。
27 不要衝出前燈範圍 127
提示42:小步前進——由始至終 127
永遠小步前進,不斷檢查回饋,並且在推進前先做調整。
提示43:避免占卜 129
只在你能看到的範圍內做計畫。
第5章 寧彎不折 130
28 解耦 131
提示44:解耦代碼讓改變更容易 132
耦合使事物緊緊綁定在一起,以至於很難只改變其中之一。
提示45:只管命令不要詢問 133
不要從物件中取出值,在加以變換後再塞回去,讓物件自己來完成這些工作。
提示46:不要鏈式調用方法 135
當訪問某事物時,使用的點號不要超過一個。
提示47:避免全域資料 137
最好給每個方法增加一個額外的參數。
提示48:如果全域唯一非常重要,那麼將它包裝到API 中 137
……但是,僅限於你真的非常希望它是全域的。
29 在現實世界中拋球雜耍 139
30 變換式程式設計 149
提示49:程式設計講的是代碼,而程式談的是資料 151
所有的程式都在變換資料——將輸入轉換為輸出。開始用變換式方法來設計吧!
提示50:不要囤積狀態,傳遞下去 156
不要把資料保持在函數或模組的內部,拿出來傳遞下去。
31 繼承稅 162
提示51:不要付繼承稅 165
考慮一下能更好滿足需求的替代方案,比如介面、委託或mixin。
提示52:儘量用介面來表達多態 167
無需繼承引入的耦合,介面就能明確描述多態性。
提示53:用委託提供服務:“有一個”勝過“是一個” 167
不要從服務中繼承,應該包含服務。
提示54:利用 mixin 共用功能 169
mixin 不必承擔繼承稅就可以給類添加功能,而與介面結合可以讓多態不再令人痛苦。
32 配置 170
提示55:使用外部配置參數化應用程式 170
如果代碼對一些在應用程式發佈後還有可能改變的值有所依賴,那麼就在應用外部維護這些值。
第6章 併發 174
33 打破時域耦合 175
提示56:通過分析工作流來提高併發性 176
利用用戶工作流中的併發性。
34 共用狀態是不正確的狀態 179
提示57:共用狀態是不正確的狀態 180
共用狀態會帶來無窮的麻煩,而且往往只有重啟才能解決。
提示58:隨機故障通常是併發問題 186
或許時間和上下文的變化能暴露併發Bug,但併發Bug無法始終保持一致,也很難重現。
35 角色與進程 187
提示59:用角色實現併發性時不必共用狀態 188
使用角色來管理併發狀態,可以避免顯式的同步。
36 黑板 193
提示60:使用黑板來協調工作流 195
使用黑板來協調不相關的事實和代理人,能同時保持參與者之間的獨立性和孤立性。
第7章 當你編碼時 198
37 聽從蜥蜴腦 199
提示61:傾聽你內心的蜥蜴 201
當程式設計舉步維艱時,其實是潛意識在告訴你有什麼地方不對勁。
38 巧合式程式設計 204
提示62:不要依賴巧合程式設計 207
只能依賴可靠的事物。注意偶然事件的複雜性,不要混淆快樂的巧合與有目的的計畫。
39 演算法速度 210
提示63:評估演算法的級別 214
在開始程式設計前,對這件事情大概會花多長時間要有概念。
提示64:對估算做測試 214
針對演算法的數學分析無法說明所有問題,嘗試在目標環境中測試一下執行代碼的耗時。
40 重構 216
提示65:儘早重構,經常重構 219
像除草和翻整花園那樣,只要有需要就對代碼進行重新編寫、修訂和架構,以便找到問題的根源並加以修復。
41 為編碼測試 220
提示66:測試與找 Bug 無關 221
測試是觀察代碼的一個視角,可以從中得到針對設計、介面和耦合度的回饋。
提示67:測試是代碼的第一個用戶 222
用測試的回饋來引導工作。
提示68:既非自上而下,也不自下而上,基於端對端構建 225
創建一小塊端到端的功能,從中獲悉問題之所在。
提示69:為測試做設計 228
寫下代碼之前先從測試角度思考。
提示70:要對軟體做測試,否則只能留給用戶去做 230
無情地測試,不要等用戶來幫你找 Bug。
42 基於特性測試 231
提示71:使用基於特性的測試來校驗假設 231
基於特性的測試將會進行你從未想過的嘗試,並會以你不曾打算採用的方式操練你的代碼。
43 出門在外注意安全 238
提示72:保持代碼簡潔,讓攻擊面最小 241
複雜的代碼給 Bug 以滋生之沃土,給攻擊者以可趁之機。
提示73:儘早打上安全補丁 243
攻擊者會盡可能快地部署攻擊,你必須快上加快。
44 事物命名 245
提示74:好好取名;需要時更名 249
用名字向讀者表達你的意圖,並且在意圖改變時及時更名。
第8章 專案啟動之前 251
45 需求之坑 252
提示75:無人確切知道自己想要什麼 252
他們或許知道大概的方向,但不會瞭解過程的曲折。
提示76:程式師幫助人們理解他們想要什麼 253
軟體發展更像是一種由用戶和程式師協同創造的行為。
提示77:需求是從回饋迴圈中學到的 254
理解需求需要探索和回饋,因此決策的結果可以用來完善最初的想法。
提示78:和用戶一起工作以便從用戶角度思考 255
這是看透系統將如何被真正使用的最佳方法。
提示79:策略即中繼資料 256
不要將策略硬編碼進系統,而應該將其表達為系統的一組中繼資料。
提示80:使用專案術語表 259
為專案的所有特定詞彙創建一張術語表,並且在單一源頭維護。
46 處理無法解決的難題 260
提示81:不要跳出框框思考——找到框框 261
在面對無法解決的難題時,識別出真正的約束。可以問自己:“必須這樣做才能搞定嗎?必須搞定它嗎?”
47 攜手共建 264
提示82:不要一個人埋頭鑽進代碼中 267
程式設計往往困難又費力,找個朋友和你一起幹。
提示83:敏捷不是一個名詞;敏捷有關你如何做事 267
敏捷是一個形容詞,有關如何做事情。
48 敏捷的本質 267
第9章 務實的項目 271
49 務實的團隊 272
提示84:維持小而穩定的團隊 272
團隊應保持穩定、小巧,團隊中的每個人都應相互信任、互相依賴。
提示85:排上日程以待其成 274
如果你不把事情納入日程表,它們就不會發生。反思、實驗、學習、提高技能,這些事都應放入日程表。
提示86:組織全功能的團隊 276
圍繞功能而不是工作職能組織團隊。不要將 UI/UX 設計者從程式師中分離出去,也不要分開前端和後端;不要區分資料建模者和測試人員,以及開發和設計。構建一個團隊,這樣你就可以漸進地不斷反覆運算端到端的代碼。
50 椰子派不上用場 277
提示87:做能起作用的事,別趕時髦 279
不要僅僅因為別的公司正在那麼幹就採納一項技術或採用一個開發方法,而是要採用自己所處環境中對團隊有效的東西。
提示88:在使用者需要時交付 281
不要卡著流程要求,刻意等到幾周甚至幾個月後才交付。
51 務實的入門套件 281
提示89:使用版本控制來驅動構建、測試和發佈 282
利用提交或推送來觸發構建、測試、發佈,利用版本控制的標籤來進行生產部署。
提示90:儘早測試,經常測試,自動測試 283
每次構建都跑一下的測試,要比束之高閣的測試計畫有效得多。
提示91:直到所有的測試都已運行,編碼才算完成 283
無須多言。
提示92:使用破壞者檢測你的測試 285
在一個單獨的源碼副本中特意引入 Bug,驗證測試能否將其捕獲。
提示93:測試狀態覆蓋率,而非代碼覆蓋率 286
要識別並測試重要的程式狀態,只測試一行行的代碼是不夠的。
提示94:每個 Bug 只找一次 286
只要人類測試者找到一個 Bug ,就應該是該 Bug 最後一次被人類發現。從此之後,自動化測試完全可以發現它。
提示95:不要使用手動程式 287
電腦能一次又一次,按照同樣的次序,執行相同的指令。
52 取悅用戶 288
提示96:取悅用戶,而不要只是交付代碼 289
為用戶開發能夠帶來商業價值的解決方案,並讓他們每天都感到愉快。
提示97:在作品上簽名 290
過去的工匠在為他們的作品簽名時非常自豪,你也應該這樣。
53 傲慢與偏見 290
跋 292
提示98:先勿傷害 293
犯錯在所難免,確保犯錯後沒人會因此受難。
提示99:不要助紂為虐 294
因為這樣做你也有變成紂王的風險。
參考文獻 295
練習的參考答案 297
譯者跋 312
網路書店
類別
折扣
價格
-
新書$534