雜談 - 關於設計:TDD 邪教論


雜談系列其實就是一時性起隨手亂寫的心得文,
主要談談最近聽看到的一些議題
也跟開發有關,有興趣隨意看

起源

日前有篇國外文章條列了一些關於軟體開發的看法
其中就有提到 TDD 是一種邪教

本來我覺得也就那樣吧
每種手段的好與壞每個人基於不同情境、經驗其實就會有不同想法

TDD 邪教論其實也不是一天兩天的事......

結果想不到還真的能引發一些討論,
然後台灣的一些網路社群也開始跟著討論測試要怎麼搞
當然也確實不激烈,不如當初 TDD 剛出來的時候很常會戰到血流成河的景象

那麼我也來談談我的看法好了
其實所有的設計或開發手段
你都應該理解其背景、解決問題的思路
你才能有比較客觀的判斷

TDD 基本原理和思路

TDD 的本質是希望測試能領先於實際開發,
然後藉由測試代碼完成系統的 scaffolding
用測試去對系統塑形之後再把實際程式寫出來

而經歷一段開發週期之後,可能系統會需要進行重構
這些測試也能夠當作重構途中的一些檢查點來保護你不會從鷹架上摔死

這些屬於 TDD 原始的目的和基本性質

TDD 的矛盾所在

關於重構這件事

其實很多的系統開發途中遭遇的重構本質上是一種對問題理解的改變。

這並不是一種「強化」而是一種根據實作面上的需求改變的設計變更所導致。

對於這種情況,先前的設計本質上其實是一種 false design
而基於這些 false design 所設計的 test case 當然也只會是一堆 false design

這些 test case 不僅不會起到鷹架的作用,反而會變成陷阱和絆腳石

你可能會需要花大把時間去跟這些 test case 做"妥協"
為什麼要妥協呢?設計改了 test case 一併改就好了不是嗎?

事實上,你可以這麼做

但相對的,你傷害了 test case 的權威性

如果修改 test case 的事情可以輕易的一而再,再而三的發生
那麼日後對 bug 的理解可能就會優先懷疑 test case 是 false design,從而喪失我們設計 test case 的價值

所以某種意義上 TDD 其實是一個存在矛盾的方法論。

test case 之所以可以做為系統穩定性的錨點,其原因就在於它是基於一個成熟穩定的設計和需求理解設計出來的代碼
而走在開發流程最前緣的階段,不可能是成熟穩定且理解完備的

來回覆一些比較有趣的問題

這些問題跟文章核心不見得有關,但是就很有趣

大量但小比例的 test case 失敗需不需要全部 review

其實這是不可能的,你沒有那個時間可以 review 所有的 failed case

但是我有發現一些比較有見識的回覆,大意是說
「其實大量 fail 很常見,但是你只需要少量的修改就能修復所有的 fail, 所以不需要全部 reivew」

這個概念源自於 failed is clustered, 簡單來說就是這些 failed 都是同一隻 bug 導致的

學理上和實務上都正確

但是用在這裡其實就倒果為因

這件事正確的前提在你的 failed 是 true negative,也就是他是真的被你弄壞的。

而如果你的 test case 落在 false negative 的區域,他就不適用這個道理
因為這些 failed case 最後會被標上 not a bug,也就沒有所謂同一 bug 導致 failed cluster 的現象。

需求變,測試變,天經地義

但是你會發現有的測試需要改有的測試不用,這是為什麼呢?

喔,因為有的測試跟需求變更的功能有關,有的無關。

那麼,你怎麼知道被你修改的 test case 是本來就應該有關的呢?

再更清楚一點說,test case 和變更之間的 dependency 是不是值得考驗的一件事?

退一步說,一次需求變更設計和實作會一次就到位嗎?

#software engineering #software design #tdd #test







你可能感興趣的文章

Styled Components

Styled Components

MTR04_0723

MTR04_0723

ES6(let 與 const、Template Literals)

ES6(let 與 const、Template Literals)






留言討論




Talisker Aug 22, 2021

