這條玉律在廚房裡面的說法是:“在開始做下一道菜前,先把當前這道菜上給客戶”。軟體開發最大的問題是一大堆事情並發進行,因此其中的一些工作就不可避免地會在後期被丟棄,這就意味著努力被浪費。
先專註於案例1;使它完全能夠正常工作;運行相關的測試;書寫與之關聯的文檔;嵌入所有相關的代碼;然後才能開始下一個任務;
非常明顯,這一條建議應該被包含在任何一個關於軟體開發建議的列表中;如果一個程式員在嵌入前做了所有適當的預防措施,進行了足夠的測試,是絕不會導致構建失敗的;如果構建失敗了,說明有人想走捷徑;
當編寫某個類的時候,你應該在腦海中有一個與之對應的使用案例,同時你應該只提供對這個使用案例來說是必需的方法。有時候程式員會考慮這個類潛在需要的一些功能,此時你應該把這些考慮作為注釋加在旁邊,但是決不要寫任何代碼,直到這些潛在功能真正被需要用到的時候;
- l 決不要在某個使用案例真正需要之前,去添加一個資料成員
這一條建議跟前面一條一樣,只是它的對象變成了類的資料成員。有時候可能看起來很明顯某條“使用者”紀錄將會在某處被使用;但是你絕對不應該去添加那個資料成員,直到你有一個具體的使用案例明確地要用到這個資料;
敏捷式軟體開發 (Agile Software Development)的精要就是應對不確定性和快速響應變化。在開發工作的前期,你可能沒有獲得完整的資訊,因此你應該儘可能延遲做決定;但是有的時候這個決定不得不做以便開發工作能夠繼續,你沒法再繼續等待下這個決定所需要的所有資訊了;此時,你應該根據手頭所掌握的資訊先做個你認為是最好的決定,然後在獲得更多的資訊之後,也要有勇氣去改變之前的決定;
品質的改進是永無止境的,因此你應該堅持不懈地尋求可以被改進的地方,同時要注意收集識別和定位軟體品質問題的方法。
敏捷開發是用來協助團隊應對未來之不確定性方法,但是對已經發生的事情,是不應當存在不確定性;所以各種類型的嘗試應該持續不斷地開展,同時每次嘗試都應該有紀錄,以此來度量其成效;
開發人員太容易把設計目標轉向技術可能性方面了。實際上最重要的是人,我們永遠不要忘了軟體的最終目的,是協助某些人更好的完成工作;
很多開發人員和經理們認為產品只是你提交給客戶的功能及相關代碼,其它一切都是不重要的;事實上測試代碼應該被作為產品不可分割的一部分予以考慮,它值得在設計階段就開始進行全面地考量,在很多情況下,甚至應該作為最終產品的一起提交給客戶;
測試案例本身能被用來澄清一個設計的最終意圖;而且在很多情況下,設計的缺陷會在完成測試案例的時候被發現。想想看在編碼之前先書寫測試案例的話,能有多少時間被節省下來。但是要記住:先寫用例1的測試,然後編寫用例1的代碼,這些都要在開始用例2之前完成;
坦白地說,這已經成了一個在任何軟體開發原則中都會被提到的陳詞濫調,因為它確實太重要了。發現並且消滅軟體開發過程中的浪費是一個永無止境的工作。任何不增加終端使用者價值的付出都是浪費,如果你不能確信它對終端使用者有什麼價值的話,很可能你將不需要它。
請理解這樣一個事實:一旦構建失敗了,項目團隊中的每一個人都會受到影響,因此沒有什麼事情比確保核心代碼能被正確構建和測試更重要了。我曾經看到過一些團隊允許構建失效延續幾個月,因為每個人都認為它是別人的責任,每個人都忍受痛苦,卻沒有人採取行動解決問題。在這方面一點小小的努力會使整個團隊都受益,應該成為團隊的共識。
大的,複雜的項目應該被拆分成一個個小的項目團隊,並且在小團隊內部進一步被分發到一個個程式員手上;但在這個過程中,決不能失去對整個產品最終目的和終端使用者需求的理解;人們應該時刻把目光聚焦在滿足終端使用者需求的目標上面。
組織代碼,使高度關聯的事物位於相近的位置,如果有可能的話,最好把它們放在一個類裡面。這是物件導向設計原則的規則之一 - 封裝,理想的情況下,所有在類外部的代碼,都不需要知道類的內部是如何工作的。有些程式員為了某種目的很喜歡在不同的檔案之間傳遞一些細節資訊,譬如為了保持所有相同的資料類型在一起,或者為了按照字母順序排列。諸如此類的操作會給系統帶來不必要的複雜性。所以指導原則是把不相關聯的東西分組,以此來降低系統的複雜度。
【譯者】有的人把這句話理解為Check in之前運行所有的單元測試,有的人理解為運行test cases,實際上個人認為這些都應該在check in之前運行。
從微觀層面來說,代碼確實應該按照最優方法來寫以避免無謂的浪費,然而對於超出方法層面的最佳化,則應該等到整個系統經曆了壓力測試之後開展,而且這種壓力測試是基於某個具體的使用者使用案例的。
如果只基於對靜態代碼的理解,就做出對系統整體效能的直覺判斷,幾乎總是錯誤的。相反,對整個系統的效能進行度量,識別出那些確實對系統效能有重要影響的1%的代碼,並且專註於最佳化這一部分代碼,才是王道。
當一個開發人員實現一個使用案例的時候,所有被改動過的,但是沒有改動完成或者沒有經過測試的代碼,都會產生代價。允許這些完成一半的變更持續存在幾天或者幾個星期,會顯著增加工作量被浪費的風險,因為其中很多半成品最終可能不得不重做。
假設有3個任務,每個需要1天來完成,若同時啟動這3個任務,在3天內每天都並發處理它們,這樣會導致9個工作單元的開銷。如果順序處理這3個任務,每天完成一個,在前面的任務完成之前,並不開始下一個任務,這樣只會導致3個工作單元的開銷;
這跟我們的直覺並不相符,直覺告訴我們當有3件事情需要處理的時候,可能同時開展3件事情的是比較合理的;然而軟體開發跟物理的建設並不相同,短周期的,快速的,完整的任務不僅會減輕認知上的負載,而且會減少幾個人之間未完成工作的相互衝突。
完成一個特定任務所需要的程式碼數,不同的程式員之間會有巨大的差異。程式碼數並不會告訴你太多關於任務完成情況或者代碼品質方面的資訊。導致代碼品質不同的因素可能多達200個,這使得計算程式碼數變得毫無意義;如果要計數的話,就用使用案例吧。
在應用這條規則的時候要小心謹慎,因為有些代碼實在是太脆弱了,這使得改變它們變得很困難,但是總體原則是你要使這些代碼跟真實的使用案例相匹配,所以不應該害怕去改變它們;一個資料成員在過去可能是一個整數,但是當使用案例需要它成為一個浮點數的時候,請不要猶豫,去改變它。
當涉及大塊不容易理解的代碼時,有一種傾向:“讓睡著了的狗躺在那吧”;其中一個例子就是在往一個類裡面添加新的方法替代老方法時,很多開發人員會保留舊有的方法以防萬一。這種情況下,我們應該額外付出一些努力去檢查老方法是否依然必要,如果沒有證據顯示非要保留它不可的話,就應該將其刪掉;
最糟糕的改動就是把一大段代碼注釋掉,然而卻不把它們刪除。被注釋掉的代碼,應該在單元測試成功運行之後,代碼簽入之前,立即被刪除。在任何時候添加代碼都是容易的,然而任何時候刪除代碼都是困難的,因此,如果在某刻,你認識到可能有些東西是沒有必要的,就應該額外花一點時間去確認這段代碼確實可以被刪除,這將提高代碼的可維護性。
一個例子是往設定檔中添加了太多的終端使用者看不懂的東西。
- l 除非你真正準備開始編碼,並且打算測試你的變更,否則不要設計
你應該對於系統將要做什麼,系統架構的目標是什麼有個粗略的理解,但是除非到了開發迭代允許某個具體的設計被實現並且測試的時候,你都不應該進行詳細設計,也不要把關於某個功能實現的具體描述寫下來。
詳細設計僅需要覆蓋剛剛好能夠滿足當前使用案例需要的內容。軟體開發中最大的浪費就是花了很多時間在不需要的詳細設計事宜上,或者是由於錯誤的假設而導致的重新設計。
跟物質的加工不同,軟體是能夠被很容易地進行重大變更的。實際上有足夠的證據證明,軟體本身相對於用來描述該軟體的設計文檔,更容易被改變。進一步說,就是軟體本身比說明文檔更能夠說明它是被設計來做什麼的。因此,你應該把時間花在直接實現上,這樣客戶就能夠親眼看到最終設計細節。如果你未能滿足客戶要求,不得不改變最初的設計,直接變更軟體本身要比變更說明文檔更加容易。更重要的是,當客戶看過系統運行以後,你所得到的關於他們希望系統如何啟動並執行資訊要清晰得多!
- l 在檢測和報告異常情況的代碼中,花時間添加一個完整的問題描述
程式員通常會懶得添加說明,以至於在拋出的異常中,只有非常簡淺的關於問題的描述。他們以為自己是唯一一個會看到這個問題的人,而且認為自己會根據這個含糊的描述想起該問題的詳細情形。事實上,由於不正確的,或者是不完整的錯誤描述導致的客戶支援開銷,比任何其它的原因都要高。所以對每一個錯誤資訊的描述,你都應該假設自己在對剛走進房門的,對編碼沒有任何經驗的陌生人解釋該問題。畢竟,終端使用者以及客戶支援部門,對編碼是沒有任何經驗的。
原文連結:
http://www.pmhut.com/26-hints-for-agile-software-development/comment-page-1#comment-10565