測試驅動開發的步驟

昨天寫的〈測試驅動開發要徹底重構〉,曾經提到 Steven 說到「如果像閣下文中說:『系統不斷演進及需求不斷改變之下,也可能會使架構或設計愈來愈複雜而變得難以維護』,我則認為是在進行 TDD 時候沒有徹底去重構系統。」,同人認為這段話有根本上的邏輯的繆誤,於是回應:

假如上面的話是成立的,那麼代表只要徹底重構系統就不會造成「系統不斷演進及需求不斷改變之下,也可能會使架構或設計愈來愈複雜而變得難以維護」嗎?如果是這樣,那 XP 根本就不需要 Refactoring 這個實務來改善程式的結構,因為你都徹底重構程式,程式結構變差的情況是根本不可能發生。

而且依照本人 20 年來軟體開發的經驗,我還不沒有看到有程式一開始就寫得很好,到後來可以不用改變架構而符合新需求的。倒是隨著對問題的更清楚,或是程式需求的變化,讓程式必須重構的現象時常履見不鮮!

所以如果自以為自己博覽群書,很懂得TDD的實務。也不要忘了用心思考,以免自己對TDD的最佳實務的認知,不小心犯了根本上的邏輯繆誤?

結果,後來同人在 Facebook 的 Scrum community in Taiwan 看到 Steven 做了以下的回應:

先說件簡單易明的事情,其實我很不喜歡閣下把 TDD 放到 “精神” 層次,卻忘記了基本步驟。

之前的討論根本連事實層次都被忽略,根本談不上是什麼多少年的經驗或者如何用心思考,連 TDD 的最基本步驟也忘記,TDD 的基本步,不是閣下做多少年工作就可以把人家的定義去改變的,我也不明白為何有 20 年工作經驗就可以把 “Refactoring” 說成 “並不必然是 TDD 的必要的步驟”,這不是邏輯問題,更不是有過什麼開發經驗然後用心思考就可以改變的事情,這是就算對軟體開發的認知不夠閣下那麼 “全面” 的都能看出的謬誤,如果閣下這樣就認為是因為說不過閣下就建議多看書本,本人深表遺憾。

我是來討論問題的,我沒有興趣去傷害閣下感情,好好閱讀書本,只是反映 TDD 三個步驟是什麼根本不存在爭議,更沒有 “好好閱讀什麼書或文章才能跟我討論” 的意思,我還未自大得要別人看過多少書才可以討論問題,亦正如討論問題我也不用跟別人說我有多少年工作經驗一樣,而且本人是衷心認為多讀書是有益的(不管是閣下還是什麼人),多讀書亦不是為上來辯論的,不過閣下如果感到有所不悅的,我就先行道歉,還是希望冷靜一點討論問題。

而簡單的例子也是思辦的過程的一部份,一方面是簡單易明地討論問題,另一方面是如果連簡單的例子也說不通,又怎麼能去談更複雜的問題呢?

上面提到:”那XP根本就不需要 refactoring 這個實務來改善程式的結構,因為你都徹底重構程式,程式結構變差的情況是根本不可能發生。”

不如冷靜一點再讀讀這句子,”XP 不需要 Refactoring 是因為徹式地進行 Refactoring”,我就看不明白這是什麼邏輯,一邊說不需要,另一邊說徹底地進行。

這裡的問題是軟件是會改變的,可能是新增功能,也可能發現有其他問題,每次帶來的變更其實都需要進行重構的。所以說 XP 不需要 Refactoring 也不正確。

世上的確沒有一寫就好的代碼,而且世界是會變的,Refactoring 就是避免以後的更改越來越困難。把 “徹底地進行重構” 理解成 “XP 不需要重構這實踐” 完全沒有邏輯可言。

我也沒有反對不用改變程式架構就能滿足新需求,亦沒有否定 Refactoring 的重要性,只不過我還是建議新的功能以 TDD 方式進行開發,有測試、有代碼、然後進行重構的。

在足夠測試覆蓋下進行重構是可使系統在不斷演進及需求不斷改變之下,使架構或設計仍然處於可以維護的狀態,相反我指出的是,如果程式架構和設計越來越難維護,是重構的力度不足夠。

