l

2014年5月2日 星期五

談談壞味道(8):Temporary Field & Message Chains

Apr. 25 16:48~17:57

image

 

Temporary Field(暫時欄位)

Temporary是「暫時」、「臨時」的意思,Field指的是稱為「data member」、「attribute」、「instance variable」的物件變數。兩個字合起來的意思是說:「物件變數只有在某些狀況之下才會被物件使用,甚至只有在特殊狀況下這些變數的數值才會是正確的。」前面幾集介紹了那麼多壞味道,看到這邊鄉民們應該可以猜得出來,Temporary Field會增加理解程式的困難度,降低可修改性。

為什麼會形成Temporary Field?一種常見的原因是物件有一個需要很多參數的函數,但是你不想,或是懶得傳遞這麼多參數,所以你把這些參數設成「instance variable(也就是field)」,讓這個需要很多參數的函數直接讀取instance variable而避免傳遞參數。但是這些「instance variable」只有這個函數會使用,在物件的其他函數中都不會被用到,也與物件的狀態無關,因此這些「instance variable」形成了Temporary Field壞味道。

還有一種常見的情況,物件狀態比較複雜,在不同的狀態之下,需要不同的「instance variable」,例如狀態A需要五個變數,但是當物件變成狀態B的時候,需要額外2個變數。這2個只有在狀態B才會被使用的變數,也算是一種Temporary Field。

***

綜合以上的說明,Temporary Field之所以會是一個bad smell的原因(force)可歸類為:understandability和modifiability這兩點。

移除Temporary Field壞味道的方法,在《Refactoring》書中提到可以套用Extract Class和Introduce Null Object。

***

Message Chains(訊息鏈)

Message Chains就是說程式中出現了如下的函數呼叫方式:

a.getXXX().getYYY().getZZZ().getUUU().doIt();

a.getXXX()得到一個物件,再透過這個物件的getYYY()得到另一個物件,再呼叫它的getZZZ()得到另一個物件,再呼叫它的getUUU再得到另外一個物件,最後的目的是為了呼叫這個物件的doIt()函數。如上一長串的函數呼叫,便產生Message Chains這個壞味道。

Message Chains違反一個算是有點小名氣的設計原則—迪米特法則(Law of Demeter;LoD),又稱為「最少知識原則」。在《Applying UML and Patterns》這本書中,作者把這個原則又叫做Don’t Talk to Strangers(別跟陌生人說話)。違反了這個原則表示物件之間有著不必要的耦合,因此中文版的《Refactoring》把這個壞味道翻譯成「過度耦合的訊息鏈」。

a.getXXX().getYYY().getZZZ().getUUU().doIt() 能夠寫出這樣的程式,代表開發人員要知道a.getXXX().getYYY().getZZZ().getUUU()這一連串呼叫所傳回物件的關係,這已經有點複雜了。如果物件之間的關係發生改變,程式也要跟著改變。此外,要測試過度耦合的程式也會變得比較困難。

***

綜合以上的討論,Message Chains之所以會是一個bad smell的原因(force),可歸類為:understandability、modifiability、testability這三點。

移除Message Chains的方法,在《Refactoring》書中提到可以套用Hide Delegate、Extract Method、Move Method。

***

友藏內心獨白:事情層層交辦下去,不確定性也會跟著提升。

沒有留言:

張貼留言