我認知的重構,並不會改變任一個既有測試的結果,所以文中所說的重構應該是一種特別的需求變更。
既是需求變更...

  • 若涉及業務邏輯變化 ---> 修改測試就是很正常的事
  • 若涉及程式設計變化 ---> 為該設計寫新的一組測試,部分業務邏輯沒有變化也可直接複製舊的測試,並做好新舊切換

若是這樣規範,新設計不會有空間去跟舊設計的測試做妥協,因為新舊設計物理上是由不同的兩組測試分別負責。

結論上說,這跟TDD與否應該是沒有甚麼關係的,這更像是測試規範不佳所可能導致的問題。


另外,時常修改測試而傷害其權威性的說法,我有點理解不能,有兩點問題:

  1. 權威的程度 (我認為: 需求 > 測試 > 實作) ---> 因為需求而修改實作去影響測試,不應該解釋為實作傷害測試的權威,而是權威上顯示需求 > 測試,這是正常
  2. 時常修改 ---> 這若不是客戶時常做變更就是需求分析環節有問題,簡言之這是人的問題,非任何方法論能解決

轉念想,癥結點或許還是重構的定義,若這樣的改動是重構,而非源於需求,那1確實可解釋成實作傷害測試權威。
但我認為,這並非重構,更像是發現先前的需求 (以當下角度) 並沒有實現完好,而再追加的一種需求 (為填補舊實現與真實需求的落差)。

CHChang810716 Aug 24, 2021

若這樣的改動是重構,而非源於需求,那1確實可解釋成實作傷害測試權威

估計你應該有想過單個 cycle 的外部需求不會讓設計和實作一次到位的問題
所以這我就不多說了,其實這篇文章很大成分要講的就是這個問題

若涉及業務邏輯變化 ---> 修改測試就是很正常的事

頻繁修改測試必然會導致開發端對測試不信任
「無論是基於任何理由修改的測試」

如果開發者發現他比壞掉的 test case 更清楚需求是什麼的時候
他就不會相信下個壞掉的 test case 是他弄壞的。

所以需求變測試跟著變
理論上對,但是一個需求變更下來,
你怎麼完全肯定要被修改的 test case 有哪些?
其實是不能的,
這在執行上導致的結果就是為新的需求加新的 case 被影響到的 case 等壞了才回去改
或者乾脆不改了,遇到壞的 case 直接刪掉

這些被修改的 case 其實就是開發反向監督 test case 的結果

TDD 的概念說這是必然的所以沒必要在這個問題上深究
這種 test case 被動調整的現象你沒辦法根本上解決

事實上,確實沒有辦法根除

但是這裡有個數量問題
根據 test case 的設計方式,這個數量是有機會降低的
這篇文章指出的點就在於 TDD 一定程度上會導致這些被修改的 test case 數量放大

如果你能接受越早期寫出來的 code 幾乎保證越爛這個概念的話
那後面這一段我差不多相當於在說
TDD 會導致測試設計不佳

我不知道你的測試規範是否相當於測試設計
如果是的話那這就是我對你的論述核心的回應

不知道這樣有沒有回應你的疑問。

Talisker Aug 24, 2021

感謝你的回覆。

我想我們應該能有幾個共識:

  1. 文中所說的改動並非重構
  2. 越早期寫出來的 code 幾乎保證越爛
    照你的回應,我認為你比較在意的是2。

TDD 說先寫測試再寫程式,其他方法的測試即便是比較晚寫 ---> 那總也還是要寫的吧?

一旦寫了,早晚也會遭遇你說的「越早期寫出來的 code 幾乎保證越爛」的問題
所以「TDD 一定程度上會導致這些被修改的 test case 數量放大」也只是因為它比其他方法早寫了這麼一點時間 (1 ~n cycles),
以這個觀點這樣去說「TDD 會導致測試設計不佳」我認為只對一半,應是 TDD 會導致測試設計較為不佳。
而這也並非全是壞處,應視為一種特性,端看專案場合適不適用而已。