前面還提到:”但重構的目的為何?就重構的定義在不改變功能的情況下改善程式結構,以增加程式碼的彈性以利未來增加或改變功能。因此如同那第三步所言,為了去掉重覆性而重構。”

如果重構只是為了去掉重覆性,那 TDD 的第三步不如叫 “Remove Duplication” 好了,無可否認代碼重覆是很常見的問題,但把這裡的重構限制成消除代碼其實會局限系統的將來發展,而且到了 TDD 的第三步,系統是應該有足夠的測試去覆蓋系統,重構的力度沒理由只局限於新增功能和現有程式的重覆。

我就相信閣下是 Refactoring 的專家,也應該會知道一些 Refactoring 的模式是完全相反的,例如 “Pull Up Method” 和 “Push Down Method”,更是需要觀察當時的情況來作決定,而沒有一面倒那個才是好的模式,我實在不明白為何要把 TDD 的 Refactoring 局限到只做 “去掉重覆性”。

這是實務上會發生的事情,消除代碼重覆以外的重構還是會發生的,如果只是單單只是 “消除重覆”,這會是另一個我認為進行重構不夠徹底的事情。

上面已經不單單是用心思考,而是由理論到實踐都可以看得到的事情。

跟討論 Refactoring 和 TDD 觀點以外的聲音,就引用 Chet Henderickson 的說法,全部都是我錯好了,現在可以解決問題嗎?

看了 Steven 的回應,同人當下的反應是不想浪費時間與心力與他周旋下去,但後來想到或許是因為 1/9 敏捷開發分享會我要分享實施 XP 的經驗與心得,也許這是一個巧妙的同步事件。我可以趁這個機會,導正對 XP 或是 Agile 的一些錯誤觀念。

例如敏捷開發並不是教條式的照本宣科,開發者要懂得變通最重要的是用心思考,而非把必要的思考都看成精神層面的問題,這並非適用於敏捷開發的心智模式。以下是同人在 Facebook 的 Scrum community in Taiwan 的回應,但一些詞句有略為做過一番修飾,以清楚表達我對測試驅動開發步驟的看法。 閱讀全文 →

分類: 問題解決, 專案管理, 思考, 溝通, 生活感觸, 編程技巧, 職場, 衝突, 設計原則, 開發流程, 閱讀 | 1 則留言

測試驅動開發要徹底重構?

同人在〈測試驅動開發的精神〉中,提到「Refactoring 並不必然是 TDD 的必要的步驟」的觀點。David Ko 回應他猜測 Steven 是根據 Kent 在《Test-driven Development》一書的前言中提到的說法,來認為測試和 Refactoring 也是TDD很重要的一環。他說:

…here’s what we do: we drive development with automated test, a style of development called Test-Driven Development(TDD). In Test Driven Development:
* Write new code only if an automated test has failed
* Eliminate duplication
……

The two rules imply an oder to the tasks of programming.
1. Red – Write a little test that doesn’t work …
2. Green – Make the test work quickly…
3. Refactor – Eliminate all of the duplication….

Red/green/refactor – the TDD mantra

在這段敘述中,Kent 認為 Red/green/refactor 是 TDD 的三字箴言,是 TDD 這個 practice 重要的工作。

所以 Steven 才會強調在做 TDD 時,”測試是第一步”,”Refactoring 本身是 TDD 三步之中其中必要的一步”

假如正如 David Ko 所說,測試與 Refactoring 是 TDD 很重要的一環,而來強調 TDD 不應該忽略 Refactoring 的工作,這樣的觀點我可以接受,但同人隨後又看到 Steven 的說法,覺得他自以為是的論點讓我很遺憾。

本人從來沒有指出 TDD 是測試 Practice,亦沒有認為測試是 TDD 的目的。

上面的 “功能” 指代碼的內容規格,寫測試時候就是思考新功能的行為,用測試用例的方式去表達出來。就正如:

AssertEquals(3, add(1,2))

那麼簡單,已經是對 add() 作出規範,投入兩個參數,輸出一個數字作結果,並規範了新 fn 的名字是 “add”。寫這句 Assert 時候就應該思考到 add 有兩個參數,投入 1 和 2 就會得 3 這個數字。

