1. 程式人生 > >讀書筆記之《高效程式設計師的45個習慣----敏捷開發之道》 摘錄

讀書筆記之《高效程式設計師的45個習慣----敏捷開發之道》 摘錄

 讀書筆記之《高效程式設計師的45習慣----敏捷開發之道》

       此次原創的意思是指這個文章中的內容是由筆者從《高效程式設計師的45習慣----敏捷開發之道》書中摘錄,而不是別人摘錄的,但是內容並非筆者原創,所摘錄的內容的版權均為《高效程式設計師的45個習慣-----敏捷開發之道》一書的作者以及翻譯者所有,特此申明。

     《高效程式員的45習慣-敏捷開發之道》真是一本好書,程式設計師必讀的著作之一。該文章會在筆者讀書過程中慢慢更新,這是一個摘錄,將該書中的45習慣以及一些細節摘抄出來,希望可以幫到沒時間讀這本書的人,同時提醒自己時刻注意。


一、敏捷----高效軟體開發之道

       一句話精闢概括敏捷:敏捷開發就是在一個高度協作的環境中,不斷地使用反饋進行自我調整和完善。

       難後易。我們首先要解決困難的問題,把簡單的問題留到最後。

二、態度決定一切

 1.做事。

       釋清楚你想要什麼,並清晰地表明你的目的是解決問題,而不是指責他人或者進行爭辯。指責不會修復bug。把矛頭對準問題的解決辦法,而不是人。這是真正有用處的正面效應。勇於承認自己不知道答案,這會讓人感覺放心。一個重大的錯誤應該被當作是一次學習而不是指責他人的機會。團隊成員在一起工作,應該互相幫助,而不是互相指責。

 2.欲速則不達。

     防微杜漸。不要急於修復一段沒有真正理解的程式碼。這種+1-1的病症始於無形,但是很快就會讓程式碼一團糟。要解決真正的問題,不要治標不治本。

    不要孤立低編碼。實行程式碼複審,花些時間去閱讀他人的程式碼,確保程式碼是可讀的和可理解的,並且不會隨意加入一些“+1-1”的代碼。這也是發現bug的最有效的方法之一。

    使用單元測試。測試驅動開發,單元測試幫你很自然地把程式碼分層,分成很多可管理的小塊,這樣你會得到設計更好、更清晰的程式碼。

   

不要墜入快速的簡單修復之中。要投入時間和精力保持程式碼的整潔、敞亮。

 3.對事不對人。

     團隊交流中,沒有譴責,沒有批判,不帶情緒,只是簡單地表達自己的觀點。工作中不感情用事是需要剋制力的,若你能展現出成熟大度來,大家一定不會視而不見。這需要有人帶頭,身體力行,去感染另一部分人。

     在一個需要緊密合作的開發團隊忠,如果能稍加註意禮貌對待他人,將會有益於整個團隊關注真正有價值的問題,而不是勾心鬥角,誤入歧途。我們每個人都有一些極好的創新想法,同樣也會萌生一些很愚蠢的想法。如果        你準備提出一個想法,卻擔心有可能被嘲笑,或你要提出一個建議,卻擔心自己丟面子,那麼你就不會主動提出自己的建議了。

     集體決策確實非常有效,但也有一些最好的創新源於很有見地的個人的獨立思考。如果你是一個很有遠見的人,就一定要特別尊重別人的意見。如果你是一個掌舵者,一定要把握方向,深思熟慮,吸取各方的意見。但是另一個極端是缺乏生氣的委員會,每個設計方案都需要全票通過。這樣的委員會總是小題大作,如果讓他們造一匹木馬,很可能最後造出的是駱駝。我們並不是建議你限制會議決策,只是你不應該成為一意孤行的首席架構師的傀儡。這裡建議你牢記亞里士多德的一句格言:能欣賞自己並不接受的想法,表明你的頭腦足夠有學識。

      支援已經做出的決定。一旦方案被確定了(不管是什麼樣的方案),每個團隊成員都必須通力合作,努力實現這個方案。

      讓我們驕傲的應該是解決了問題,而不是比較出誰的主意更好。

4.排除萬難,奮勇前進。

     發現問題是,不要試圖掩蓋這些問題。而是要有勇氣站起來,說:現在知道了,我過去使用的方法不對。我想到了一些辦法,可以解決這個問題-如果你有更好的想法,我也很樂意聽一聽-----但可能會多花些時間。你已經把所有對問題的負面情緒拋諸腦後,你的意圖很清楚,就是尋找解決方案。既然你提出大家一起努力來解決問題,那就不會有任何爭辯的餘地。這樣會促進大家去解決問題。你深知怎樣做才是正確的,或者至少知道目前的做法是錯誤的。要有勇氣向其他專案成員、老闆或者客戶解釋你的不同觀點。也許會冒犯他們,但是你都要不顧一切,向著正確的方向奮力前進。要誠實,要有勇氣去說出實情。有時,這樣做很困難,所以我們要有足夠的勇氣。


