為什麼從測試聞 Code Smell#
在團隊裡,如果身邊的人習慣寫難讀、難改的程式碼,待久了你也會慢慢被同化。專業開發者要避免這件事,就需要敏感度去察覺程式碼異味(Code Smell)。
而幫助我們察覺異味的最有效手段之一,並不是 Code Review,也不是昂貴的 IDE,而是夠密集的單元測試。當設計上有缺陷,寫測試時就會被「逼著」用同一種樣子重複寫,於是味道自然浮現。
「重複」是萬惡之淵藪#
程式世界的萬惡之源,當之無愧的就是重複(Duplication)。Andrew Hunt 與 David Thomas 在 The Pragmatic Programmer 中將此原則命名為「DRY — Don’t Repeat Yourself」。
大多數爛程式都是從「複製貼上」開始。在 Stack Overflow 抄答案、從舊專案搬運類似邏輯,當下確實能完成工作,但長期累積下來就是技術債。
當寫程式發現自己在重複時,大概代表兩件事:
- 介面設計不好,使用者被迫一再做相同的事
- 確實存在多個類似邏輯,重複程式碼是這個事實的展現
無論哪一種,都是進行重構或修改設計的好時機。
範例:成績單獎學金計算#
以「依照學生身份計算獎學金」為例。原本的 calculate 方法在不重構時,會依大學生、碩士生、博士生三種身份各寫一段邏輯,三段邏輯外觀非常類似。
只看「形狀」就能聞到味道:方法被切成三大塊,每一塊長得很像,那一定有共通的抽象邏輯被重複了。
如果在寫產品程式時沒注意到,還有第二次機會:寫測試的時候。
class ScholarshipServiceTest {
@Test
void bachelor_full_scholarship() { /* 略 */ }
@Test
void bachelor_half_scholarship() { /* 略 */ }
@Test
void bachelor_NO_courses() { /* 略 */ }
@Test
void bachelor_NO_scholarship() { /* 略 */ }
@Test
void master_full_scholarship() { /* 略 */ }
@Test
void master_half_scholarship() { /* 略 */ }
@Test
void master_NO_courses() { /* 略 */ }
@Test
void master_NO_scholarship() { /* 略 */ }
@Test
void PhD_full_scholarship() { /* 略 */ }
@Test
void PhD_half_scholarship() { /* 略 */ }
@Test
void PhD_NO_courses() { /* 略 */ }
@Test
void PhD_NO_scholarship() { /* 略 */ }
}把所有細節隱藏,光看測試方法名稱就能看出重複:三種學生 × 四種場景。寫這些測試時你會大量「複製過來改一下」,覺得麻煩。
覺得麻煩,就是壞味道在說話#
覺得麻煩就對了,這意味著:
- 介面設計可能有問題,應該回頭檢視
- 邏輯確實是這個量級,那就回頭看看程式有沒有可以重構的地方
這是聞出重複的第二次機會。錯過這次,未來再回頭時,因為已忘記當初寫了什麼,重構成本會更高。
「如果我們沒發現,就給程式寫一點測試」── 測試會誠實揭露程式設計上的不足。
原文出處#
- 原書/iThome:https://ithelp.ithome.com.tw/articles/10262134