TDD 以我的觀念來說,最大的幫助是促使團隊先完善思維 (當然也是依當下了解程度) 再寫程式,這是採用團隊最起碼能獲得的好處。
雖然早點寫的測試被修改的可能性比較高,但資深的決策者之所以採用必然是判斷於該專案場合套用是利大於弊,更有相應的使用規範例如近幾個cycle被修改的test case比例超標,可以幫助團隊反思與客戶的溝通或是需求分析的可能問題、甚至這個cycle沒法到位的需求設計和實作,可以根據經驗部分採用 TDD 先寫測試的方式,不需要每個 test case 都用 TDD。
使用 TDD 的方式根據情況應該有很多可以做規範去適應團隊和專案。
一個方法的特性,在不適合的專案、沒有適合的利用規範、套用到不適合的範圍時,都會變成一場災難。


頻繁修改測試必然會導致開發端對測試不信任「無論是基於任何理由修改的測試」

這我並不認同,但這或許是我的想法比較怪 (?),姑且分享一下。

我認為,在需求的面前,開發跟測試不需要有任何的信任
開發負責實現需求,測試負責測試實現,兩者獨立為需求服務。

就是這麼簡單,我不覺得確認測試有沒有符合需求是浪費,報了錯它就是一個不能省的功。
即便有上百個測試失敗,你也只能選擇先檢查實作的改動,找不出問題那就負起責任去逐個檢查每個測試。
(但我認為TDD下,你的測試在做改動前應該都已經寫完或改完了,幾乎可以確定是實作的問題)
(另一個層面是一個改動能觸發上百個失敗,說明改動可能需要再進行更細緻專一的切分,並調整相關規範)
若寫了測試出問題卻連這個功都想省,那其實一開始就不該寫任何測試,完全相信實作就好。

至於你說的「開發反向監督 test case」在我看來就只是一種對 test case 的維護方式,這我認為存在但不是 TDD吧?
TDD 的方式下你這次的改動也應該先寫 (其實是改現有的) 好 test case 再去改,不存在反向監督的可能。

當然,上面是理想的情況,執行上總是會漏掉幾個沒寫沒改的 test case。
這也可以幫助團隊檢討測試規範,像是怎麼讓開發者更容易地找到一個改動相關的所有測試、或某類 test case 取消使用 TDD 等等。
但我想我們不能以此去說 TDD 怎樣怎樣,因為我們在這幾個 test case 上對這次的改動來說並不是用 TDD 進行的。

還是我對 TDD 先寫測試的理解有誤,只有新建的方法要先寫那麼一次,現有的都不該先改測試再寫?
(這點如果有誤再麻煩指出,我會解釋為使用 TDD 的一種個人規範)

CHChang810716 Aug 24, 2021

文中所說的改動並非重構

我第一篇就有注意到你想講重構的定義問題
但是你會發現即便我們釐清了這個名詞的定義對這個主題的討論其實沒什麼幫助
所以我選擇不去討論它

你必須承認"重構"這個字沒辦法在所有人腦海裡形成相同的想像
對我來說我只是知道了你採用哪裡來的定義而已,確實沒有跟我的完全一樣
所以你會發現我回你的留言裡面完全不會去用這個字。

... 早晚也會遭遇你說的「越早期寫出來的 code 幾乎保證越爛」的問題 ...

我這兩回答這個早晚的問題可能不下三次

其實我上一篇留言已經有等價的答案

test case 的總數是隨時間增長的
所以我前面說 false negative 比例會降低的同時
就是在告訴你大量 false negative 的問題會比較"晚"遇到

應視為一種特性,端看專案場合適不適用而已

你會發現我的原文從來沒有否定 TDD 對系統雛型建構的幫助
對我來說這就是它的正面特性
但其實也僅止於此而已,其所付出的代價就是「TDD 會導致測試設計較為不佳」

我個人經驗認為 這個交易是非常不划算的

當然有些人的價值觀會認為划算,我不會去計算它

這篇文章也沒有試圖推導這筆交易的判斷

我只打算闡述「TDD 會導致測試設計較為不佳」這部分

其他的就給看的人自己判斷了。

TDD 以我的觀念來說,最大的幫助是促使團隊先完善思維

同上。

但是值得補充一點是,現在有的方法論裡面

能幫助你完善思維的方法太多了

其實這篇文章構思的途中我曾經試圖用另一種論述切入:


你可曾因為沒先寫 test case 而寫出與需求南轅北轍的 code?

你可曾有過先寫 test case 之後發現實作不了的經驗?