三、學無止境

 5.跟蹤變化。

      赫拉克利特說過:唯有變化是永恆的。XML現的時候,你花時間學習它。你深入研究ASP,熟知如何用它來開Web應用。你雖然不是這些技術的專家,但也不是對它們一無所知。好奇心促使你去了解MVC是什麼,設計模式是什麼。你會使用一點Java,去試試那些讓人興奮的功能。

      跟蹤技術變化,你不需要精通所有技術,但需要清楚知道行業的動向,從而規劃你的專案和職業生涯。

      你能嗅到將要流行的新技術,知道它們已經發布或投入使用。如果必須要把工作切換到一種新的技術領域,你能做到。

      在做決策前,你必須評估新技術的優勢。開發一個小的原型系統,是對付技術狂熱者的一劑良藥。

      如何跟上技術變化的步伐呢?下面是一些建議:

      迭代和增量式的學習。每天計劃用一段時間來學習新技術,它不需要很長時間,但需要經常進行。記下那些你想學習的東西-當你聽到一些不熟悉的術語或者短語時,簡要地把它記錄下來。然後在計劃的時間中深入研究它。

     瞭解最新行情。聯網上有大量關於學習新技術的資源。閱讀社群討論和郵件列表,可以瞭解其他人遇到的問題,以及他們發現的很酷的解決方案。選擇一些公認的優秀技術部落格,經常去讀一讀,瞭解那些頂尖的部落格作者們正在關注什麼。

      參加本地的用戶組活動。講座,然後積極加入到問答環節中。

     參加研討會。這些會議是向專家學習的最直接的好機會。

     飢似渴的閱讀。找一些關於軟體開發喝非技術主題的好書,也可以是一些專業的期刊和商業雜誌,甚至是一些大眾媒體新聞。

6.對團隊投資。 

     一個學習型的團隊才是較好的團隊。

     午餐會是在團隊中分享知識非常好的方式。每週,要求團隊中的一個人主持講座。他會給大家介紹一些概念,演示工具,或者做團隊感興趣的任何一件事情。你可以挑一本書,給大家說說其中一些特別內容、專案或者實踐。無論什麼主題都可以。先讓主持人講15鍾,然後進行開放式討論。通過午餐會議可以增進每個人的知識和技能,並幫助大家聚集在一起進行溝通交流。喚起人們對技術和技巧的激情,將會對專案大有裨益。堅持有計劃有規律地舉行講座,不要侷限於純技術的圖書和主題,相關的非技術主題(專案估算、溝通技巧等)也會對團隊有幫助。

 7。懂得丟棄。

    學會丟棄舊習慣、舊技術,力求儘可能完全轉入新的開發環境。學習新的東西,丟棄舊的東西。在學習一門新技術的時候,要丟棄會阻止你前進的就習慣。畢竟,汽車要比馬車車廂強得多。

8.打破砂鍋問到底.

    為了解決問題,你需要知道許多可能的影響因素。當找人詢問任何相關的問題時,讓他們耐心地回答你的問題,這是你的職責。

    不停地問為什麼。不能只滿足於別人告訴你的表面現象。要不停地提問直到你明白問題的根源。

9.把握開發節奏。

    解決任務,在事情變得一團糟之前。保持事件之間穩定重複的間隔,更容易解決常見的重複任務。

   專案開發需要有一致和穩定的節奏。編輯,執行測試,程式碼複審,一致的迭代,然後釋出。如果知道什麼時候開始下一個節拍,跳舞就會更加容易。

    每天結束的時候,測試程式碼,提交程式碼,沒有殘留程式碼。不要搞得經常加班。以固定、有規律的長度執行迭代,找到團隊最舒服可行的時間值,然後堅持。如果開發節奏過於密集,你會精疲力盡。就像是減肥一樣,一點點的成功也是一個很大的激勵。小而可達到的目標會讓每個人全速前進。慶祝每一次難忘的成功:共享美食和啤酒或者團隊聚餐。


交付用戶想要的軟體

10.讓客戶做決定。

     發者或者專案經理能做的一個最重要決定就是:判斷哪些是自己決定不了的,應該讓企業主做決定。你不需要自己給業務上的關鍵問題做決定。如果遇到一些問題,會影響到系統的行為或如何使用系統,把這個問題告訴業務負責人。開發者、經理或者業務分析師不應該做業務方面的決定。用業務負責人能夠理解的語言,向他們詳細解釋遇到的問題,並讓他們做決定。

11.讓設計指導開發而不是操縱開發

    敏捷開發建議你早在設計初期就開始編碼:先畫關鍵工作圖,然後才考慮開始編碼。

    設計可以分為兩層:戰略和戰術。前期的設計應該是隻描述總體戰略,不應該深入到具體的細節。不要一開始就進行戰術設計,它的重點是集中在單個的方法或資料型別上。這時更適合討論如何設計類的職責。因為這仍然是一個高層次、面向目標的設計。事實上,CRC(類-職責-協作)卡片的設計方法就是用來做這個事情的。每個類按照下面的術語描述。

      類名。

     職責:它應該做什麼?

     協作者:要完成工作它要與其他什麼物件一起工作?

     好設計是一張地圖,它也會進化。設計指引你向正確的方向前進,它不是殖民地,它不應該標識具體的路線。你不要被設計(或設計師)操縱。

     白板、草圖、便利貼都是非常好的設計工具。複雜的建模工具只會讓你分散精力,而不是啟發你的工作。

12.合理地使用技術。

       在考慮引入新技術或框架之前,先把你需要解決的問題找出來。接下來考慮如下幾方面。

      這個技術框架真能解決這個問題嗎?確保它能解決你的問題,並沒有任何的毒副作用。如果需要,先做一個小的原型。

     你將會被它套住嗎?

     維護的成本是多少?

     不要開發你能下載到的東西。程式碼寫得越少,需要維護的東西就越少。

     根據需要選擇技術。首先決定什麼是你需要的,接著為這些具體的問題評估使用技術。對任何要使用的技術,多問一些挑剔的問題,並真實地作出回答。

13.保持可以釋出。

     保證你的系統隨時可以編譯、執行、測試並立即部署。下面是一個簡單的工作流程,可以防止你提交破壞系統的程式碼。

     在本地執行測試。先保證你完成的程式碼可以編譯,並且能通過所有的單元測試。接著確保系統中的其他測試都可以通過。

     更新到最新的程式碼。從SVN中更新程式碼到最新的版本,再編譯和執行測試。這時你往往發現衝突了,解決衝突,並編譯測試。

     提交程式碼。現在是最新程式碼並通過編譯和測試,你可以提交它們了。

     建立分支。如果你不得不讓系統長期不可以釋出,那就做一個分支版本。你可以繼續自己的實驗,如果不行,還可以撤銷重來。

