測試驅動開發(TDD)已死?
一系列關於測試驅動開發(TDD)及其對軟體設計影響的對話,參與者包括 Kent Beck、David Heinemeier Hansson,以及我。
起源
一場引人注目的演講和部落格文章引發了一場對話,我們旨在了解彼此的觀點和經驗。
更多...這個對話是作為對David 在 RailsConf 的主題演講的回應而開始的,他對 Rails 社群中的 TDD 和單元測試感到不滿。隨後不久,他發表了一些部落格文章,其中第一篇宣稱 “TDD 已死”。
在此之後的幾天,我給他發了一個錯別字更正,他說他歡迎我對他的演講和部落格文章的看法。然後我們在 Skype 上進行了一個愉快而思考深入的討論。Kent 也和 David 進行了類似的討論,Kent 建議我們三個人繼續討論,並將對話公開。David 發推文提出這個想法,得到了許多積極的反應。
我們對這個系列沒有太多計劃,除了大致想法是進行半個小時左右的對話。我們主要是因為想了解彼此的經驗和觀點,我們自認為有很多其他人也想看我們。在早期的節目中,我們沒有接受問題,但在最後一期中接受了幾個問題。當我們進行這個對話時,我們很享受討論在部落格和 Twitter 上的持續。
我們要感謝 Thoughtworks,特別是 Wesley Clock,他幫助我們處理了組織視訊設備以及安排聊天時間的大部分後勤工作。每一集結束後,我都會寫下討論的摘要,供那些更喜歡閱讀而不是觀看的人參考。
1: TDD 與信心
2014年5月9日
我們討論了我們對 TDD 流程的不同經驗,以及 TDD 和自我測試程式碼常被混淆的方式。
更多...
會議記錄
David 舉起他對 TDD 和單元測試的三個主要問題展開討論:對於 TDD 和單元測試的定義混淆, 使用模擬物件驅動架構導致的測試損壞, 以及 TDD 的紅綠重構循環對他從未奏效的問題。我評論道,要了解 TDD 等的起源,了解歷史是有用的,因此Kent 解釋了 TDD 的起源。他開始在 Smalltalk 中試驗, 發現 TDD 對他的性格很適合。
我評論道,在我們首次在 C3 公司共事時,我們並未開始使用 TDD,但確保每次編程都將程式碼和測試一起交付。 Kent 說,程式設計師應該有信心自己的程式碼是正確的,TDD 是達成這一目標的一種(但不是唯一的)方式。 David 喜歡 Ruby 的設計目標是讓程式設計師快樂,並且贊成一種觀念:只有當你有了測試時,你才算完成了任務 - 但他不喜歡 TDD 作為達成目標的方式。 他認為不同的人有不同的大腦,因此喜歡不同的技術和語言, 他不喜歡 TDD 被認為與自我測試程式碼所帶來的信心混為一談。
Kent 談到了臉書最近的一次黑客馬拉松,他大約一半的時間使用了 TDD,另一半則不適用。 在可以使用 TDD 的程式碼中,他發現自己進入了一種愉悅的流程,但在其他部分卻感到更棘手。但在不使用 TDD 的部分,他仍然使用了回歸測試和短反饋迴圈。 他並不介意混合兩種風格,這就像同時演奏古典音樂和爵士樂一樣。 TDD 讓他想起了他在學校學習數學的方式 - 總是需要例子。
David 曾處於 TDD 流暢的情況下,但他的大部分工作並非如此 - 他的問題是,你願意為了達到那種流程而犧牲什麼? 許多人做出了糟糕的取捨,尤其是在使用大量模擬物件時。 Kent 認為這是關於取捨:值得讓中間結果具有測試性嗎? 他舉了一個編譯器的例子,其中一個中間解析樹可以成為一個良好的測試點,同時也是一個更好的設計。 但在回應 David 關於模擬物件的問題時,他說他很少使用它們, 他擔心那些經常使用模擬物件的人在進行重構時會遇到困難,而他發現測試可以使重構變得更容易。
我評論說,術語存在兩個問題,不同的事物被混淆在一起:第一,DHH對TDD的批評基於一個假設,即你必須在TDD中使用大量的模擬,但事實並非如此;第二,自測試代碼和TDD之間存在差異。TDD是實現自測試代碼的一種方式。David表示,他對看到人們將TDD描述為一種道德行為而產生了反應,結果是很多代碼因其希望實現隔離的單元測試而設計得很差。
我以時間警察的身份結束,並表示在下一個會議中,我們將探討TDD可能導致的損害,如果那確實是損害,以及我們如何判斷它是否是損害。
2:測試誘導的設計損害
2014年5月16日
David認為使用TDD導致了諸如六角形鐵路等方法,這是由於過度間接的複雜性而產生的測試誘導的設計損害。Kent認為這與TDD本身的質量和設計決策有關。
在觀看這個對話之前,您應該查看David準備的概要,以展示他所關心的設計損害的例子。您也可以觀看錯過的Jim Weirich探索六角形架構的方法的視頻。
更多...
會議記錄
我開始時提出問題。TDD是否會導致設計損害?產生的損害真的是損害嗎?我們如何判斷一個設計是否受損? David描述了他之前發布的概要。這是他看到的人們使用大量模擬進行TDD的架構的一個例子。應用程序的每一層都被分開,例如,可以測試控制器而不必與真實模型、數據庫或請求/響應循環交談。 對David來說,重要的不是具體的例子,而是為了更容易地進行隔離測試而需要的不必要的間接性和複雜性。
肯特表示,將測試誘發的損害歸咎於TDD就像開車到一個糟糕的地方,然後責怪車子一樣。 大衛展示的設計並不是由於TDD,真正的問題是這些間接性在某些情況下都是好的技巧,我們需要了解它們是否值得成本。 大衛不同意,認為一旦你跳上TDD的馬(或車),它就鼓勵你走特定的路線 - 這導致了一個一次測試的怪物。 肯特反駁說,這實際上是一次設計決策。TDD對設計施加了進化壓力,人們對於測試覆蓋範圍的粒度有不同的偏好。
肯特問大衛他想要用gist做哪些事情,以至於其結構變得困難。 ("如果它只是坐在那裡,誰在乎 - 當我想要改變它時,設計才真正重要")。 大衛回答說,代碼的大小與其易於更改之間有直接的相關性。所有這些間接性都必須保持同步, 10行代碼比60行代碼更容易理解和更改。 每一層間接性都帶來了很高的成本。 大衛接著說TDD的紅綠重構流程非常令人上癮 (肯特觀察到他是地球上最窮的毒品販子),這種上癮導致了人們做出這些糟糕的決定。我不同意這一點,認為這不是由於TDD而是由於對隔離的渴望, 六角形架構的本質是與其環境(在本例中是Rails)隔離。
大衛說人們想要隔離的原因是由於TDD, 他聽過各種對隔離的論點,但只有測試的論點有道理。 他認為有人想把一個rails應用程式變成命令行應用程式的想法是如此罕見,令人發笑, 同樣地,你不能只是將內存存儲換成對web服務的調用,因為它們具有不同的操作特性。 這些換能力的白日夢不是真正的目標-真正的目標是隔離測試。 肯特同意你不能把內存和web服務看待為一樣的("你可能認為你解耦了,但實際上,你真的沒有")因為故障案例是不同的。 元素之間的邊界將在某種程度上洩漏,"問題是我們願意花多少錢來獲得多少元素之間的解耦"。
肯特認為,程式碼從10行變成60行是一個內聚性問題。 大衛同意,但認為內聚性和耦合性通常是相對的。更高的耦合性通常是值得的,以獲得更好的內聚性。 肯特觀察到,消除外部依賴的其他方法,你也可以使用中間結果,這就是編譯器所發生的事情。 難以測試的東西表明你需要一個設計洞察力,通常有用的是站起來散步,找到導致更好且更易測試的設計的那些洞察力。 大衛同意測試可以導致更好的設計,但他說他的經驗往往也相反,沒有一個好的可測試的設計。 肯特指責大衛缺乏足夠的自信,也許你今天看不到這個洞察力,所以你必須在此期間取得進展,但他樂觀地認為他最終會找到它們。 大衛將這稱為「以信仰為基礎的TDD」-他曾經這樣想,但當他找不到理想解決方案時陷入了一個令人沮喪的循環中。 肯特澄清他不是在談論TDD,而是在談論一般軟件設計,這不是關於TDD,而是關於如何獲得反饋。 思考軟件設計是關鍵,因為當你獲得一個良好的設計洞察時,回報是如此巨大。 獲得這些洞察力與你的工作流程無關,而是與知道何時工作和何時休息,從其他地方收集影響,與其他人合作等事情有關。
我們最後說下次主題將探討在編程時如何尋求反饋的權衡。
進一步閱讀
- 大衛的gist 顯示了他關心的設計損害的示例。該gist基於Jim Weirich的演講中對六角形Rails架構的探索。
- 大衛的博客文章介紹了測試誘導的設計損害問題
- 「六角形架構」一詞最初是由Alistair Cockburn創造的,它也被稱為「端口和適配器」。
- 在這次聚會之後,我與我的同事Badri Janakiraman進行了另一次關於六角形Rails架構的性質和使用它的權衡的討論。
3: 意見回饋與品質保證
2014年5月20日
我們討論了在編程過程中獲取意見回饋的各種方式以及品質保證在向開發人員提供意見回饋中的作用。
更多...
會議記錄
肯特開場時說,關於TDD的決定涉及到權衡: "在某個理想的世界裡,我們將對我們的編程決定獲得即時、無誤的反饋"… "我每輸入一個按鍵,如果代碼準備好部署,它就會立即部署。" 但是這個理想目前是不可能實現的,所以問題是我們要從中退卻多少。 他接著列舉了權衡中的幾個限制。
- 頻率:我們希望多快獲得反饋 ?
- 真實度:我們希望紅綠燈信號有多準確?
- 開銷:我們準備支付多少成本?
- 壽命:這個軟件要存在多久,這既是概率也是時間。
這四個是他認為我們需要比較的限制。 "我們不是來這裡達成共識的 - 我個人的目標只是通過向願意以建設性方式批判我的人表達它們來理解這些權衡的一組人"
我概述了我們希望獲得反饋的三件事。
- 軟件對軟件用戶是否有用? 有時測試有助於這一點(例如工資計算),有時則不(例如HTML渲染)。
- 我有沒有搞砸任何事情? "這就是自測代碼…是多麼的救命。 我想要看到每個測試至少失敗一次。
- 我的代碼庫是否健康? 這樣我就可以繼續快速建立東西。當你不確定誰會接手代碼時,這一元素變得更加棘手。
大衛提出了TDD的成功導致忽視QA的話題。 許多商店採用了TDD並且取消了QA, 直到幾年前,Basecamp才有QA。 他認為 TDD使程序員變得過於自信,以至於他們覺得不需要QA。 儘管舊模式已經破裂,但擺盪太遠了: "我認為你無法在沒有一個不是你自己的人測試的情況下,工作在任何具有實質品質並產生優秀軟件的項目上。" 這令人失望,因為他見證了有一個QA人員介入是多麼有效。
另一個問題是,要了解權衡,就必須了解成本,所有關於TDD的談話都是關於好處。 對成本的忽視是人們無法理解測試誘發損害的原因。 權衡的連續性也適用於其他事物。考慮可靠性的成本:從99%到99.999%的成本是呈指數增長的,而不是達到99%。 我們還必須考慮到關鍵性。對於太空梭和心臟起搏器來說,高可靠性非常重要,但對於一個探索性的網站來說是錯誤的。 不寫一行生產代碼而不進行測試的規則不符合關於關鍵性的權衡。
肯特想回到QA的問題,他認為與QA的舊關係是有問題的。 他辦公室裡唯一的一件Facebook紀念品是一幅寫著“Facebook裡沒有什麼是別人的問題”的海報,他覺得Facebook在這方面做得非常好,特別是對於一家如此大的公司。 直到最近,Facebook才有了QA,程序員們承擔起了這個責任。 “這是一個‘與什麼比較’的問題?”與擁有有效的QA相比,沒有QA更糟糕,但沒有QA比舊的有問題的關係更好。 我補充說,在Thoughtworks,我們幾乎在所有的項目上都有QA。 我還覺得90年代的重大轉變不僅僅是擺脫了有問題的對立關係,而且還擺脫了手動腳本測試。 而且,可以不需要QA的初創公司也是一件令人振奮的事情。 大衛認為,明智地權衡QA和初始速度是好事,但有些人把程序員測試進行得太遠,不明白探索性測試的價值。 如果開發人員認為他們可以創建高質量的軟件而不需要QA,那是錯誤的,你的測試可能是綠色的,但當它投入生產時,用戶會做出你意想不到的事情。
大衛說,最糟糕的情況是開發人員不參與客戶服務。 許多程序員不想值班,因為這很單調,但這也是一個反饋循環。 有綠色測試的代碼可能是低於你想要的水平的高原。 肯特認為我們應該在綠色條中添加一些紅色像素來提醒我們這些限制。 “值班是教你你沒有寫的測試的反饋循環。” Facebook的程序員必須值班,每個人都抱怨,但他們無法擺脫這一點。 一旦你覺得自己不再犯錯,那就是一個錯誤,你停止成長。最終,“世界不會讓你假裝你不再犯錯。”他寧願早些付出在凌晨2點的電話中發現問題的代價。
我結束觀察到我們沒有更多討論測試成本(大衛先前提到的第二點),建議我們下次再來看看。我也提到,巧合地,今天我的網站上有一篇 Mike Bland 發表的文章正好探討了這個主題。
4: 測試成本
2014年5月27日
我們討論了一些測試和 TDD 的缺點:你可以做過多的測試嗎?團隊將測試價值化是否比對功能代碼更重要?
更多...
會議記錄
大衛開始說:"要談論權衡,你真的必須了解缺點,因為如果沒有缺點,就沒有權衡。" 他繼續說,TDD 不強迫你做事情,但確實會推動你朝某些方向發展。 他想提出的第一個問題是過度測試。通常有人說你不應該在沒有失敗測試的情況下寫代碼,一開始這似乎合理,但它可能導致過度測試,例如,每行生產代碼有四行測試代碼。這意味著當您需要更改行為時,您需要更改的代碼更多 . 肯特曾說過'你不是為了寫測試而付費,你只需要寫足夠讓自己有信心的測試' - 所以他問肯特和我是不是在每行生產代碼之前寫測試?
肯特回答說:"這取決於,這將是我對任何有趣問題的答案的開始。" 他們在 JUnit 中對測試先行非常嚴格,並且對結果感到非常滿意 - 所以他認為當您使用TDD時,您不總是會過度測試。 赫伯·德比提出了增量覆蓋率的概念 - 這個測試提供了哪些獨特的覆蓋率?沒有增量覆蓋率的測試應該被刪除,除非它們提供某種溝通目的。 他說他經常會寫一個系統測試,寫一些實現它的代碼,進行一些重構,最終棄用初始測試。許多人對棄用測試感到驚慌,但如果它們沒有為您帶來任何好處,您應該這樣做。 如果同一件事以多種方式進行測試,那就是耦合,而耦合的代價是高昂的。
我說我確信有過度測試的代碼,確實如果有人這樣做,那會是 Thoughtworks,因為我們有一個強大的測試文化。很難把握好數量,有時你會過度,有時你會不及。我期望偶爾會過度,這不是件值得擔心的事情,除非它太大了。 在每行代碼都要進行測試的觀點上,我提出了一個問題:"如果我搞砸了這行代碼,測試會失敗嗎?" 我有時故意註釋掉一行或反轉條件並運行測試,以確保其中一個失敗。 我另一個心理測試(來自肯特)是只測試可能出錯的事情。 我假設庫可以工作(除非它們真的很怪異)。我問自己我是否可以搞砸對庫的使用,以及錯誤的後果有多嚴重。
Kent 宣稱,測試代碼與生產代碼行數比是一個虛假的指標。 對他來說,一次形成性經驗是看 Christopher Glaeser 編寫編譯器,他每行編譯器代碼有 4 行測試代碼 - 但這是因為編譯器有很多耦合。一個更簡單的系統會有更小的比率。 David 說,檢測將一行代碼註釋掉意味著 100% 的測試覆蓋率。思考可能出錯的地方是值得探索的,Rails 的聲明式語句不會引起足夠的故障而值得測試,所以他對不到 100% 覆蓋率感到滿意。
我回答說,“如果你不能自信地更改代碼,那就是你沒有足夠的測試(或者測試不夠好),” 和 “太多的跡象就是每次你改代碼時,你覺得你花在改測試上的時間比改代碼還多。” 你想要處於金髮熊的區域,但這需要經驗,知道你和你的團隊往往會犯哪些錯誤,哪些不會造成問題。 我說當我對自己的立場不確定時,我喜歡“我能註釋掉一行代碼嗎”的方法,這是一個起始點,但當我在一個環境中工作更多時,我可以想出更好的啟發法。 David 認為這種調整在穩定的產品團隊和將代碼交給未知團隊的諮詢團隊之間是不同的,因此需要更多的測試。 Kent 說學習測試優先的紀律是好的,這就像開著四輪驅動低檔在開發的棘手部分。
David 提出了下一個問題:許多人過去認為文檔比代碼更重要。現在他擔心人們認為測試比功能代碼更重要。與此相關的是 TDD 循環中重構部分的低調。所有這些導致了對重構和保持代碼清晰的能量不足。 Kent 描述說他剛剛經歷了一段時間,他丟棄了一些生產代碼,但保留了測試並重新實現它。他非常喜歡這種方法,因為測試告訴他新代碼是否有效。 這引出了一個有趣的問題:你寧願丟棄代碼保留測試還是相反?在不同情況下,你會有不同的答案。
我曾經遇到過這樣的情況,閱讀測試幫助我理解程式碼正在做什麼。我認為兩者之間沒有一個比另一個更重要 - 整個重點是在出錯時進行雙重檢查,以防止不一致。 我同意大衛的觀點,有時我感覺到團隊會犯下更糟糕的舉動,將更多的精力放在測試環境中,而不是支援使用者,測試應該是達成目標的手段。 當我澄清程式碼時,我會感到一股多巴胺,但我的最大興奮點是當我需要新增功能時,認為這將會很棘手,但結果卻很簡單。這是由於乾淨的程式碼,但清理程式碼與得到多巴胺衝擊之間存在一定距離。 肯特展示了傑夫·伊斯曼的一個比喻,這個比喻很難用文字描述。他從大型設計簡化中得到了滿足感。 他認為解釋新測試運作的價值很容易,但很難陳述清理設計的價值。
大衛說我們經常把注意力放在可以量化的事物上,但你無法把設計品質化為一個數字 - 所以人們會優先考慮低於列表的事物,如測試速度、覆蓋率和比率。這些事物是誘人的陷阱,我們需要意識到它們的誘惑。 他對Cucumber非常反感 - 把測試環境的美化放在生產代碼之前。只在與非技術利益相關者一起撰寫測試的虛構甜蜜點中有用。 以前重要的是推銷TDD,但現在它已經征服了一切,我們需要探索其缺點。 我不同意TDD佔主導地位的觀點,聽說很多地方尚未採用。
進一步閱讀
- 關於誤用測量的主題,可以參考帕特·庫亞的文章適當使用指標。
- 我已經寫了更多關於測試覆蓋率的使用與誤用。
5: 回答問題
2014年6月4日
我們回答了觀眾的問題:有哪些TDD的開源範例存在,什麼變化會使我們改變對TDD的使用,以及它對經驗不足的開發者的運作效果如何。最後,我們總結了我們對TDD健康狀況的看法。
更多...
會議記錄
我們將以挑選並回答觀眾提交的一些問題的方式來結構這次聚會。 David 首先從 Mike Harris 提出的問題中挑選一個,他詢問有哪些使用了 TDD 的開源項目,並且要求示例中有測試誘發的設計損壞或者正確使用了 TDD。David 回答說沒有好的例子,這就是這類辯論的問題之一。 一般來說,我們沒有好的應用示例,因為開源貢獻者通常會在私有應用程式和開源的常見框架和庫上工作。 因此,我們在進行這些討論時會有不同的上下文, 這往往會使看起來像是有更多分歧,而實際上並非如此。當你有真實的代碼而不是哲學原則時,人們會聚在一起。 我們所擁有的代碼示例只是一些小的例子,而不是人們實際正在工作的東西, 因此,你必須通過演示來理解人們 - 這就是為什麼他使用了 Jim Weirich 的示例來說明設計損壞。對於良好的 Rails 代碼,他建議查看展示了標準測試方法的 Rails 書籍。
我評論說理解真實代碼需要大量的努力。我對我們的代碼庫進行了一些挖掘,但這需要很多時間,即使這樣,理解也不像與團隊一起工作那樣。 Kent 說 JUnit 是一個嚴格使用了 TDD 的項目的示例,而且結果很好。 但這並不是這次討論的好例子,因為它具有清晰的接口,這為 TDD 提供了一個理想的點。我們在這裡討論不同類型的應用。 如果有人有好的例子,他們應該寫下來。
David 說我的評論說明我們不能把編程當作一門科學 - 我們無法客觀地評估技術。 這並不意味著辯論沒有價值。我們無法得到一個明確的答案,這是你的工作來弄清楚什麼是有道理的。 Kent 同意我們無法重複實驗,但說我們仍然可以以科學的心態從個人角度來看待事物。我們可以根據自己的經驗嘗試事物,但不能得到普遍的答案。
肯特挑選了下一個問題(由格雷厄姆·李提出):我們寫軟體的方式可能會改變什麼,使得對肯特和馬丁來說測試驅動開發(TDD)變得多餘或過時?以及對大衛來說,TDD 的執行方式可能會改變什麼,使其對他有用? 肯特回答說,他的 RIP TDD 文章 指出了他的立場(雖然帶有些許諷刺)。TDD 可以解決幾個問題,首先是信心問題。 TDD 還讓他能夠逐步分解問題,處理特定情況,而不必一次解決所有一般情況。 他不準備因為困難就放棄 TDD。
我認為對我而言,關鍵不在於使 TDD 變得過時的改變,而在於 TDD 在不同情境下的適用性。我曾經以一種平靜的「快速不慌不忙」的方式遵循 TDD,我在這樣做時不斷遇到了良好的設計。 我現在的大部分程式設計是關於我的網站工具鏈,雖然我逐步進展,並擁有完整的回歸測試套件,但我並不覺得 TDD 適用。但當我建立 infodeck 代碼時,有許多應用行為是 TDD 有效的。 「有些情境非常適合 TDD,有些情境則不太適合」。人們將其個性帶入了這個情境中。
大衛說他的經驗類似。他是通過 TDD 介紹到測試中的,他喜歡這樣做,並試圖將其應用於所有事情,但他慢慢意識到 MVC 網絡應用程序中的許多領域並不適合 TDD。 這並不意味著 TDD 對一些情況無效,只是這些情況在他的工作中所佔比例很小。 但放棄 TDD 並不意味著他想要放棄自我測試的代碼 - 這一直是他看重 TDD 的價值所在。
我認為這正是某人應該採用TDD(或任何技術)的方式。試試看,過度使用它,找到適合自己的模式。然後再深入一點:「tdd是自測代碼的入門藥物」。肯特說,他不在乎人們在完成這種流程後的工作流程。他對使用TDD的經驗與大衛的不同。他發現在開發過程中有時會遇到難題,然後想到一個具有某個協議的對象,可以簡化事情。TDD讓他能夠快速獲得對這樣一個想法的反饋,嘗試使用API的示例和實現它。他還發現了TDD不適用的情況。然後他發現按下Command-R可以獲得反饋,但他希望能夠看到簡化的對象並嘗試使用TDD。
我挑選了下一個問題(來自Tudor Pavel):TDD如何與經驗較少的開發人員合作。我回答說,TDD迫使人們做小塊並幫助他們將界面與實現分開。它並不能保證有很好的結果,因為沒有經驗,你無法做出良好的設計。當經驗較少的人們進行TDD時,他們通常不會進行足夠的重構,導致次優化的設計。你不能將經驗較少的開發人員的輸出與經驗豐富的開發人員的輸出進行比較,你必須將其與該經驗較少的開發人員在沒有TDD的情況下所做的進行比較。雖然我們無法衡量這一點,但似乎是有利的,並通過重構使自測代碼庫更容易改進。因此,TDD為您提供了一個良好的起點。
大衛說這是他從TDD中獲得的價值。他從TDD開始,發現它是一個很好的訓練輪,但他認為討論還不夠深入。當人們說你必須向新人提供簡單、直接、誇張的建議,否則他們不會這樣做時,他感到懷疑。這表明了對所教內容的信心不足。我同意不喜歡教條式的語句。如果我描述的事物找不到反對的論點,我會感到懷疑。然而,有一個扭曲的地方是,我們必須不斷地為新人重複基本知識:有些人抗拒重複基礎知識。
大衛認為這就是我們現在進行這次對話的原因。當人們描述TDD時,他們會在基礎上添加自己的理解,經過十年的這樣,你會發現自己已經離開了最初的地方,並且不是處於一個好的位置。 你需要按下重置按鈕,這是一種粗糙但有效的方法。當他說TDD已經死了,他指的是目前的這種變異 - 我們必須回到基本原則。 肯特說他對大衛原始的主題演講的直覺反應就在那個水平上。程序員通常會做同樣的事情很多次,把事情搞得太複雜,並堅持在工作中使用功能失調的系統。他很樂意重啟到基本原則,但不想失去人們對過去十年編程期望的演進。你應該能夠感到自信,指出進步,進行有效的技術合作。他現在感覺自己可以全神貫注地工作,這是他剛開始職業生涯時無法做到的。
大衛認為幾件事情同時發生了:TDD、XP和Ruby。人們嘲笑編程應該是有趣的概念,但他想繼續發展Rails時,他想堅持這個概念。現在他認為Ruby世界視這種快樂為理所當然 - 這些事情已經取得了勝利 - 敏捷也是如此。 我不同意敏捷取得了勝利 - 是標籤贏得了勝利,但許多人說他們在做敏捷,但實際上不是這樣。這對於這種事情是典型的,我稱之為語義擴散。最大的勝利在於我們現在能夠在客戶那裡公開地進行敏捷。 大衛觀察到其他事物也存在這種重啟問題 - 十年後你會得到大量的瑕疵。他舉了Pinkberry的例子,起初只有兩種口味,但後來出現了各種各樣的口味,就像其他冰淇淋一樣 - "大多數人無法放下好主意." TDD和敏捷現在非常廣泛。自稱在做敏捷的人做相反的事情。 肯特說他沒有看到大衛看到的TDD的問題。他始終從他的工作中的第一原則應用TDD。
肯特欣賞大衛引起了人們對TDD存在一些帆船藤壺並需要一些刮擦的注意。 大衛說他在Rails中也看到了類似的問題。他以基本形式使用Rails,對他見過的某些Rails使用方式感到震驚。 肯特記得第一次OOPSLA,當時XP受到關注,吉姆·魯姆保說你在十年後將不會認識到XP的發展,他是對的。 我說這就是成功的樣子,另一種情況是事情沒有起飛。很難判斷某件壞事是由技術內在的某個因素引起的還是由於技術的誤用。我們所能做的就是不斷重複基礎和好的教訓。 大衛同意說:“你要么英雄不再,要么成為壞人。” Ruby是關於編程的好思想的重啟。功能編程是另一個重啟。這些重啟是健康的。 他對Rails和TDD持續了多久感到印象深刻。 在Rails之前,
肯特一直沒有找到時間,他可以將問題的一部分分解成一個有用的抽象,他可以使用TDD。 他想要探索達成整體自我的程式設計的其他途徑。他將繼續透過實驗來探索:做得太多、不夠、找到剛剛好的區域,並理解為什麼。 他明確反駁了大衛的看法:TDD並不已死,但他很高興大衛點燃了它,讓它像鳳凰一樣浴火重生。
大衛說他開始這個討論是因為人們不願討論TDD無法發揮作用的案例。他們感到不舒服或沒有信心,但被告知他們必須使用TDD。他希望開放可接受的反應範圍,以便我們可以討論TDD何時適用何時不適用。 網上有很多人談論TDD有多好,但人們害怕說對他們不起作用。對於大衛來說,重點是自測代碼,當我們質疑TDD時,我們不希望失去這一點。
我總結說(正如我在開始前懷疑的那樣),我們在許多方面都是同意的。我們都非常重視自測代碼,我們都同意TDD在某些情況下是有價值的,我們可能在多少情況下持不同意見(雖然很難真正判斷)。 一切仍然歸結為一點,即如果您從事軟體開發,您必須思考,您必須建立出對您和您的團隊有用的實踐,您不能盲目地採用任何技術。您需要嘗試它,使用它,過度使用它,並找到對您和您的團隊有用的方法。我們不是在進行規範化的科學,所以我們必須根據自己的經驗工作。

要加入此對話,請在推特上使用#isTDDDead標籤。
我們已經為所有這些討論添加了音頻,您可以通過Thoughtworks播客提供的itunes或soundcloud來獲取。
如果你喜歡這個視頻,你可能會喜歡與巴德里·賈納基拉曼(Badri Janakiraman)進行的這次對話,我們在其中更深入地討論了六角形架構,使用 Active Record 還是 Data Mapper,以及將 Rails 視為平台還是一套組件。
這些頁面,包括我們對話的記錄,已經被翻譯成韓文。