如果第一題的答案是 no 那 你本來就不需要 TDD 的特性

如果第二題的答案是 yes 那 TDD 沒有解決它 claim 能解決的問題

如果你的答案是 yes, no, 那恭喜你非常適合使用 TDD


不過基於論點收斂,這個部份後來被我廢棄了

我有點後悔,因為我發現很多人很在意 TDD 可以幫助思維這一段

放上來給你參考一下

TDD 的方式下你這次的改動也應該先寫 (其實是改現有的) 好 test case 再去改,不存在反向監督的可能。
當然,上面是理想的情況,執行上總是會漏掉幾個沒寫沒改的 test case。

這個問題我也回答了不下三次
改動導致的 test case 改動有哪些?你怎麼挑出來的?
如果這件是在理論上講不出可執行的方案,那你的理想在理論上就行不通。

再更具體一點來說,你有系統化的實現過你的理想嗎?

我認為,在需求的面前,開發跟測試不需要有任何的信任 ... 即便有上百個測試失敗,你也只能選擇先檢查實作的改動,找不出問題那就負起責任去逐個檢查每個測試。

如果這是執行 TDD 的先決條件的話,那你幾乎就是在說 TDD 不可行

因為如果有一件事 100 個人裡面 3,4 個人做不到,你的確可以把問題推給 人的問題

但是如果有一件事 100 個人裡面你連用逼的可能都只有不到 10 個人做得到的話

那這肯定不是人的問題,你必須面對方法論裡面有某種觀念是壞的

我可以告訴你不管任何方法都遲早要遭遇百多個 test case failed (false negative)的問題

而從測試理論和我個人作為開發者的角度出發

我認為方法論有義務推遲這件事的發生,因為沒人想花時間在研究一堆 not a bug 的 failed 上

然而你會發現 TDD 的方法論不太願意為這件事負責

你們情願相信這是人的問題

Talisker Aug 25, 2021

感謝你的回應,那個時間不知道你是早起還是熬夜回應,總之非常謝謝。

我想是這樣的,我們有很多有共識的地方,差別在於看待 TDD 特性的方式。
我也沒有否定你說的問題是問題,只說在適合的規範底下採用 TDD,是有利大於弊的空間的。

我基本上看不出為何「上百個測試失敗需要對實作和測試進行檢查」會幾乎等於「TDD 不可行」。
前者是只要有導入測試的專案都早晚會遇到的問題 (只是 TDD 可能提早遇到),這點我們是有共識的不是嗎?

若說兩者幾乎相等,我想你的經驗讓你反對的並不是 TDD,而是測試本身
(準確說是會讓你容易遭遇一次上百個的測試失敗的測試規範)。

所以我一開始就認為這篇文討論的比較像是測試規範不佳導致的問題,而不是TDD的問題。
上次回覆我有提到,「另一個層面是一個改動能觸發上百個失敗,說明改動可能需要再進行更細緻專一的切分,並調整相關規範」
而不是完全歸咎於這是採用了甚麼方法害的,好像是方法論該為採用者負責各種問題一樣。
你的經驗裡似乎沒有 TDD 能搭配好的專案場合與測試規範,這我也覺得很正常,TDD 本來就不是萬靈藥

TDD 就是要先寫測試,所以你用「越早期寫出來的 code 幾乎保證越爛」得出 TDD 有矛盾我並不認同
因為它就是一個特性而已,採用團隊自然會用規範去解決或減輕問題,不應該認為 TDD 沒有照顧到這點所以怎樣怎樣。
尤其在你是用它最根本的定義與一個任何方法都會遇到的問題來說明,這只能說 TDD 的作法本身你就不喜歡 (根據經驗造成的不偏好)。

你可以試想這樣的邏輯: 假設沒有 TDD,哪個方法或規範會是最早寫測試的? 你是不是該用同個理由去反對?
如此往復,到最後沒有方法或規範可以說服你導入測試,是不是乾脆就不要寫測試算了?
所以你說「我認為方法論有義務推遲這件事的發生」這是你對方法的一種期望,只是非 TDD 能滿足而已。
(你用人家的特性打死它了,它怎麼有辦法滿足你?)

最後來回一些你問的問題吧