14,提早整合,頻繁整合。

       敏捷開發的一個主要特點就是持續開發,而不是三天打魚兩天晒網似地工作。特別是在幾個人一起開發同一個功能的時候,更應該頻繁地整合程式碼。

       程式碼整合是主要的風險來源。要想規避這個風險,只有提早整合,持續而有規律的整合。

15.提早實現自動化部署。

      質量保證人員 應該測試部署過程。

      16.使用演示獲得頻繁反饋。

      需求就像是流動這的油墨。如果你期望在專案開始之前,就能給你可靠和明確的需求,那就大錯特錯了,趕快醒醒吧!

      在開發的時候,要保持應用可見(而且客戶心中也要了解)。每隔一週或兩週,邀請所有的客戶,給他們演示最新完成的功能,積極獲得他們的反饋。

17.使用短迭代,增量釋出。

       敏捷方法使用迭代和增量開發。使用增量開發一次開發應用功能的幾個小組。每一輪開發都是基於前一次的功能,增加為產品增值的新功能。這時,你就可以釋出或者演示產品。釋出帶有最小卻可用功能塊的產品。每個增量開發中,使用1~4周左右迭代週期。

       迭代開發是,在小且重複的週期裡,你完成各種開發任務:分析、設計、實現、測試和獲得反饋,所以叫做迭代。迭代的結束就標記一個里程碑。

      對付大專案,最理想的辦法是小步前進,這也是敏捷方法的核心。大步跳躍大大地增加了風險,小步前進才可以幫助你很好地把握平衡。

      詢問使用者,哪些是使產品可用且不可缺少的核心功能。不要為所有可能需要的華麗功能而分心,不要沉迷於你的想象,去做那些華而不實的使用者介面。

      有一堆理由值得你儘快把軟體交到使用者手中:只要交到使用者手中,你就有了收入,這樣就有更好的理由繼續為產品投資了。從使用者那裡得到的反饋,會讓我們進一步理解什麼是使用者真正想要的,以及下一步該實現哪些功能。也許你會發現,一些過去認為重要的功能,現在已經不再重要了--------我們都知道市場的變化有多快。儘快釋出你的應用,遲了也許它就沒有用了。

  

 18.固定的價格就意味著背叛承諾。

      固定價格的合同會是敏捷團隊的一大難題。我們一直在談論如何用持續、迭代和增量的方式工作。但現在卻有些人跑過來,想提早知道它會花費多少時間以及多少成本。

      軟體專案天生就是變化無常的,不可重複。如果要提前給出一個固定的價格,就幾乎肯定不能遵守開發上的承諾

     一些解決矛盾的建議:

     主動提議先構建系統最初的、小的和有用的部分,這時候還不是要完成所有的功能,而是要足夠一次交付,並能讓使用者真正使用。

     每一個迭代結束時客戶有兩個選擇:可以選擇一系列新的功能,繼續進入下一個迭代;或者取消合同。

    讓團隊和客戶一起,真正地在當前專案中工作,做具體實際的評估,由客戶控制他們要的功能和預算。


五、敏捷反饋

     一步行動,勝過千萬專家的意見。在敏捷專案中,我們小步前進,不停地收集反饋,時刻矯正自己。實踐是絕對必須的,確保你明確知道專案的正確狀態,而不是主觀臆測。

19.守護天使。

         敏捷就是管理變化的,而且,程式碼可能是變化最頻繁的東西。為了應對程式碼的變化,你需要持續獲得程式碼健康狀態的反饋:這時你就需要自動化測試。

         只要有了單元測試,就要讓它們自動執行。也就是每次編譯或者構建程式碼的時候,就執行一次測試。把單元測試的結果看作是和編譯器一樣,如果測試沒通過,就像編譯沒通過一樣糟糕。這樣你就有了一個守護天使。如果出現了問題,你會立刻知道,並且這是最容易修復(也是成本最低)的時候。

         好的單元測試能夠為你的程式碼問題提供及時的警報。如果沒有到位的單元測試,不要進行任何設計和程式碼修改。

         不是測試越多質量就會越高,測試必須要有效。

20.先用它再實現它

        編碼之前,先寫測試。使用被稱為TTD(測試驅動開發)的技術,你總是在有一個失敗的單元測試之後才開始編碼。先寫測試有助於消除過度複雜的設計,讓你可以真正專注於需要完成的工作。消除那些還沒有編寫的類,這會很容易地簡化程式碼。只在有具體理由的時候才開始編碼。你可以專注於設計介面,而不會被很多實現的細節干擾。

       21.不同環境,就有不同問題

       使用自動化會節省時間。使用一個持續整合工具,週期性地從原始碼控制系統中取得程式碼,並執行程式碼。如果有任何測試失敗了,它會通知相關的開發者。通知方式可能是電子郵件、頁面、RSS Feed,或者其他一些新穎的方式。

       要在多個平臺上測試,你只要為每個平臺設定持續整合系統就行了。當你或者你同事提交了程式碼,測試會在每個平臺上自動執行。要積極地尋找問題,而不是等問題來找你。

22.自動驗收測試。

        FIT,即整合測試框架,它很實用;可以更容易地使用HTML表格定義測試用例,並比較測試結果資料。你應該讓使用者可以在不必學習編碼的情況下,根據自己的需要進行新增、更新和修改資料。  為核心的業務邏輯建立測試。讓你的客戶單獨驗證這些測試,要讓它們像一般的測試一樣可以自動執行。

