<<重構>>裡介紹的壞味道, 都是直接去嗅代碼. 不過既然我們採用TDD, 那麼代碼的一切壞味道, 都會反應在測試上, 比如一個函數的測試案例組合太多, 可能意味著函數職責過多. 這在物理上稱為對偶性, 即不同的表達方式, 反應的是同一件事. 兩個非常不同的理論精確的描述了同樣的現象. 分別讓一對夫妻給你講他們的故事,他們的說法會不同,但每個重要事件都能相互得到印證。和他們談話多了,你就能指出兩人說的故事有什麼不同和聯絡。例如,丈夫覺得妻子過於自信,這正好印證了妻子抱怨丈夫太懦弱。我們可以說,兩個人的話是互為對偶的。換句話講, 我們可以通過觀察測試而不是直接去看代碼, 來發現代碼的壞味道.
以上是題外話, 現在進入正題
今天在物件導向訓練營的培訓中, 發現了一種新的壞味道. 事情是這樣的: 學員在完成按空位絕對數量多少停車的時候, 使用了繼承, SmartBoy繼承自Boy. 停車是不同的, override; 而取車是一樣的, 代碼都在基類裡. 而在寫測試的時候, 我發現他們分成了兩派. 一派沒有對SmartBoy的取車進行測試, 而另一派做了測試. 組織他們討論, 兩派的理由都有道理: 前者說取車代碼只有一份, 前面Boy的測試已經測過了, 因此SmartBoy可以不測; 而後者說從功能上SmartBoy和Boy完全是獨立的, 測試案例應該從功能分解下來, 因此應該測. 而你只是內部實現使用了繼承, 要是我現在不測, 哪一天你不用繼承了, 豈不是有破壞現有功能的風險?
我認為兩者都有道理. 且不說可否從單元測試和功能測試的角度來解釋(況且前面我們已經說了Unit Level Fucntional Test),單是這種爭論的存在我們就可以思考: 是什麼讓我們陷入了可測可不測, 進退兩難的境地?
幾秒鐘之後我想清楚了, 這是一種壞味道, 原因是這裡有重複. 這裡雖然沒有重複的代碼, 但是有重複的概念. SmartBoy根本就不是一個獨立的概念. 同樣的Boy加不同的選車位的策略才是更基本的概念. 重構到策略模式至少是一種可以消除爭論的一種方案, 因為此時取車只有一份了, 無論從代碼上還是概念上. 因此前面Boy的測試已經測過了, 我們根本不需要再寫一遍
推而廣之, 我們可以重新發現一種已知的壞味道: 實現繼承. 而可有可無的測試和實現繼承在壞味道方面是對偶的.