你可曾因為沒先寫 test case 而寫出與需求南轅北轍的 code?

沒有,而且這也不可能,因為在沒有導入測試前的所有專案都有辦法為需求服務,測試對於需求來說不是必須
(甚至沒有測試,也不會寫出所謂南轅北轍的 code)
退一萬步講這只有需求完全理解錯誤 (人的問題) 才會發生,而這種時候寫出來的測試根本也是錯的。
連測試都跟你會不會寫出南轅北轍的 code 無關了,測試先寫還是後寫我想是更沒有關聯。

你可曾有過先寫 test case 之後發現實作不了的經驗?

並沒有,這可能是由於團隊的規範,讓我們有好好切分每個方法的職責。
可能我經驗不多,經手專案也並不那麼雜亂,我也沒有辦法想像怎麼會有「測試有辦法測,實作卻無法寫」的情況。
(或許你可以分享一下是甚麼情況)

改動導致的 test case 改動有哪些?你怎麼挑出來的?再更具體一點來說,你有系統化的實現過你的理想嗎?

因為我們的規範,可以很容易地找到每個方法對應的是那些測試,那些方法或物件也都有遵循好SRP等優良原則;加之每個改動都還算專一,不會動不動要你大改一堆方法。
坦白說,我們也沒有真的所有方法都寫測試這麼理想,只是規範為那些不那麼雜亂的方法寫
(當然遇到雜亂的要修好,這次寫或下次寫就看當下的需求,要不要用 TDD 也可以討論決定,不是強制每個都要用)。
就是一個正在完善導入測試的階段,甚至也不是每個測試都用 TDD。
我也不清楚這夠不夠系統化,但確實是可遵循的規範,我想那就夠了。

CHChang810716 Aug 25, 2021

即便有上百個測試失敗,你也只能選擇先檢查實作的改動,找不出問題那就負起責任去逐個檢查每個測試。
我基本上看不出為何「上百個測試失敗需要對實作和測試進行檢查」會幾乎等於「TDD 不可行」。

講得更白話一點,commit 是你的,你要負責去查這 100 個 case 到底是什麼問題

摸著良心說,你會老老實實地去查嗎?
你覺得 100 個人裡有多少個人會老老實實去查?

我回答完了,這個點上我停止說服你

你可以試想這樣的邏輯: 假設沒有 TDD,哪個方法或規範會是最早寫測試的? 你是不是該用同個理由去反對?.....是不是乾脆就不要寫測試算了?

code 先寫在寫測試就好了,你回看 Reddit 的原文
他也同意測試很重要,但是不見得需要 TDD

如果有另一個不是 TDD 的方法鼓勵先寫測試在寫 code
那很大的概率我確實也會反對這個方法

但是話不能說死,這是一個完全假設出來的問題

「我認為方法論有義務推遲這件事的發生」這是你對方法的一種期望,只是非 TDD 能滿足而已

對於任何統計學數據科學問題,如何保持資料乾淨是一種共同的追求
只要資料源雜訊越少,我們就在 clean data 上的成本就可以越低
而軟體測試其實就是一門數據科學

所以你對期望的見解在我看來是這樣的:
有人賣了一顆減肥藥給你,它確實能給你減重,但是代價是你的健康
我跟你說健康很重要
你說「我的目的就是減重,你想要健康只是我們的期望不一樣而已」

我可以同意的就是邏輯上的正確而已

沒有,而且這也不可能
並沒有,這可能是由於團隊的規範

所以答案不是 yes 和 no 對吧?

因為我們的規範,可以很容易地找到每個方法對應的是那些測試...可遵循的規範,我想那就夠了

所謂系統化的意思是有計畫、可執行且可檢討

你所描述的內容只有提到有計畫而且你自己有執行而已
從你的描述是完全看不出成效的,你也不知道你的隊友是不是真的都有照計畫執行

具體來說

我所問的其實就是你的規範有沒有真的讓你遇到假的 test fail 以前就把 test case 修好

你有客觀數據證明的感覺是對的嗎?我姑且猜是沒有

因為有的話你大概不會看不懂我的問題。

我在我第一間公司個位數個人的團隊,我自己給整個團隊做了這件事
然後換一間公司之後幾千個人的團隊他們做得更徹底