23.度量真實的進度

     時間的消逝(通常很快)可以證明:判斷工作進度最好是看實際花費的時間而不是估計的時間。不幸的是,幾乎所有公司的時間表都是為工資會計準備的,不是用來度量軟體專案的開發進度的。

    你曾經聽到開發人員報告一個任務完成了80%嗎?然而過了一天又一天,一週又一週,那個任務仍然是完成了80%?在你真正完成一項任務時,要清楚知道完成這個任務真正花費的時間。奇怪的是,它花費的時間很可能要比最初估計時間長。沒有關係,我們希望這能作為下一次的參考。隨著時間的推移,你的評估會與事實接近,你也會對任務所花費的時間有更清楚的認識。

    如果能一直讓下一步工作是可見的,會有助於進度度量。最好的做法就是使用待辦事項。待辦事項就是等待完成的任務列表。

     度量剩下的工作量。不要用不恰當的度量來欺騙自己或團隊。要評估那些需要完成的待辦事項。關注功能,而不是日程表。

24.傾聽使用者的聲音。

    當出了錯誤,你要儘可能地提供詳細資訊。黑屏和含義不明的“退出”按鈕是很不友好的行為。更糟糕的是,在得到使用者反饋的時候,你還嘲笑使用者愚蠢,而不去真正地解決問題。

   不管它是否產品的bug,還是文件的bug,或者是對使用者社群理解的bug,它都是團隊的問題,而不是使用者的問題。每一個抱怨的背後都隱藏了一個事實。找出真相,修復真正的問題。對客戶的那些愚蠢抱怨,你既不會生氣,也不會輕視。你會檢視一下,找出背後真正的問題。“它就是這樣的。”這不是一個好的答案。

25.程式碼要清晰地表達意圖。

     開發程式碼是,應該更注重可讀性,而不是隻圖自己方便。程式碼閱讀的次數要遠遠超過編寫的次數,所以在編寫的時候值得花點功夫讓它讀起來更加簡單。實際上,從衡量標準上來看,程式碼清晰程度的優先順序應該排在執行效率之前

     在改動程式碼修復bug或者新增新功能時,應該有條不紊地進行。首先,應該理解程式碼做了什麼,它是如何做的。接下來,搞清楚將要改變哪些部分,然後著手修改並進行測試。作為一個開發者,應該時常提醒自己是否有辦法讓寫出的程式碼更容易理解。要編寫清晰而不是討巧的程式碼。向程式碼閱讀者明確表明你的意圖,可讀性差的程式碼一點都不聰明。

      PIE原則:程式碼必須明確說出你的意圖,而且必須富有表達力。這樣可以讓程式碼更易於被別人閱讀和理解。程式碼不讓人疑惑,也就減少了發生潛在錯誤的可能。一言以蔽之,程式碼應意圖清晰,表達明確。

    在編寫程式碼時,應該使用語言特性來提升表現力。使用方法名來傳達意向,對方法引數的命名要幫助讀者理解背後的想法。異常傳達的資訊是哪些可能會出問題,以及如何進行防禦式程式設計,要正確地使用和命名異常。好的編碼規範可以讓程式碼變得易於理解,同時減少不必要的註釋和文件。

26.用程式碼溝通。

       建立程式碼文件無非兩種方式:利用程式碼本身;利用註釋來溝通程式碼之外的問題註釋可以讓其他開發人員快速瞭解方法的意圖、期待結果,以及應該注意之處。但是不要用註釋來包裹你的程式碼。原始碼可以被讀懂,不是因為其中的註釋,而應該是由於它本身優雅而清晰------變數名運用正確、空格使用得當、邏輯分離清晰,以及表示式非常簡潔。

      如何命名很重要。程式元素的命名是程式碼讀者必讀的部分。通過使用細心挑選的名稱,可以向閱讀者傳遞大量的意圖和資訊。反過來講,使用人造的命名正規化(比如現在已經無人問津的匈牙利表示法)會讓程式碼難以閱讀和理解。這些正規化中包括的底層資料型別資訊,會硬編碼在變數名和方法名中,形成脆弱、僵硬的程式碼,並會在將來造成麻煩。

    使用細心挑選的名稱和清晰的執行路徑,程式碼幾乎不需要註釋。如何界定一個良好的命名?良好的命名可以向讀者傳遞大量的正確的資訊。不好的命名不會傳遞任何資訊,糟糕的命名則會傳遞錯誤的資訊。儘量避免使用神祕的變數名,但是也不必費盡心思去用繁複冗長的名字來替換大家已習慣的名稱。

   對於顯而易見的程式碼增加註釋,最好的狀況不過是為程式碼添加了“噪音”。最壞的狀況下,隨著時間推進,這些註釋會過時。許多註釋沒喲傳遞任何有意義的資訊,只會分散注意力,而且容易失去時效性。

   註釋可用來為讀者指定一條正確的程式碼訪問路線圖。為程式碼中的每個類或模組新增一個短小的描述,說明其目的以及是否有任何特別需求。對於類中的每個方法,可能要說明下列資訊。

  •  目的:為什麼需要這個方法?
  • 需求(前置條件):方法需要什麼樣的輸入,物件必須處於何種狀態,才能讓這個方法工作?
  • 承諾(後置條件):方法成功執行之後,物件現在處於什麼狀態,有哪些返回值?
  • 異常:可能會發生什麼樣的問題?會丟擲什麼樣的異常?

      感謝如RDoc、javadoc和ndoc這樣的工具,使用它們可以很方便地直接從程式碼註釋建立有用的、格式優美的文件。這些工具抽取註釋,並生成樣式漂亮且呆有超連結的HTML輸出。程式碼被閱讀的次數要遠超過被編寫的次數,所以在程式設計時多付出一點努力來做好文件,會讓你在將來受益匪淺。

     用註釋溝通。使用細心選擇的、有意義的命名。用註釋描述程式碼意圖和約束。註釋不能替代優秀的程式碼。解釋程式碼做了什麼的註釋用處不那麼大。相反,註釋要說明為什麼會這樣寫程式碼。在程式碼可以傳遞意圖的地方不要使用註釋。