重構是 TDD 其中一步,不存在混淆點,再者,沒有測試覆蓋下的根本不能說成重構;另一方面,先寫代碼後補測試是很痛苦的事情。

如果像閣下文中說:「系統不斷演進及需求不斷改變之下,也可能會使架構或設計愈來愈複雜而變得難以維護」,我則認為是在進行 TDD 時候沒有徹底去重構系統。

我建議閣下好好閱讀 TDD 的書本,Refactoring 是 TDD 必需的步驟,由 Kent Beck 到 Robert Martin 以至其他不太有名的 TDD 書本作者,都指出 TDD 的第三步是重構,而不是 “Refactoring 並不必然是 TDD 的必要的步驟。”

看到「我建議閣下好好閱讀 TDD 的書本」這種不尊重不同觀點的說法,同人根本就不想浪費時間來跟對方爭論。即使耐著性子仔細看他的論點,像那些「沒有測試覆蓋下的根本不能說成重構;另一方面,先寫代碼後補測試是很痛苦的事情。」、「如果像閣下文中說:『系統不斷演進及需求不斷改變之下,也可能會使架構或設計愈來愈複雜而變得難以維護』,我則認為是在進行 TDD 時候沒有徹底去重構系統。」等說法,更讓同人懷疑他對 TDD 的認知,其實是過於偏向理念化而不夠切合實際。

不過,對 David Ko 提出 Kent 認為 Red/green/refactor 是 TDD 的三字箴言的說法,同人倒是覺得有探討的必要。以下分享我在 Facebook 的 Scrum Community in Taiwan 回應 David Ko 的觀點,這些觀點應該可以解釋為什麼測試開發不需要徹底重構 閱讀全文 →

分類: 問題解決, 專案管理, 思考, 溝通, 生活感觸, 編程技巧, 開發流程 | 2 則留言

測試驅動開發的精神

在 Facebook 的 Scrum Community in Taiwan 看到 David Ko 提到:

聽到有人說 TDD 是個測試的 practice,跟 RD 不是那麼有關,我想這是誤會了。TDD是一種設計的活動,它並不是單純在做 verification,它是一種 spec 確認的活動。

David Ko 還分享了一篇探討 TDD 的文章供大家參考。這讓同人想到我之前曾經對 InfoQ 的一篇有關軟體開發信仰問題的文章做過的評論。

在那篇文章的評論當中,同人認為作者不應該拿 TDD 與驗收測試相提並論,因為 TDD 並不是測試的 practice,而是設計的活動。如果這兩種實務可以相提並論,似乎就像是爭論有了良好品質的設計就可以省略測試,或是增加測試的效率就可以取代設計的重要性。同人當時在我的評論中提到:

測試的涵蓋面要夠廣,軟體開發所需的開發成本與時間就要增加,所以與其靠檢驗來控制品質,還不如把設計做好。所以,品質是設計出來的,而非檢驗出來的。

不過,雖然品質並不是檢驗出來的,但軟體要具備足以信賴的品質,卻不能省略測試。舉個例子來說,不管開發者如何確保他的開發所產出的品質,驗收測試是絕對不可能省略的,否則客戶是很難信任軟體是合乎他們需求的。良好的軟體設計可以減輕測試的負擔與壓力,但它絕對無法否定軟體測試的價值。

因此,同人認為不該拿 TDD 來與各種形式的測試來做比較,但在 David Ko 提出這個主題後面的討論,我卻看到一個我不太認同的說法。 閱讀全文 →

分類: 問題解決, 專案監控, 思考, 編程技巧, 職場, 設計原則, 開發流程 | 3 則留言

再談技術經理當教練

MaoYang 兄看到我分享〈技術經理的教練角色〉之後,他在噗浪河道上回應他對我文章觀點的看法。他說:

我常在做的 “教練” 工作大部分是在講一些基礎的東西與衍生的技術, 但是倒沒有想過要將團隊變成 “一致性” , 試想, 你身為經理確發現實作的工程師缺乏某些觀念時, 你不得不著急,但是這種狀況出來的時候, 產品也開始出現許多問題, 這是技術經理面臨最大的挑戰。但是當技術經理開始當 “教練” 已經離開工程師角色一段時間, 這又是另一個挑戰

