爲什麼要TDD(測試驅動開發)

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在Codurance,除非有非常有說服力的解釋,否則不管使用什麼開發語言,都是從測試開始的。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果直接空降到這樣一個環境,四周所有的人都是這麼做的,自然不會有太大的阻力。但在絕大多數工作環境中,真正這麼做的還是鳳毛麟角,那就要好好問問這個問題,爲什麼需要TDD。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在進行任何討論前,都要從一個問句出發才能避免空對空的胡天海吹:","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"要解決的是什麼問題","attrs":{}},{"type":"text","text":"?","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"TDD,或者說軟件匠藝要解決的是:如何才能讓軟件可以有長久的生命力,能夠應對不斷新增的需求,不拖業務的後腿,進而成爲業務的推動力。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Agile、DevOps、軟件匠藝其實都是爲了解決這個問題。而TDD更多的是從技術角度來提供答案。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"其中邏輯如此推演:","attrs":{}}]},{"type":"numberedlist","attrs":{"start":1,"normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"爲什麼軟件在初期能夠快速應對變化,但是少則一兩年後就迅速疲於應對?因爲隨着臨時方案的堆積(tech debt),代碼很快會難以維護。","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"怎麼解決?每次增加新功能時,都要審視現有代碼,通過","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"重構","attrs":{}},{"type":"text","text":"確保代碼質量不下降。有句話:代碼的結構需要能夠支持新功能順暢地滑進去(slide)。","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"爲什麼大多時候不敢重構?怕結構性地修改代碼會破壞現有的功能。","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":4,"align":null,"origin":null},"content":[{"type":"text","text":"所以需要有多層面的自動化測試。人工迴歸測試的反饋週期與軟件功能正比甚至多項式增加(考慮到功能之間的交互影響),無法保證快速的新需求響應。","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":5,"align":null,"origin":null},"content":[{"type":"text","text":"那找專人寫測試確保測試覆蓋率是否可以?僅僅自動化端到端的測試(end-to-end, 往往同義於黑盒或UI測試)可不可以?","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null},"content":[{"type":"text","text":"現實中維護這樣的測試成本過高,而且一套測試運行下來所需要的時間過長,難以輔助到日常的重構與開發。同時,單元測試(這裏特指針對最小代碼單元的測試,比如一個Java類)並不是想寫就能寫的,實際碰到的代碼大多根本沒有考慮到可測試性。","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":7,"align":null,"origin":null},"content":[{"type":"text","text":"因而,從測試開始開發,至少能保證代碼實現是可測試的,從而使得解決技術債務,確保快速迭代真正成爲可能。","attrs":{}}]}],"attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":8,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":8,"align":null,"origin":null},"content":[{"type":"text","text":"TDD實踐顯然還能帶來其它好處,比如用測試記錄軟件功能和基本單元的行爲,大多情況下提供更好的代碼質量(低耦合,高內聚)。但就我個人的思考來說,以上是最本質的可以追述到要解決的問題的邏輯推導。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":8,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":8,"align":null,"origin":null},"content":[{"type":"text","text":"那TDD難麼?難。一個沒有相關經驗的團隊,需要數月甚至半年的時間才能迴歸到最初的效率,這個是同事交流中得出的經驗數字;因此想要推行勢必要自上而下的支持。同時,除非經歷過軟件維護噩夢的組織,無法理解這種犧牲的必要性。但一旦過了這最初階段,整個團隊的交付速度會有質的提升,而團隊成員也不再疲於奔命,整日在修Bug、調試代碼,有精力去關注更多的新工作方式與技術,工作生活的平衡也能得到改善。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":8,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":8,"align":null,"origin":null},"content":[{"type":"text","text":"我先列下爲了解決同樣訴求的相關的話題:","attrs":{}}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":8,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"TDD","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":8,"align":null,"origin":null},"content":[{"type":"text","text":"重構","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":8,"align":null,"origin":null},"content":[{"type":"text","text":"金字塔式測試","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":8,"align":null,"origin":null},"content":[{"type":"text","text":"持續集成持續部署(CI/CD)","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":8,"align":null,"origin":null},"content":[{"type":"text","text":"單一主線開發(trunk based development)","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":8,"align":null,"origin":null},"content":[{"type":"text","text":"敏捷項目管理,看板,Scrum,精益製造","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":8,"align":null,"origin":null},"content":[{"type":"text","text":"極限編程(結對編程,快速反饋等等)","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":8,"align":null,"origin":null},"content":[{"type":"text","text":"基礎設施即代碼 (Infrastructure as code) ,不可更改的基礎設施(Immutable infrastructure),容器化","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":8,"align":null,"origin":null},"content":[{"type":"text","text":"隨時生產發佈待命(production ready anytime),功能開關(feature flag),功能迭代","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":8,"align":null,"origin":null},"content":[{"type":"text","text":"QA左移,安全左移,運維左移","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":8,"align":null,"origin":null},"content":[{"type":"text","text":"自治團隊","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":8,"align":null,"origin":null},"content":[{"type":"text","text":"軟件模塊化,微服務化","attrs":{}}]}],"attrs":{}}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":8,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":8,"align":null,"origin":null},"content":[{"type":"text","text":"所有的這些都構成了一個閉環,都是爲了解決如何快速滿足業務需求這一終極命題;同時不斷也有新的方法去應對新挑戰,補足現有的不足。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":8,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"推薦閱讀:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":8,"align":null,"origin":null},"content":[{"type":"text","text":"鳳凰項目:這是一本講述一位運維經理的偶遇宗師、傳授絕學、臨危受命,力挽狂瀾的個人英雄主義玄幻修真小說。我的這個介紹是爲了避免讀者真的拿小說去生搬硬套,但是這的確是我見過最容易讀進去的講述現代IT運維乃至IT項目方法的書籍。其中涵蓋了一些重要的精益製造、敏捷項目管理的知識;在通勤地鐵上很容易就能看完。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":8,"align":null,"origin":null},"content":[{"type":"text","text":"最重要的是,它爲困頓於現實泥沼的從業者漏出了一點希望的光亮。不願意改變是人類的本能,唯有看到了可能性,纔有動力去嘗試一個短期非最優的方向。","attrs":{}}]}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章