27、動態評估取捨。

    對任何單個因素如此獨斷地強調,而不考慮它是否是專案成功的必要因素,必然導致災難的發生。強調效能的重要性情有可原,因為惡劣的效能表現會讓一個應用在市場上鎩羽而歸。然而,如果應用的效能已經足夠好了,還有必要繼續投入精力讓其執行得更加快一點嗎?大概不用了吧。一個應用還有很多其他方面的因素同樣重要。與其花費時間去提升千分之一的效能表現,也許減少開發投入,降低成本,並儘快讓應用程式上市銷售更有價值。總而言之,要想讓應用成功,降低開發成本與縮短上市時間,二者的影響同樣重要。由於計算機硬體價格日益便宜,處理速度日益加快,所以可在硬體上多投入以換取效能的提升,並將節省下來的時間放在應用的其他方面。

   但是誰來最終判定效能表現已經足夠好,或是應用的展現已經足夠“炫”了呢?客戶或是利益相關者必須進行評估,並做出相關決定。沒有適宜所有狀況的最佳解決方案。你必須對受傷的問題進行評估,並選出最合適的解決方案。每個設計都是針對特定問題的-------只有明確地進行評估和權衡,才能得出更好的解決方案。

   動態評估權衡。考慮效能、便利性、生產力、成本和上市時間。如果效能表現足夠了,就將注意力放在其他因素上。不要為了感覺上的效能提升或者設計的優雅,而將設計複雜化。如果現在投入額外的資源和精力,是為了將來可能得到的好處,要確認投入一定要得到回報(大部分情況下,是不會有回報的)。

28、增量式程式設計。

       增量式程式設計可以精煉並結構化你的程式碼。程式碼被複雜化、變成一團亂麻的機率減少了。所開發的程式碼基於即時的反饋,這些反饋來自以小步幅方式編寫程式碼和測試的過程。你會傾向於建立更小的方法和更具內聚性的類。你不是在盲目地一次性編寫一大堆程式碼。相反,你會經常評估程式碼質量,並不時地進行許多小調整,而不是一次修改許多東西。編寫程式碼的時候,經常留心可以改進的微小方面。這可能會改善程式碼的可讀性。也許你會發現可以把一個方法拆成幾個更小的方法,使其變得更易於測試。可以使用測試優先開發方式,作為強制進行增量式程式設計的方式。關鍵在於持續做一些細小而有用的事情,而不是做一段長時間的程式設計或者重構。

       在很短的編輯、構建、測試迴圈中編寫程式碼。這要比花費長時間僅僅做編寫程式碼的工作好得多。可以建立更加清晰、簡單、易於維護的程式碼。

29.保持簡單。

        優雅的程式碼第一眼看上去,就知道它的用處,而且很簡潔。評價設計質量的最佳方式之一,就是聽從直覺。直覺不是魔術,它是經驗和技能的厚積薄發之產物。在檢視一個設計時,聽從頭腦中的聲音。如果覺得有什麼地方不對,那就好好想想,是哪裡出了問題。一個好的設計會讓人覺得很舒服。當你覺得所編寫的程式碼中沒有一行是多餘的,並且仍能交付全部的功能時,這種感覺就對了。這樣的程式碼容易理解和改正。

        開發可以工作的、最簡單的解決方案。除非有不可辯駁的原因,否則不要使用模式、原則和高難度技術之類的東西。

30.編寫內聚的程式碼。

        內聚性用來評估一個元件(包、模組或配件)中成員的功能相關性。內聚程度高,表明各個成員共同完成了一個功能特性或一組功能特性。內聚程度低的話,表明各個成員提供的功能是互不相干的。

        在決定建立一個類時,問問自己,這個類的功能是不是與元件中其他某個類的功能類似,而且功能緊密相關。這就是元件級的內聚性。類也要遵循內聚性。如果一個類的方法和屬性共同完成了一個功能(或是一系列緊密相關的功能),這個類就是內聚的。感覺類和元件的功能都很集中:每個類或元件只做一件事,而且做得很好。bug很容易跟蹤,程式碼也易於修改,因為類和元件的責任都很清晰。

       根據單一職責原則,一個模組應該只有一個發生變化的原因。

       讓類的功能儘量集中,讓元件儘量小。要避免建立很大的類或元件,也不要建立無所不包的大雜燴類。     

31.告知,不要詢問。

        面向過程的程式碼取得資訊,然後做出決策。面向物件的程式碼則讓別的物件去做事情。作為某段程式碼的呼叫者,開發人員絕對不應該基於被呼叫物件的狀態來做出任何決策,更不能去改變該物件的狀態。這樣的邏輯應該是被呼叫物件的責任,而不是你的。在該物件之外替它做決策,就違反了它的封裝原則,而且為bug提供了滋生的土壤。

        將命令與查詢分離開來。就是將功能和方法分為“命令”和"查詢"兩類,並在原始碼中記錄下來(這樣做可以幫助將所有的“命令”程式碼放在一起,並將所有的“查詢”程式碼放在一起)。一個常規的“命令”可能會改變物件的狀態,而且有可能返回一些有用的值,以方便使用。一個“查詢”僅僅提供給開發人員物件的狀態,並不會對其外部的可見狀態進行修改。從外部將“查詢”和“命令”隔離,讓開發者有機會詢問自己為什麼要暴露某些特定的資料。

        告知,不要詢問。不要搶別的物件或是元件的工作。告訴它做什麼,然後盯著你自己的職責就好了。