同人很高興 MaoYang 能夠針對這個主題提出討論。對於他所提到的問題,我常看到的是技術經理不能因材施教,所以究竟來看也是身為教練本身指導的彈性不足,也是多樣性的問題,尤其在軟體開發專案更為常見。

而且有時候工程師不是不懂那些概念,而是他們碰到一些技術經理不重視或忽略的問題,但如果沒辦法幫他們解決那些問題,如何讓他們接受那些觀念。教練就只會流於說教的自說自話。 閱讀全文 →

分類: 品質文化, 問題解決, 專案團隊, 思考, 溝通, 生活感觸, 職場, 領導 | 發佈留言

在 2009 年的最後一天

今天是 2009 年的最後一天。計劃未來一直不是同人擅長的項目,隨性的個性也讓我不喜歡依照目標來做事,喜歡把重點放在當下。然而,最近在回顧這一年的經歷卻感受到,在 2009 年的最後一天,很想寫下自己對來年努力方向的期望。

2009 年對同人來說,是「清理過去」的一年。 閱讀全文 →

分類: 占星, 寫作, 新時代, 生活感觸 | 發佈留言

技術經理的教練角色

在噗浪的河道上看到 MaoYang 兄提到技術經理做好教練角色的困難。他說:

技術經理有時候要扮演 “教練” 的角色, 這時候要將正確的觀念傳遞, 這是有點困難的, 因為往往會被自己的極限所限制, 想起了一位朋友,他是長笛老師, 他說他知道那個音要如何如何才是完美的, 但是他確無法示範出來

對於 MaoYang 兄的觀點,通達人認為 MaoYang 的朋友應該要學如何示範,不然就不是個夠格的老師。這代表了技術經理應該要學習如何正確示範,否則就不能算是個好教練。MaoYang 兄進一步解釋他對技術經理擔任教練角色的觀察:

在公司內部, 技術經理當 “教練” 並不是明定的工作, 但是當團隊的程度良莠不齊的時候, 技術經理帶頭出來當 “教練” , 是不得不的, 但是技術經理有時當管理職太久, 要把許多實作交代清楚, 這是當技術經理累人的地方

以上的解釋,通達人認為他同意當「教練」並不是技術經理明定的工作,但為了要避免身為技術經理的時間都被部屬瓜分了,較佳的方案還是當教練,讓部屬有成長的機會和空間。另外,有一位噗友 Daniel Li 也認為,身為技術領導者,給部屬魚吃不如教他如何釣魚。因為總是有一天,他們會離開教練單飛,就像教小孩走路;我們不可能一直挨著他隨時扶著他,只能教他方法、鼓勵或強迫他嘗試,並獎勵或誇大他的小成功。

在觀念上,以上的討論已經將技術經理擔任教練的動機及基本觀念,詮釋地相當清楚。但從自己實際從事技術工作的經驗來看技術經理當教練這件事,事情卻好像並不如以上討論到的那麼簡單。同人認為 MaoYang 兄提到的這個主題,可以從兩方面來探討,一個是技術經理要教練的東西為何,另一個則是技術經理擔任教練的目的為何。 閱讀全文 →

分類: 問題解決, 專案團隊, 思考, 溝通, 生活感觸, 職場, 領導 | 2 則留言

買到海砂屋存證信函怎麼寫?

去年同人寫下〈從海砂屋陰影學到的教訓〉,分享我們全家陷入海砂屋陰影的經驗,並提供同人從此事件得到的教訓與心得。原來這篇文章的寫作動機,只是想提醒想要購屋的朋友要小心資訊不對稱的現象,不要隨便聽信仲介的說辭而陷入對買方不公平的交易陷阱。但這一年來,看到很多朋友都是發現買到海砂屋之後,才看到同人的文章。從文章的留言與 email 的詢問中,關心最多的應該就是詢問存證信函該如何寫的問題,這似乎提醒我應該再寫一篇文章來分享存證信函該怎麼寫,來爭取買方的權益。

同人先提供當時我所寫的版本如下 閱讀全文 →

分類: 問題解決, 生活感觸 | 6 則留言

月亮星座的反應

在河道上看到噗友分享「認識自己的<西洋星座命盤>」,它是轉貼自網路上的資訊,內容提到星體與上昇星座在占星盤中所代表的意涵。其中在月亮星座的部分,有下面這一段話。