所以這個數據其實並不強人所難,如果你真的想要檢驗方法論的效力的話

你們應該要去做這件事


規範這種東西不是有或感覺好就好

它是一種需要接受檢討跟反省的東西

不是感覺我們有東西可以 follow 產品的品質就會自己好起來

至於 SOLID 原則

我也可以很直白的跟你說

不是你照著 SOLID 寫 code 就不會遇到代碼品質爛掉的問題

因為事實上我們根本沒有系統化數據化的方法去分析耦合和聚合

舉例來說好了,一份 code 拿來

你看到有兩段 code 看起來類似,你覺得 DRY

但它有沒有可能就是基於完全不同的動機和目的寫出來最後只是乍看相似的 code?

如果你不分青紅皂白的直接 merge 兩段 code 到一個 function 或 object

你是不是過度復用了這些代碼?

軟體工程原則是充滿哲學和主觀價值判斷的東西,就光 S 和 O 就存在拮抗成分在裡面的

這無法作為你有系統化執行任何方法論的參考依據

Talisker Aug 25, 2021

恩 我的意思就是那兩題對我來說答案都是no,只是可以延伸探討去說明不是我認為第一題是no我就不需要TDD,這樣的問題而已。
我也沒說我們團隊就是有系統化的去執行TDD,但這樣的規範是可以遵循的也是事實,總是踏出了第一步。

SOLID 原則的部分我沒有什麼意見,那些判斷我們有自己的標準 (主觀),只是說明遵循這樣的原則去設計,對 TDD 的採用我認為有正面影響

你有客觀數據證明的感覺是對的嗎?我姑且猜是沒有

確實是沒有,原因應該就是我們目前也沒有系統化,只能說我們確實能不太費力的做到這件事,以及不太費力的可能理由 (規範與程式原則等等)。

期望的見解

這裡雖然例子有點偏心,但邏輯上你說的沒錯,我就是這個意思。
我也可以偏心的舉例為給你一種保健食品,副作用是可能稍微增重些,但你可以控制飲食搭配運動 (規範) 去做調整。
只能說我們角度不同,偏好自然不同,沒有什麼對錯。

code 先寫在寫測試就好了,你回看 Reddit 的原文
他也同意測試很重要,但是不見得需要 TDD

我當然有看過,我的意思是

  1. 「越早期寫出來的 code 幾乎保證越爛」
  2. 不論任何方法「遲早要遭遇百多個 test case failed (false negative)的問題」

若這可以用來說明 TDD 有矛盾甚至不可行,則被反對的不是 TDD,而是測試本身。
因為 1和2 都沒有限定於採用 TDD,因此我認為這兩點不能用以評論 TDD的可行性。

另外,「code 先寫在寫測試就好了」具體到底能跟 TDD 差多少時間寫測試?
以 TDD 來說,寫實作程式和測試程式的都是同一個人,要比較的話我們極端點大可以先寫完實作再去寫測試。
這也是一種 「code 先寫在寫測試就好了」,但真的跟 TDD 有甚麼顯著差距嗎?
我想應該是幾乎沒有,甚至你晚兩個 cycles 再寫測試,最後還是逃不過2。

至於上百的測試失敗大家會不會照著查的問題,我說了這可以是另一個層面的事
「另一個層面是一個改動能觸發上百個失敗,說明改動可能需要再進行更細緻專一的切分,並調整相關規範」
但最初遇到的,如果沒辦法從實作找出問題,還是應該好好的一個個 review,後面再去檢討切分和規範調整的問題。
2就是沒有限定 TDD,你不認同上面的做法,說大家不會這樣做,那就是再一次: 被反對的不是 TDD,而是測試

請注意,2是我們認為遲早會遭遇到的事。
你的反應是 TDD 也會遇到,它有矛盾,可能不可行;
我的反應是大家都會遇到,採用 TDD 也不能解決,但我們可以想個規範處理慢慢修正,降低發生的機會或減少數量。

(我好像倒著回了)

但我想我們都知道對方想說的是什麼了,也謝謝你耐心地回應。

CHChang810716 Aug 25, 2021