32.根據契約進行替換。

       保持系統靈活性的關鍵方式,是當新程式碼取代原有程式碼之後,其他已有的程式碼不會意識到任何差別。Liskov替換原則告訴我們:任何繼承後得到的派生類物件,必須可以替換任何被使用的基類物件,而且使用者不必知道任何差異。換句話說,某段程式碼如果使用了基類中的方法,就必須能夠使用派生類的物件,並且自己不必進行任何修改。相對基類的對應方法,派生類應該不要求更多,不承諾更少;要可以進行自由的替換。

       當使用繼承是,要想想派生類是否可以替換基類。如果答案是不能,就要問問自己為什麼要使用繼承。如果答案是希望在編寫新類的時候,還要重用基類中的程式碼,也許要考慮轉而使用聚合。聚合是指在一個類中包含一個物件,並且該物件是其他類的例項。開發人員將責任委託給所包含的物件來完成(該技術同樣被稱為委託)。

       那麼繼承和委託分別在什麼時候使用呢?

  •  如果新類可以替換已有的類,並且它們之間的關係可以通過is-a來描述,就要使用繼承。
  • 如果新類只是使用已有的類,並且兩者之間的關係可以描述為has-a或uses-a,就使用委託吧。

       通過替換程式碼來擴充套件系統。通過替換遵循介面契約的類,來新增並改進功能特性,要多使用委託而不是繼承。  

七、敏捷除錯。

        你也許會對木匠那毫無差錯的工作印象深刻,但我向你保證,事實不是這樣。真正的高手只是知道如何亡羊補牢。----------Jeff Miller。

 33.記錄問題解決日誌。

        面對問題並解決它們是開發人員的一種生活方式。維護一個儲存曾遇到的問題以及對應解決方案的日誌,稱之為每日日誌。可以選擇符合需求的任何格式。下面這些條目可能會用的上:

  • 問題發生日期。
  • 問題簡述。
  • 解決方案詳細描述。
  • 引用文章或網址,以提供更多細節或相關資訊。
  • 任何程式碼片段、設定或對話方塊的截圖,只要它們是解決方案的一部分,或者可以幫助更深入地理解相關細節。       

        要共享日誌給其他人,而不僅僅是靠一個人維護。可以建立一個Wiki,並鼓勵其他開發人員使用和更新其內容。

       維護一個問題及其解決方案的日誌。保留解決方案是修復問題過程的一部分,以後發生相同或類似問題時,就可以很快找到並使用了。

34.警告就是錯誤。

     要找到一種方式讓編譯器將警告作為錯誤提示出來。如果編譯器允許調整警告的報告級別,那就把級別調到最高,讓任何警告不能被忽略。

     將警告視為錯誤,簽入帶有警告的程式碼,就跟簽入有錯誤或沒有通過測試的程式碼一樣,都是極差的做法。簽入構建工具中的程式碼不應該產生任何警告資訊。

     由於編譯器的bug或是第三方工具或程式碼的原因,有些警告無法消除。如果確實沒有應對之策的話,就不要再浪費更多時間了。但是類似的狀況很少發生。

35.對問題各個擊破。

     對問題各個擊破,這樣做有很多好處;通過將問題與應用其他部分隔離開來,可以將關注點直接放在與問題相關的議題上;可以通過多種改變,來接近問題發生的核心-----你不可能針對正在執行的系統來這樣做。可以更快地發現問題的根源所在,因為只與所需最小數量的相關程式碼發生關係。

    對問題各個擊破。在解決問題時,要將問題域與其周邊隔離開,特別是在大型應用中。

36.報告所有的異常。

      從事任何程式設計工作,都要考慮事物正常狀況下是如何運作的。不過更應該想一想,當出現問題-------也就是事情沒有按計劃進行時,會發生什麼。

      處理或是向上傳播所有的異常。不要將它們壓制不管,就算是臨時這樣做也不行。在寫程式碼時要估計到會發生的問題。

37.提供有用的錯誤資訊。

        當應用釋出並在真實世界中得到使用之後,仍然會發生這樣那樣的問題。針對這個問題,常用的解決方案是記錄日誌:當發生問題時,讓應用詳細記錄錯誤的相關資料。錯誤日誌最起碼應該以文字檔案的形式維護。不過也許可以釋出到一個系統級別的事件日誌中,可以使用RSS Feed等工具來瀏覽日誌。

       一方面要提供給使用者清晰、易於理解的問題描述和解釋,使他們有可能尋求變通之法。另一方面,還要提供具備關於錯誤的詳細技術細節給使用者,這樣方便開發人員尋找程式碼中真正的問題所在。

      展示有用的錯誤資訊。提供更易於查詢錯誤細節的方式。發生問題時,要展示出儘量多的支援細節,不過別讓使用者陷入其中。

      區分錯誤型別:

      程式缺陷。這些是真正的bug,使用者或系統管理員對此束手無策。

      環境問題。包括資料庫連結失敗,或無法連結遠端Web Service、磁碟空間滿、許可權不足,以及類似的問題。程式設計師對此沒有應對之策,但是使用者也許可以找到變通的方法,如果提供足夠詳細的資訊,系統管理員應該可以解決這些問題。

      使用者錯誤。程式設計師與系統管理員不必擔心這些問題。在告知是哪裡操作的問題後,使用者可以重新來過。


八、敏捷協作。

      我不僅發揮了自己的全部能力,還將我所仰仗的人的能力發揮到極致。 ---------伍德羅.威爾遜,美國第28任總統(1856----1924)