月亮:主導潛在的特質,遇到突發狀況的立即反應!月亮星座很重要,是指情緒、第一時間的反應… 比如說當你的車子被人撞凹了,第一時間反應是打人還是報警?是看月亮星座…

同人直覺到上面這段話有問題。就我所知道的占星學觀念,月亮星座的確和突然狀況的立即反應有關,是代表情緒反應沒錯,但這種反應是否就是一般人所認知的第一時間的反應?同人認為這是很有問題的。然後,我又看到車子被撞凹後的行為反應是看月亮星座,這顯然並不是精確的說法,而是有以月亮星座簡化性格之嫌。

其實月亮星座的反應僅限於內心情感的情緒層面,而不會讓命盤主採取行動。或者用更精確的說法是,命盤主會選擇用行為來處理他的情緒反應,是因為其它星體的性格而非月亮星座。 閱讀全文 →

分類: 占星, 學習, 思考, 生活感觸 | 發佈留言

Java 泛型複雜嗎?

石頭成在〈與 metavige 和 alexchen 對話 Java 語言〉這篇文章中,直言他對 Java 語言泛型的批評:

我不認為 Java 讓我們「慢工出細活」,我覺得它帶來的是「冗餘的複雜性」。就算以 C++ 的觀點來看 Java 程式碼,我仍覺得 Java 程式碼有許多不必要的複雜度。Java 把類別變成施加在程序員身上的束縛,而是不是幫助我們進行抽象化資料處理的工具。

我個人認為,所謂「更強化的靜態型態」是跟 C++ 樣板相比, Java 泛型比起 C++ 樣板是在走回頭路。就我到目前為止的 Java 使用經驗來看,我幾乎以為泛型只是 Java 專門用來重新設計容器類別的特殊語法。在那以外的場所,你大概不會想用泛型來重構你的程式碼。

metavige 就說會想用 Strategy Pattern 來重構我在〈從 C++ Template 到 Java Generic,一步一步來〉舉的例子,而不會用泛型。但是泛型難道不是用來處理這個問題的直覺想法嗎? Java 沒有足夠理由說服我們不要用泛型來做,但是用泛型來做… 呃,似乎更困難。

石頭成用泛型來重構程式碼,是不是處理他的問題之直覺想法?我想石頭成比較偏好動態型態語言的自由,比較不欣賞「更強化的靜態型態」的做法。或許是因為 C++ 用 template 實作不會受到參數型別類型的限制,自然會讓他比較想用泛型來重構程式,以去除資料型態與演算邏輯的相依性。然而,看過石頭成所舉的實例,同人認為用泛型來實作的想法未必是直覺的做法。

表面上看起來好像實作泛型可以讓某一段程式碼重複使用,但 Java 在泛型的限制,也增加他重構程式碼的困難度與複雜度。這麼說來,假如石頭成的想法是正確的,用 Java 的泛型來重構程式碼,只會讓程式員沒事自討苦吃。然而,同人在仔細研究他的程式碼之後,發現可以用更簡潔的方式來使用 Java 的泛型。不過,還是讓我們先來看看石頭成的程式碼: 閱讀全文 →

分類: 分析設計建模, 品質文化, 問題解決, 學習, 編程技巧, 職場, 設計原則, 軟體開發 | 發佈留言

名牌數位相機的維修服務

一個月前,同人買了一台新的數位照相機。當時我比較了幾種不同廠牌的機型,覺得 OLYMPUS 的 FE3000 看起來還不錯。在外觀、功能及價格上的比較上,似乎是比較經濟實惠的選擇。而且在印象中,OLYMPUS 是照相機中的世界知名品牌,品牌形象還不錯,所以最後就決定將它購買下來。

經過一個月來的使用,這台 FE3000 用起來還蠻順手,直到最近因為無法透過 USB 連接線輸出照片,才發現 USB 的連接埠故障。老婆到總代理元佑實業要求維修,才發現 OLYMPUS 這個世界名牌數位相機的維修服務,竟是如此糟糕而令人失望。 閱讀全文 →

分類: 問題解決, 溝通, 生活感觸, 組織, 職場, 衝突 | 1 則留言