若這可以用來說明 TDD 有矛盾甚至不可行,則被反對的不是 TDD,而是測試本身。

你的邏輯似乎是

因為必然有最先寫出來的 test code, 所以必然存在最不穩定的 test case。
而如果我們的目標為總是避免讓最不穩定的 test case 出現

then recursively, 我們就會得到沒有 test case 的結果

如果這是你的邏輯的話,那麼來看看我的邏輯:

如果越早寫的 code 就相對越不穩定的話,
那麼對單一功能而言,我們應該先實作 code 再寫測試

我認為 bug 出在絕對、相對和比較對象

不論任何方法「遲早要遭遇百多個 test case failed (false negative)的問題」

我前面寫了很多 遲早 本身的價值

我想關鍵就在於你沒有看著數據思考過一些問題

所以你很難想像這會差多少

RD 在調查 false negative test case 的時間應該視為效能空轉

只是在 TDD 觀念裡不願意承認這件事,你們的方法論教你這是人的問題和必要之惡(見前面討論)

甚至根本無視、不去討論這個問題

如果遲早都會發生所以可以選擇不去討論不去尋找對應策略的話

大概就相當於就是在說 RD 空轉的時間多和少無所謂反正都是空轉 所以這個問題不重要,擱置。

這個環節應該屬於我跟你觀念上最大的歧異

你的反應是 TDD 也會遇到,它有矛盾,可能不可行;

不是,我是主張從根本解決問題

如果 TDD 導致 false negative 上升的話,那就不要使用 TDD 就好了。

矛盾論只是一個對 FN 上升和測試的原始目的做出的解釋

它只是在"測試"這件事上存在矛盾而已

如果你有更重要的目的要執行 TDD,你還是可以執行

所謂的指出矛盾,只是在某個面向上告訴你你在繞遠路而已,而且你可能不知道你繞了多遠


我也非常感謝你的回覆

一定程度上這些討論有涉及到一些文章沒有提及的部分

也算是完善或指出了文章的漏洞

謝謝

Talisker Aug 26, 2021

確實就像你說的

沒有系統化的採用者,很可能感覺不出差別,也感覺不出自己在繞遠路。

最後想再針對這句做個簡短回應

如果 TDD 導致 false negative 上升的話,那就不要使用 TDD 就好了。

我想說的是,或說是理想的 TDD 實踐,不會有 FN 上升的情況,甚至概念上不存在 FN。
因為都是先改測試再改實作,會出現的 FN 就只是漏改的數量 (也就是說這些測試這次並未採用 TDD 的作法)。
改錯也是有採用 TDD,但連測試都改錯了 (需求理解有誤),實作更難保證沒有問題,所以這一樣不能歸咎於採用 TDD。

(題外話,需求理解錯誤在任何的方法下,我認為更有可能提高的是 FP)
(所以我想應該不存在任何方法能主打降低 FP,這等於要為需求理解負責,沒有方法能如此神通廣大)

TDD 簡要就是在理解需求後,切分完善得到一個個大小適合的需求之後,對每一個小需求進行 (左邊這些都不在 TDD 範圍內):
新增/修改 測試 ---> 測試失敗 ---> 撰寫剛好能通過測試的實作 ---> 測試通過 ---> 整理與重構 ---> 測試直至通過
(步驟裡,或說我們的 TDD 實踐步驟裡是有重構的,所以最一開始才會跟你糾結在它的定義上)
TDD 沒有規劃你該怎麼理解需求,更規定改實作前要先處理好測試,甚至寫的都是同一個人 (不存在在開發測試由各自團隊處理時,可能的需求理解落差,這是 FN 常見的提高原因,TDD 這類強制測試實作由同一人進行的方法則根本上完全解決這裡的所有 FN)。
所以它本身的最理想情況是不會有 FN 的 (或說 FN 不可能是由於採用 TDD 而出現)。

這是理想沒錯,但 TDD 這個詞應該代表的就是它的理想,而不是嘗試失敗的實踐
總之,直接說 TDD 可能導致 FN 上升,我想是會讓人感到很困惑的。

我相信你也知道上面這些道理,所以這只是一個論事上的小建議。

跟你的討論也讓我收穫滿多,非常感謝。




2
2
2