38.定期安排會面時間。

       也許你個人很討厭開會,但是溝通是專案成功的關鍵。我們不只要跟客戶談話,還應該與開發人員進行良好的溝通。

      立會是將團隊召集在一起,並讓每個人瞭解當下進展狀況的好辦法。顧名思義,參與者們不允許在立會中就坐,這可以保證會議快速進行。要保證會議不會發散,每個人都應該只回答下述三個問題:

  • 昨天有什麼收穫?
  • 今天計劃要做哪些工作?
  • 面臨著哪些障礙?      

       通常,立會都是在每個工作日的早些時候,且大家都在上班時舉行。但是不要把它安排為上班後的第一件事。要讓大家有機會從剛才混亂的交通狀況中恢復狀態,喝點咖啡,刪除一些垃圾郵件什麼的。要保證會議結束後有足夠的時間,讓大家在午餐之前做不少工作,同時也不要開始得過早,讓每個人都巴不得趕緊結束會議,去喝點東西。一般來說,在大家到公司之後的半個小時到一個小時之內舉行,是個不錯的選擇。

     每日立會有諸多好處:

  • 讓大家儘快投入到一天的工作中來。
  • 如果讓某個開發人員在某一點上有問題,他可以趁此機會將問題公開,並積極尋求幫助。
  • 幫助團隊帶頭人或管理層瞭解哪些領域需要更多的幫助,並重新分配人手。
  • 讓團隊成員知道專案其他部分的進展情況。
  • 幫助團隊識別是否在某些東西上有重複勞動而耗費了精力,或者不是某個問題有人已有現成的解決方案。
  • 通過促進程式碼和思路的共享,來提升開發速度。
  • 鼓勵向前的動力:看到別人報告的進度都在前進,會對彼此形成激勵。    

         使用立會。立會可以讓團隊達成共識。保證會議短小精悍不跑題。

39.架構師必須寫程式碼。

      You can't code in PowerPoint .  你不可能在PPT中進行程式設計。

      許多架構師通常在專案開始時介入,繪製各種各樣的設計圖,然後在重要的程式碼實現開始之前離開。由於得不到反饋,他們的架構設計工作也不會有很好的收效。一個設計要解決的是眼前的面臨的特定問題,隨著設計的實現,對問題的理解也會發生改變。最為設計人員,如果不能理解系統的具體細節,就不可能做出有效的設計。只通過一些高度概括的、粗略的設計圖是無法很好地理解系統。

       好的設計者必須能夠捲起袖子,加入開發隊伍,毫不猶豫地參與實際程式設計。真正的架構師,如果不允許參與編碼的話,他們會提出強烈的抗議。應該根據設計開發出原型,經過測試,當然還有驗證----它是要演化的。實現可用的設計,這是設計者或說架構師的責任。

      要鼓勵程式設計師參與設計。主力程式設計師應該試著擔任架構師的角色,而且可以從事多種不同的角色。他會負責解決設計上的問題,同時也不會放棄編碼的工作。如果開發人員不願意承擔設計的責任,要給他們配備一個有良好設計能力的人。程式設計師在拒絕設計的同時,也就放棄了思考。

     優秀的設計從積極的程式設計師那裡開始演化。積極的程式設計可以帶來深入的理解。不要使用不願意程式設計的架構師------不知道系統的真實情況,是無法展開設計的。

     架構、設計、編碼和測試,這些工作給人的感覺就像是同一個活動-----開發的不同方面。感覺它們彼此之間應該是不可分割的。

     如果有一位首席架構師,他可能沒有足夠的時間來參與編碼工作。還是要讓他參與,但是別讓他開發在專案關鍵路徑上的、工作量最大的程式碼。

40.實行程式碼集體所有制

     任何具備一定規模的應用,都需要多人協作進行開發。在這種狀況下,不應該像國家宣稱對領土的所有權一樣,宣告個人對程式碼的所有權。任何一位團隊成員,只要理解某段程式碼的來龍去脈,就應該可以對其進行處理。如果某一段程式碼只有一位開發人員能夠處理,專案的風險無形中也就增加了。

   相比找出誰的主意最好、誰的的程式碼實現很爛而言,解決問題,並讓應用滿足使用者的期望要更為重要。

   當多人同時開發時,程式碼會被頻繁地檢查、重構以及維護。如果需要修復bug,任何一名開發人員都可以完成這項工作。同時有兩個或兩個以上的人,可以處理應用中不同部分的程式碼,可以讓專案的日程安排也變得更為容易。

   在團隊中實行任務輪換制,讓每個成員都可以接觸到不同部分的程式碼,可以提升團隊整體的知識和專業技能。當Joe接過Sally的程式碼,他可以對其進行重構,消除待處理的問題。在試圖理解程式碼的時候,他會問些有用的問題,儘早開始對問題領域的深入理解。

    另一方面,知道別人將會接過自己的程式碼,就意味著自己要更守規矩。當知道別人在注意時,一定會更加小心。

   可能會有人會說,如果一個開發者專門應對某一個領域中的任務,他就可以精通該領域,並讓後續的開發任務更加高效。這沒錯,但是眼光放長遠一點,有好幾雙眼睛盯著某一段程式碼,是一定可以帶來好處的。這樣可以提升程式碼的整體質量,使其易於維護和理解,並降低出錯率。

    要強調程式碼的集體所有制。讓開發人員輪換完成系統不同領域中不同模組的不同任務。

    不要無意間喪失了團隊的專家技能。如果某個開發人員在某個領域中極其精通,不妨讓他作為這方面的駐留專家,而且系統的其他部分程式碼也對他開放,這樣對團隊和專案都很有幫助。

   在大型專案中,如果每個人都可以隨意改變任何程式碼,一定會把專案弄得一團糟。程式碼集體所有制並不意味著可以隨心所欲、到處破壞。

    開發人員不必瞭解專案每一部分的每個細節,但是也不能因為要處理某個模組的程式碼而感到驚恐。

   有些場合是不能採用程式碼集體所有制的,也許程式碼需要某些特定的知識、對特定問題的瞭解,比如一個高難度的實時控制系統。這些時候,人多了反而容易誤事。

   任何人都可能遭遇到諸如車禍等突發的災難事故,或者可能被競爭對手僱傭。如果不向整個團隊分享知識,反而增加了喪失知識的風險。

