一燈能除千年暗,一智能滅萬(wàn)年愚。 —— 慧能,中國(guó)禪宗第6代祖師
第1章 敏捷 —— 高效軟件開(kāi)發(fā)之道
不管是預(yù)料之外的波浪沖擊,還是預(yù)想不到的設(shè)計(jì)失敗,在這兩種情況下敏捷都意味著可以快速地適應(yīng)變化
敏捷開(kāi)發(fā)就是在一個(gè)高度協(xié)作的環(huán)境中,不斷地使用反饋進(jìn)行自我調(diào)整和完善
第2章 態(tài)度決定一切
專業(yè)的態(tài)度應(yīng)該著眼于項(xiàng)目和團(tuán)隊(duì)的積極結(jié)果,關(guān)注個(gè)人和團(tuán)隊(duì)的成長(zhǎng),圍繞最后成功開(kāi)展工作
習(xí)慣1:做事
指責(zé)不能該修復(fù)Bug(Blame doesn't fix bugs)
過(guò)程符合標(biāo)準(zhǔn)并不意味著結(jié)果是正確的,敏捷團(tuán)隊(duì)重結(jié)果勝于過(guò)程
清晰地表明你的目的是解決問(wèn)題,而不是指責(zé)他人或者進(jìn)行爭(zhēng)辯
把矛頭對(duì)準(zhǔn)問(wèn)題的解決辦法,而不是人。這是真正有用處的正面效應(yīng)
“這不是我的錯(cuò)”這句話不對(duì),“這都是你的錯(cuò)”這句話更不對(duì)
習(xí)慣2:欲速則不達(dá)
防微杜漸(Beware of land mines)
不要孤立地編碼(Don't code in isolation)
使用單元測(cè)試(Use unit tests)
不要墜入快速的簡(jiǎn)單修復(fù)之中,要投入時(shí)間和精力保持代碼的整潔、敞亮
不要急于修復(fù)一段沒(méi)能真正理解的代碼。這種+1/-1的病癥始于無(wú)形,但是很快就會(huì)讓代碼一團(tuán)糟。要解決真正的問(wèn)題,不要治標(biāo)不治本
習(xí)慣3:對(duì)事不對(duì)人
消極扼殺創(chuàng)新(Negativity kills innovation)
負(fù)面的評(píng)論和態(tài)度扼殺了創(chuàng)新
你不需要很出色才能起步,但是你必須起步才能變得很出色
能容納自己并不接受的想法,表明你的頭腦足夠有學(xué)識(shí)
沒(méi)有最好的答案,只有更合適的方案
設(shè)定期限能夠 幫你在為難的時(shí)候果斷作出決策,讓工作可以繼續(xù)進(jìn)行
設(shè)計(jì)充滿了妥協(xié)(生活本身也是如此),成功屬于意識(shí)到這一點(diǎn)的團(tuán)隊(duì)
對(duì)事不對(duì)人。讓我們驕傲的應(yīng)該是解決了問(wèn)題,而不是比較出誰(shuí)的主意更好
只有更好,沒(méi)有最好。盡管“最佳實(shí)踐”這個(gè)術(shù)語(yǔ)到處在用,但實(shí)際上不存在“最佳”,只有在某個(gè)特定條件下更好的實(shí)踐
習(xí)慣4:排除萬(wàn)難,奮勇前進(jìn)
做正確的事。要誠(chéng)實(shí),要有勇氣去說(shuō)出實(shí)情。有時(shí),這樣做很困難,所以我們要有足夠的勇氣
如果涉及或代碼中出現(xiàn)了奇怪的問(wèn)題,花實(shí)踐去理解為什么代碼會(huì)是這樣的。如果你找到了解決辦法,但代碼仍然令人費(fèi)解,唯一的解決辦法是重構(gòu)代碼,讓它可讀性更強(qiáng)。如果你沒(méi)有馬上理解那段代碼,不要輕易地否定和重寫(xiě)它們。那不是勇氣,而是魯莽
第3章 學(xué)無(wú)止境
在一個(gè)企業(yè)化的社會(huì)中,只有一個(gè)人會(huì)為你負(fù)責(zé) —— 你自己。是否能跟上變化,完全取決于你自己
如果你跟蹤技術(shù)變化,那么學(xué)習(xí)這些新東西對(duì)你來(lái)說(shuō)就是了解這些增量變化
學(xué)習(xí)新的技術(shù)和新的開(kāi)發(fā)方法和重要,同時(shí)你也要能摒棄陳舊和過(guò)時(shí)的開(kāi)發(fā)方法
習(xí)慣5:跟蹤變化
迭代和增量式的學(xué)習(xí)、了解最新行情、參加本地的用戶組活動(dòng)、參加研討會(huì)議、如饑似渴地閱讀
跟蹤技術(shù)變化。你不需要精通所有技術(shù),但需要清楚知道行業(yè)的動(dòng)向,從而規(guī)劃你的項(xiàng)目和職業(yè)生涯
你不可能精通每一項(xiàng)技術(shù),沒(méi)有必要去做這樣的嘗試。只要你在某些方面成為專家,就能使用同樣的方法,很容易成為新領(lǐng)域的專家
習(xí)慣6:對(duì)團(tuán)隊(duì)投資
一個(gè)學(xué)習(xí)型的團(tuán)隊(duì)才是較好的團(tuán)隊(duì)
堅(jiān)持有計(jì)劃有規(guī)律地舉行講座。持續(xù)、小步前進(jìn)才是敏捷。稀少、間隔時(shí)間長(zhǎng)的馬拉松式會(huì)議非敏捷也
習(xí)慣7:懂得丟棄
在學(xué)習(xí)一門(mén)新技術(shù)的時(shí)候,多問(wèn)問(wèn)自己,是否把太多舊的態(tài)度和方法用在了新技術(shù)上
根深蒂固的習(xí)慣不可能輕易地就丟棄掉(Expensive mental models aren't discarded lightly)
丟棄的第一步,就是要意識(shí)到你還在使用過(guò)時(shí)的方法,做到真正丟棄舊習(xí)慣
不是完全忘記舊的習(xí)慣,而是只在適當(dāng)?shù)募夹g(shù)時(shí)才使用它
習(xí)慣8:打破沙鍋問(wèn)到底
為了解決問(wèn)題,你需要很好地了解系統(tǒng)的全局。你需要查看所有你認(rèn)為和問(wèn)題相關(guān)的部分 —— 即便其他人覺(jué)得這并不想干
“這個(gè),我不知道”是一個(gè)好的起點(diǎn),應(yīng)該由此進(jìn)行更進(jìn)一步的調(diào)查,而不應(yīng)該在此戛然而止
習(xí)慣9:把握開(kāi)發(fā)節(jié)奏
讓你的工作有一個(gè)節(jié)奏,在每天下班的時(shí)候,提交所有的工作,開(kāi)心地收工。這樣,明天就能開(kāi)始新的內(nèi)容,解決下一系列難題
項(xiàng)目開(kāi)發(fā)需要有一致和穩(wěn)定的節(jié)奏。編輯,運(yùn)行測(cè)試,代碼復(fù)審,一致的迭代,然后發(fā)布
第4章 交付用戶想要的軟件
你不可能戰(zhàn)勝變化,敏捷 —— 取決于你識(shí)別和適應(yīng)變化的能力
習(xí)慣10:讓客戶做決定
決定什么不該決定(Decide what you shouldn't decide)
開(kāi)發(fā)者能做的一個(gè)最重要的決定就是:判斷是哪些是自己決定不了的,應(yīng)該讓企業(yè)主做決定
當(dāng)你和客戶討論問(wèn)題的時(shí)候,準(zhǔn)備好幾種方案。不是從技術(shù)的角度,而是從業(yè)務(wù)的角度,介紹每種方案的優(yōu)缺點(diǎn),以及潛在的成本和利益
不要隨意假設(shè)低級(jí)別的問(wèn)題不會(huì)影響他們的業(yè)務(wù),如果能影響他們的業(yè)務(wù),就是有價(jià)值的問(wèn)題
習(xí)慣11:讓設(shè)計(jì)指導(dǎo)而不是操縱開(kāi)發(fā)
設(shè)計(jì)滿足實(shí)現(xiàn)即可,不必過(guò)于詳細(xì)(Design should be only as detailed as needed to implement)
設(shè)計(jì)可以分為兩層:戰(zhàn)略和戰(zhàn)術(shù)
馮諾依曼:“如果你自己都不清楚所談?wù)摰臇|西,就根本不可能精確地描述它”
戰(zhàn)略級(jí)別的設(shè)計(jì)不應(yīng)該具體說(shuō)明程序方法、參數(shù)、字段和對(duì)象交互精確順序的細(xì)節(jié)
好的設(shè)計(jì)應(yīng)該是正確的,而不是精確的
“不要在前期做大量的設(shè)計(jì)”并不是說(shuō)不要設(shè)計(jì)。只是說(shuō)在沒(méi)有經(jīng)過(guò)真正的代碼驗(yàn)證之前,不要陷入太多的設(shè)計(jì)任務(wù)。當(dāng)對(duì)設(shè)計(jì)一無(wú)所知的時(shí)候,投入編碼也是一件危險(xiǎn)的事。如果深入編碼只是為了學(xué)習(xí)或創(chuàng)造原型,只要你隨后能把這些代碼扔掉,那也是一個(gè)不錯(cuò)的辦法
習(xí)慣12:合理地使用技術(shù)
盲目地為項(xiàng)目選擇技術(shù)框架,就好比是為了少交稅而生孩子(Blindly picking a framework is like having kids to save taxes)
這個(gè)技術(shù)框架真能解決這個(gè)問(wèn)題嗎?如果需要,先做一個(gè)小的原型
也許為了迎合你發(fā)現(xiàn)的給你,你正在為它們找問(wèn)題
不要開(kāi)發(fā)你能下載到的東西(Don't build what you can download)
雖然有時(shí)需要從最基礎(chǔ)開(kāi)發(fā)所有你需要的東西,但那是相當(dāng)危險(xiǎn)和昂貴的
習(xí)慣13:保持可以發(fā)布
任何時(shí)候只要你沒(méi)有準(zhǔn)備好,那就是敵人進(jìn)攻你的最佳時(shí)機(jī)
已提交的代碼應(yīng)該隨時(shí)可以行動(dòng)(Checked-in code is always ready for action)
如果你不得不讓系統(tǒng)長(zhǎng)期不可以發(fā)布,那就做一個(gè)(代碼和架構(gòu)的)分支版本,你可以繼續(xù)進(jìn)行自己的實(shí)驗(yàn),如果不行,還可以撤銷,從頭再來(lái)。千萬(wàn)不能讓系統(tǒng)既不可以發(fā)布,又不可以撤銷
習(xí)慣14:提早集成,頻繁集成
在產(chǎn)品的開(kāi)發(fā)過(guò)程中,集成是一個(gè)主要的風(fēng)險(xiǎn)區(qū)域
絕不要做大爆炸式的集成(Never accept big-bang integration)
成功的集成就意味著所有的單元測(cè)試不停地通過(guò)。正如醫(yī)學(xué)界希波克拉底的誓言:首先,不要造成傷害
習(xí)慣15:提早實(shí)現(xiàn)自動(dòng)化部署
不幸的是,大部分開(kāi)發(fā)者只會(huì)在項(xiàng)目的尾期才開(kāi)始考慮部署問(wèn)題
質(zhì)量保證人員應(yīng)該測(cè)試部署過(guò)程(QA should test deployment)
如果你打算把持續(xù)部署系統(tǒng)和產(chǎn)品CD或者DVD刻錄機(jī)連接到一起,你就可以自動(dòng)地為每個(gè)構(gòu)建制作出一個(gè)完整且有標(biāo)簽的光盤(pán)。任何人想要最新的構(gòu)建,只要從架子上拿最上面的一張光盤(pán)安裝即可
習(xí)慣16:使用演示獲得頻繁反饋
需求就像是流動(dòng)著的油墨(Requirements are as fluid as ink)
你生產(chǎn)出了他們?cè)?jīng)要求過(guò)的軟件,但卻不是他們現(xiàn)在真正想要的。那最后的結(jié)果就是:驚訝、震驚和失望,而不是滿意
清晰可見(jiàn)的開(kāi)發(fā)。每隔一兩周,邀請(qǐng)所有的客戶,給他們演示最新完成的功能,積極獲得他們的反饋
演示是用來(lái)讓客戶提出反饋的,有助于駕馭項(xiàng)目的方向。如果缺少功能或者穩(wěn)定性的時(shí)候,不應(yīng)該拿來(lái)演示,那只能讓人生氣
可以及早說(shuō)明期望的功能:讓客戶知道,他們看到的是一個(gè)正在開(kāi)發(fā)中的應(yīng)用,而不是一個(gè)最終已經(jīng)完成的產(chǎn)品
習(xí)慣17:使用短迭代,增量發(fā)布
給我一份詳細(xì)的長(zhǎng)期計(jì)劃,我就會(huì)給你一個(gè)注定完蛋的項(xiàng)目(Show me a detailed long-term plan, and I'll show you a project that's doomed)
對(duì)付大項(xiàng)目,最理想的辦法就是小步前進(jìn)
大部分用戶都是希望現(xiàn)在就有一個(gè)夠用的軟件,而不是在一年之后得到一個(gè)超級(jí)好的軟件
增量的發(fā)布必須是可用的,并且能為用戶提供價(jià)值。你怎么知道用戶會(huì)覺(jué)得有價(jià)值呢?這當(dāng)然要去問(wèn)用戶。
習(xí)慣18:固定的價(jià)格就意味著背叛承諾
固定的價(jià)格就是保證要背叛承諾(A fixed price guarantees a broken promise)
敏捷不是意味著“開(kāi)始編碼,我們最終會(huì)知道何時(shí)可以完成”。你仍然需要根據(jù)當(dāng)前的知識(shí)和猜想,做一個(gè)大致的評(píng)估,解釋如何才能到達(dá)這個(gè)目標(biāo),并給出誤差范圍
第5章 敏捷反饋
習(xí)慣19:守護(hù)天使
編寫(xiě)能產(chǎn)生反饋的代碼(Coding feedback)
人們不編寫(xiě)單元測(cè)試的很多借口都是因?yàn)榇a中的設(shè)計(jì)缺陷。通常,抗議越強(qiáng)烈,就說(shuō)明設(shè)計(jì)越糟糕
習(xí)慣20:先用它再實(shí)現(xiàn)它
編程之前,先寫(xiě)測(cè)試(Write tests before writing code)
好的設(shè)計(jì)并不意味著需要更多的類(Good design doesn't mean more classes)
不要把測(cè)試優(yōu)先和提交代碼之前的測(cè)試等同起來(lái)。測(cè)試先行可以幫助你改進(jìn)設(shè)計(jì),但是你還是需要在提交代碼之前做測(cè)試。
習(xí)慣21:不同環(huán)境,就有不同問(wèn)題
使用自動(dòng)化會(huì)節(jié)省時(shí)間(Automate to save time)
硬件比開(kāi)發(fā)人員的時(shí)間便宜。但如果你有很多配置,要支持大量的平臺(tái),可以選擇哪些平臺(tái)需要內(nèi)部測(cè)試
習(xí)慣22:自動(dòng)化測(cè)試
為核心的業(yè)務(wù)邏輯創(chuàng)建測(cè)試。讓你的客戶單獨(dú)驗(yàn)證這些測(cè)試,要讓它們像一般的測(cè)試一樣可以自動(dòng)運(yùn)行
習(xí)慣23:度量真實(shí)的進(jìn)度
專注于你的方向(Focus on where you're going)
一周工作40個(gè)小時(shí),不是說(shuō)你就有40個(gè)小時(shí)的編碼時(shí)間。你需要減去會(huì)議、電話、電子郵件以及其他相關(guān)活動(dòng)的時(shí)間
習(xí)慣24:傾聽(tīng)用戶的聲音
這是一個(gè)bug(It is a bug)
每一個(gè)抱怨的背后都隱藏了一個(gè)事實(shí)。找出真相,修復(fù)真正的問(wèn)題
沒(méi)有愚蠢的用戶,只有愚蠢、自大的開(kāi)發(fā)人員
第6章 敏捷編碼
習(xí)慣25:代碼要清晰地表達(dá)意圖
C.A.R Hoare:“設(shè)計(jì)軟件有兩種方式,一種是設(shè)計(jì)得盡量簡(jiǎn)單,并且明顯沒(méi)有缺陷。另一種方式是設(shè)計(jì)得盡量復(fù)雜,并且沒(méi)有明顯的缺陷。”
代碼清晰程度的優(yōu)先級(jí)應(yīng)該排在執(zhí)行效率之前
應(yīng)該讓自己或團(tuán)隊(duì)的其他任何人,可以讀懂自己一年前寫(xiě)的代碼,而且只讀一遍就知道它的運(yùn)行機(jī)制
習(xí)慣26:用代碼溝通
不要用注釋來(lái)包裹你的代碼(Don't comment to cover up)
源代碼可以被讀懂,不是因?yàn)槠渲械淖⑨專鴳?yīng)該是由于它本身優(yōu)雅而清晰
代碼能夠自解釋,而不用依賴注釋
良好的命名可以向讀者傳遞大量的正確信息,不好的命名不會(huì)傳遞任何信息,糟糕的命名則會(huì)傳遞錯(cuò)誤的信息
不必費(fèi)盡新機(jī)去用繁冗的名字替換大家已習(xí)慣的名稱
解釋代碼做了什么的注釋用處不那么大。相反,注釋要說(shuō)明為什么會(huì)這樣寫(xiě)代碼
習(xí)慣27:動(dòng)態(tài)評(píng)估取舍
問(wèn)題的關(guān)鍵是要多長(zhǎng)個(gè)心眼兒,而不是總按照習(xí)慣的思路去解決問(wèn)題
沒(méi)有最佳解決方案(No best solution)
過(guò)去用過(guò)的解決方案對(duì)當(dāng)前的問(wèn)題可能適用,也可能不適用。不要事先預(yù)設(shè)結(jié)論,先看看現(xiàn)在是什么狀況
習(xí)慣28:增量式編程
在寫(xiě)了幾行代碼之后,你會(huì)迫切地希望進(jìn)行一次構(gòu)建/測(cè)試循環(huán)。在沒(méi)有得到反饋時(shí),你不想走得太遠(yuǎn)
習(xí)慣29:保持簡(jiǎn)單
簡(jiǎn)單不是簡(jiǎn)陋(Simple is not simplistic)
代碼幾乎總是可以得到進(jìn)一步精煉,但是到了某個(gè)點(diǎn)之后,再做改進(jìn)就不會(huì)帶來(lái)任何實(shí)質(zhì)性的好處了。這是開(kāi)發(fā)人員就該停下來(lái),去做其他方面的工作了
習(xí)慣30:編寫(xiě)內(nèi)聚的代碼
根據(jù)單一職責(zé)原則,一個(gè)模塊應(yīng)該只有一個(gè)發(fā)生變化的原因
感覺(jué)類和組件的功能都很集中:每個(gè)類或組件只做一件事,而且做得很好。bug很容易跟蹤,代碼也易于修改,因?yàn)轭惡徒M件的責(zé)任都很清晰
習(xí)慣31:告知,不要詢問(wèn)
面向過(guò)程的代碼取得信息,然后做出決策。面向?qū)ο蟮拇a讓別的對(duì)象去做事情
將命令與查詢分離開(kāi)來(lái)(Keep commands separate from queries)
不要搶別的對(duì)象或組件的工作,告訴它做什么,然后盯著你自己的職責(zé)就好了
習(xí)慣32:根據(jù)契約進(jìn)行替換
針對(duì)is-a關(guān)系使用繼承,針對(duì)has-a或uses-a關(guān)系使用委托(Use inheritance for is-a, use delegation for has-a or uses-a)
相對(duì)繼承來(lái)說(shuō),委托更加靈活,適應(yīng)力更強(qiáng)
第7章敏捷調(diào)試
習(xí)慣33:記錄問(wèn)題解決日志
不要在同一處跌倒兩次(Don't get burned twice)
維護(hù)一個(gè)問(wèn)題及其解決方案的日志
習(xí)慣34:警告就是錯(cuò)誤
將警告視為錯(cuò)誤。簽入帶有警告的代碼,就跟簽入有錯(cuò)誤或者沒(méi)有通過(guò)測(cè)試的代碼一樣,都是極差的做法
習(xí)慣35:對(duì)問(wèn)題各個(gè)擊破
用原型進(jìn)行分離(Prototype to isolate)
以二分查找的方式來(lái)定位問(wèn)題是很有用的。也就是說(shuō),將問(wèn)題空間分為兩半,看看哪一半包含問(wèn)題,再將問(wèn)題的一半進(jìn)行二分,并不斷重復(fù)這個(gè)過(guò)程
習(xí)慣36:報(bào)告所有的異常
處理或是向上傳播所有的異常。不要將它們壓制不管,就算是臨時(shí)這樣做也不行。在寫(xiě)代碼時(shí)要估計(jì)到會(huì)發(fā)生問(wèn)題
習(xí)慣37:提供有用的錯(cuò)誤信息
提供給用戶的信息可以包含一個(gè)主鍵,以便于在日志文件或是審核記錄中定位相關(guān)內(nèi)容
第8章 敏捷協(xié)作
習(xí)慣38:定期安排會(huì)面時(shí)間
站會(huì)每個(gè)人要回答三個(gè)問(wèn)題:昨天有什么收獲?今天計(jì)劃要做哪些工作?面臨哪些障礙?
迅速地開(kāi)始可以保證會(huì)議短小,不要浪費(fèi)時(shí)間等著會(huì)議開(kāi)始
習(xí)慣39:架構(gòu)師必須寫(xiě)代碼
不可能在PowerPoint中進(jìn)行編程(You can't code in PowerPoint)
Donald E. Knuth:“新系統(tǒng)的設(shè)計(jì)者必須要親自投入到實(shí)現(xiàn)中去。”
真正的架構(gòu)師,如果不允許參與編碼的話,他們會(huì)提出強(qiáng)烈的抗議
不要允許任何人單獨(dú)進(jìn)行設(shè)計(jì),特別是你自己
習(xí)慣40:實(shí)行代碼集體所有制
在團(tuán)隊(duì)中實(shí)行任務(wù)輪換制,讓每個(gè)成員都可以接觸到不同部分的代碼,可以提升團(tuán)隊(duì)整體的知識(shí)和專業(yè)技能
要強(qiáng)調(diào)代碼的集體所有制。讓開(kāi)發(fā)人員輪換完成系統(tǒng)不同領(lǐng)域中不同模塊的不同任務(wù)
習(xí)慣41:成為指導(dǎo)者
教學(xué)相長(zhǎng)(Knowledge grows when given)
努力爬到高處,再以蔑視的眼神輕視其他人,這似乎是人類本性
為團(tuán)隊(duì)成員在尋求幫助之前陷入某個(gè)問(wèn)題的時(shí)間設(shè)定一個(gè)時(shí)限,一個(gè)小時(shí)應(yīng)該是不錯(cuò)的選擇
習(xí)慣42:允許大家自己想辦法
感覺(jué)不是以填鴨式的方式給予別人幫助。不是有意掩飾,更非諱莫如深,而是帶領(lǐng)大家找到自己的解決方案
習(xí)慣43:準(zhǔn)備好后再共享代碼
絕不要提交尚未完成的代碼,故意簽入編譯未通過(guò)或是沒(méi)有通過(guò)單元測(cè)試的代碼,對(duì)項(xiàng)目來(lái)說(shuō),應(yīng)被視為玩忽職守的犯罪行為
習(xí)慣44:做代碼復(fù)查
Capers Jones《估算軟件成本》:“要尋找深藏不露的程序bug,正式地進(jìn)行代碼檢查,其效果是任何已知形式測(cè)試的兩倍,而且是移除80%缺陷的唯一已知辦法。”
要確保代碼復(fù)查參與人員得到每次復(fù)查活動(dòng)的反饋。作為結(jié)果,要讓每個(gè)人知道復(fù)查完成后所采取的行動(dòng)
習(xí)慣45:及時(shí)通報(bào)與問(wèn)題
接受一個(gè)任務(wù),也就意味著做出了要準(zhǔn)時(shí)交付的承諾
經(jīng)常抬頭看看四周,而不是只埋頭于自己的工作
也許你會(huì)喜歡: