|
犯錯誤是最好的學習方式。 ──莎倫·德雷珀
背景
我們為客戶提供咨詢,剛開始做了很多敏捷的實踐,包括:持續集成、測試驅動、用戶故事需求分析、迭代開發等等之后,發現如果再想深入下去,就會面臨一些“硬骨頭”:遺留系統和開發設計能力的問題。在一些客戶那里,他們產品有10多年了,但是很少有人新加程序文件,寫代碼習慣于復制粘貼,都是在已有的類和函數上修修補補。團隊缺少追求好代碼的品質和能力,到處是大函數,上帝類(超大類,任何功能變化都要修改此類),重復代碼,混亂邏輯,開發和維護成本太高。作為一個顧問,如何才能從根本解決這樣的開發設計能力問題呢?
在ThoughtWorks,如果招聘了一個沒有經驗的開發人員,會把他們送到印度的TWU(ThoughtWorks University)培養2-6個月,OO訓練營是開發人員的主要課程之一。它專門用來訓練開發人員如何使用面向對象,如何進行測試驅動開發。通過這樣的訓練之后,開發人員可以很快的掌握面向對象開發和簡單設計能力,養成追求好代碼的品質。所以,我們也為客戶的團隊引入了TWU的OO訓練營活動。
活動方式
OO訓練營的培訓方式和我們傳統的“填鴨式”教育完全相反。它采用的是蘇格拉底式教學法,顧問不會給你任何標準答案,而是通過問題的引導,讓學員自己一步一步找到最佳的解決方案。我的OO訓練營的組織方式一般是:
一、顧問提出需求
顧問在訓練營活動會扮演著客戶的角色?;顒右婚_始的時候,會以客戶的身份提出一個需求,讓大家去完成。例如:要求建模一個長方形。
二、簡單設計
以分組討論方式做一個簡單設計,一般從如下三個方面進行設計。
- 類名是什么?
- 類的職責是什么?對于復雜需求,可能會要求畫一個簡潔的UML對象關系圖。
- 類的測試用例會有哪些,并且找到第一個測試用例
討論結束之后,每組介紹一下各自的討論結果。通過分組討論和顧問的引導,對建模一個長方形需求一般會得到如下的設計結果:
- 類名是: Rectangle
- 類的職責是計算周長和面積
- 計算周長的測試用例:
a. 正常場景。如果長是2,寬是3,那么周長是10
b. 異常場景,寬為0的情況。如果長是2,寬是0,那么應該拋出異常
c. 異常場景,寬為負數的情況。如果長是2,寬是-3,那么應該拋出異常
這些測試用例完全是由學員自己設計出來的,沒有標準答案。作為顧問只是引導大家,讓每組的測試用例更具體和全面。假設沒有一組學員沒有考慮到異常情況的測試用例,這時也也不用指出來,等后面代碼展示的時候,再指出這個問題,因為犯錯是最好的學習方式。
三、測試驅動(TDD)開發
學員根據設計和討論的結果,用測試驅動的方式進行結對編碼開發。要求先寫單元測試,寫完一個單元測試之后,運行測試失敗,然后再去寫業務代碼。如果沒有失敗的測試,不允許寫一行業務代碼。這樣嚴格的要求,讓大家養成測試驅動開發的好習慣。
兩個人一組使用結對方式進行開發,要求使用乒乓式的結對方法。假設是A和B進行結對開發,A先寫一個測試用例,編譯通過但是測試失敗。然后把鍵盤和鼠標交給B,B寫業務代碼,讓測試通過,然后為A再寫一個失敗的測試。通過這種乒乓的方式,一個人寫測試用例,一個人實現業務代碼,并且不停的變換角色。這樣兩個人可以很好的進行配合,互相給對方出“難題”,一個人在寫實現的時候,另一個人會思考下一個測試用例會是什么。
有的時候,我們會對團隊提出一些更高的要求。比如編程過程中不允許使用鼠標,一切都是快捷鍵操作,這樣能提高開發的效率。編程過程中不允許使用復制和粘貼功能,如果是相同的功能或者代碼,第一應該考慮到的是如何進行功能重用,而不是復制一遍,這樣可以杜絕這樣錯誤的編程習慣。
四、代碼展示和顧問點評
寫完代碼之后,每個人開始展示自己的代碼。這時,顧問就開始從代碼里面尋找代碼懷味道(Bad smell),告訴大家什么樣的是好代碼,什么樣的是壞代碼。壞代碼會有哪些危害,讓后讓大家重構。
例如:在實現長方形周長的時候,有人實現了getLength了getWidth方法,把長方形的長和寬的數據暴露出來了。那么這就是一個代碼壞味道(Bad smell),顧問會指出這個問題,告訴大家面向對象最重要的一個特征是封裝,不應該把數據直接暴露出來。因為數據暴露出來之后,一方面造成數據的依賴和耦合,另一方面其它代碼在調用長方形這個對象的時候,也許會拿到長和寬的數據自己進行運算,這樣就破壞了封裝,對象之間耦合增大,并且容易產生重復的代碼。然后提問大家,正確的做法應該是什么?
答案應該會是長方形不應該把長和寬的數據暴露出來,所有長方形相關的運算和邏輯都應該在長方形這個領域對象里面進行。這也正是面向對象設計的一個重要原則:Tell don’t ask的體現。通過這樣的引導的方式,帶領大家一步一步找到正確的面向對象設計方法和原則,同時糾正那些錯誤的編碼和設計習慣。
每次活動就是類似這樣的流程。顧問提出需求,然后是討論和設計,結對開發,最后展示代碼和點評。一輪結束之后,顧問又給大家一些新的需求,進行第二輪,如此一直的循環下去。
經驗和教訓
我多次為客戶的團隊組織過類似的訓練營活動。最長的一次堅持了3個月,每周2次,每次兩個小時,完成了OO訓練營的所有課程。堅持參加完這個活動之后,開發人員和技術Leader的都能真正的全面掌握面向對象設計方法和原則,并且把這些用到自己的項目中。下面是我的一些經驗和教訓:
- 活動時間安排。如果每次活動2個小時,一般是安排在下班左右,一小時工作時間和一小時個人時間。因為大部分團隊都有交付的任務和壓力,完全占用工作時間不現實。
- 家庭作業。由于我培訓的一些團隊技術基礎不是很好,大部分開發人員無法在2個小時內完成編碼任務。所以我會把沒有完成的任務留作家庭作業,讓大家在活動之后完成,這樣在OO訓練營的時候主要是進行設計討論和代碼的展示點評。這樣也有一個好處,每個人都會有時間進行獨立思考,對代碼進行重構產生一個更好的設計。
- 活動整個過程是以引導為主,讓大家自己進行編碼、重構和討論,自己解決問題,尋找設計的最佳解決方案。顧問只是擔任一個類似主持人的角色。
參考資料
如果你也想在自己的團隊或者公司引入這樣的活動,下面一些資料可供參考:
- OO訓練營資源
為了做好OO訓練營這樣的活動,需要事先設計好一些練習和案例。下面的書籍里面就有一些很不錯的例子,可以直接拿來練習。比如:《測試驅動開發》這本書里面的Money例子,《重構》這本書的影評出租店例子等等。也可以去網上找到一些訓練營的資料,我這里為大家提供一個咖啡機的案例,它有現成的用戶故事,可以直接拿來做OO訓練營。它的網址是:http://agile.csc.ncsu.edu/SEMaterials/tutorials/coffee_maker/index.html 。
- 參考書籍
顧問點評是一個很重要的環節。要求顧問首先自己是一個優秀的程序員,有豐富的開發和設計經驗,這時候才能去很好的指導別人。精通和掌握下面幾本書,是對顧問最基本的要求:
《重構:改善既有代碼的設計》Martin Fowler
《測試驅動開發(中文版)》Kent Beck
《敏捷軟件開發:原則、模式與實踐》Robert C. Martin
《代碼整潔之道》Robert C. Martin
關于作者
錢安川,ThoughtWorks公司高級軟件咨詢師、敏捷過程教練、資深講師、Team Leader、開發者、 BeiJing Open Party組織者和主持人。個人博客:敏捷開發訓練。
it知識庫:敏捷咨詢工具箱(二)──OO訓練營,轉載需保留來源!
鄭重聲明:本文版權歸原作者所有,轉載文章僅為傳播更多信息之目的,如作者信息標記有誤,請第一時間聯系我們修改或刪除,多謝。