41.成為指導者。

         Knowledge grows when given!與團隊其他人一起共事是很好的學習機會。知識有一些很獨特的屬性;假設你給別人錢的話,最後你錢會變少,而他們的財富會增多。但如果是去教育別人,那雙方都可以得到更多的知識。通過詳細解釋自己知道的東西,可以使自己的理解更深入。當別人提出問題時,也可以發現不同的角度。也許可以發現一些新技巧-------聽到一個聲音這樣告訴自己:“我以前還沒有這樣思考過這個問題。”

        多數時候,成為指導者,是指在幫助團隊成員提升水平的同時也提高自己。這個過程不必侷限於自己的團隊。可以開設個人部落格,貼一些程式碼和技術在上面。不一定是多麼偉大的專案,即使是一小段程式碼和解釋,對別人也可能是有幫助的。成為指導者意味著要分享----而不是固守------自己的知識、經驗和體會。

       成為指導者。分享自己的知識很有趣--------付出的同時便有收穫。還可以激勵別人獲得更好的成果,而且提升了整個團隊的實力。

  • 如果一直在就同一個主題向不同的人反覆闡述,不妨記錄筆記,此後就此主題寫一篇文章,甚至是一本書。
  • 成為指導者是向團隊進行投資的一種極佳方式。
  • 結對程式設計是一種進行高效指導的、很自然的環境。
  • 為團隊成員在尋求幫助之前陷入某個問題的時間設定一個時限,一個小時應該是不錯的選擇。      

 42.允許大家自己想辦法

      “授人以魚,三餐之需;授人以漁,終生之用。”告訴團隊成員解決問題的方法,也要讓他們指導如何解決問題的思路,這也是成為指導者的一部分。

      給別人解決問題的機會。指給他們正確的方向,而不是直接提供解決方案。每個人都能從中學到不少東西。     

      用問題來回答問題,可以引導提問的人走上正確的道路。

43.準備好後再共享程式碼。

        完成一項任務後,應該馬上提交程式碼,不應該讓程式碼在開發機器上多停留一分鐘。如果程式碼不能被別人整合使用,那又有什麼用處呢?應該趕緊釋出出去,並開始收集反饋。

     通常情況下,提交的檔案應該與一個特定的任務或是一個bug的解決相關。而且應該是同時提交相關的檔案,並注有日誌資訊,將來也能夠知道修改了哪些地方,以及為什麼要做修改。一旦需要對變更採取回滾操作,這種“原子”提交也是有幫助的。 要保證在提交程式碼之前,所有的單元測試都是可以通過的。

     程式碼不執行提交操作的其他安全選擇:1.使用遠端訪問。 2.隨身攜帶。將程式碼複製到U盤、CD或DVD中。3、使用帶有底座擴充套件的膝上型電腦。4、使用原始碼控制系統的特性。在CVS和Subversion中,可以將尚未允許合併到主幹的程式碼,設定為開發者的分支。

     準備好後在共享程式碼。絕不要提交尚未完成的程式碼。故意簽入編譯未通過或是沒有單元測試的程式碼,對專案來說,應被視作玩忽職守的犯罪行為。  

44.做程式碼複查。

     如何進行程式碼複查:1.通宵複查,每個月進行一次恐怖的程式碼複查之夜。不建議這方式。 2.撿拾遊戲。程式碼完成編譯、測試,提交之前由其他開發人員“撿拾”起這些程式碼開始複查。並且最好進行輪換複查。3.結對程式設計。

     程式碼複查的一些基本問題檢查列表:

  • 程式碼能否被讀懂和理解?
  • 是否有任何明顯的錯誤?
  • 程式碼是否會對應用的其他部分產生不良影響?
  • 是否存在重複的程式碼(在複查的這部分程式碼中,或是在系統的其他部分程式碼)?
  • 是否存在可以改進或重構的部分?     

      還可考慮使用諸如Similarity Analyzer或Jester這樣程式碼分析工具。

    複查所有的程式碼。對於提升程式碼質量和降低錯誤率來說,程式碼複查是無價之寶。如果以正確的方式進行,複查可以產生非常使用而高效的成果。要讓不同的開發人員在每個任務完成後複查程式碼。

    程式碼複查需要積極評估程式碼的設計和清晰程度,而不只是考量變數名和程式碼格式是否符合組織的標準。

     同樣的功能,不同開發人員的程式碼實現可能不同。差異並不意味著不好。除非你可以讓某段程式碼明確變得更好,否則不要隨意批評別人的程式碼。


45.及時通報進展與問題。

    接受一個任務,也就意味著做出了要準時交付的承諾。不過,遇到各種問題從而導致延遲,這種情形並不少見。截止日期來臨,大家都等著你在演示會議上展示工作成果。如果你到會後通知大家工作還沒有完成,會有什麼後果?除了感到窘迫,這對你的事業發展也沒有什麼好處。

   如果等到截止時間才釋出壞訊息,就等於是為經理和技術主管提供了對你進行微觀管理的機會。他們會擔心你再次讓他們失望,並開始每天多次檢查你的工作進度。你的生活就開始變得像呆伯特的漫畫一樣了。

  &nbs