l

2014年4月24日 星期四

談談壞味道(5):Data Clumps & Primitive Obsession

Mar. 24 13:20~14:23

image

 

Data Clumps(資料泥團)

Data clumps 是指「總是一起出現的資料」例如出現在不同類別或是不同函數參數列的資料,像是用X, Y來代表平面上的一個Point(點),或是資料庫connection string所需使用的多個參數(id、password、ip、port number、database name、database arguments等)。在這種情況之下把這些資料集中到一個類別中會比較好。

廣義的來看data clumps也是一種duplicated code,因為你需要在不同的地方重複宣告多個相同的資料組。此外,data clumps很可能形成long parameter list,算是有雙重殺傷力的一種壞味道。

鄉民甲:「既然data clump造成的不良影響與duplicated code和long parameter list那麼像,為什麼還要特別獨立出一個壞味道?」

這個問題很好,簡單的說,因為判斷這些不同壞味道的「主要著眼點」不同,所以形成不同的壞味道。Teddy在〈什麼是Refactoring?〉解釋說,壞味道是form(型式)的一部分,而form就是refactoring所要改善的「現存設計」。不同的「現存設計」背後形成壞味道的原因可能會全部或部分重複,但是它們所表現出來的「form」卻各不相同。因為人的眼睛在閱讀程式碼的時候比較不容易直接看出壞味道背後的force,或是因為這些force很像因此比較不容易直接由force引導出改正設計的步驟。所以《Refactoring》書中針對各種「不良的form」取了不同名稱的壞味道,只要開發人員能夠辨識出這些「不良的form」(壞味道),也就可以比較容易地套用重構步驟來改善設計,把不良的form調整成比較優良的form。

回到原本的問題:「既然data clumps造成的不良影響與duplicated code和long parameter list那麼像,為什麼還要特別獨立出一個壞味道?」因為data clumps、duplicated code、long parameter list這三者形成的「form」都不一樣。Duplicated code是最廣義的「重複程式碼」型式,只要是表示式、程式邏輯、結構重複,都算在duplicated code身上。因此,廣義的說long parameter list與data clumps也都有某種duplicated code的味道,但是duplicated code卻又不能全部涵蓋long parameter list與data clumps。Long parameter list強調的是「函數參數列很長,而這些很長的參數列有可能會在不同的函數中重複出現,但卻不能說重複出現的參數就一定會形成long parameter list」。Data clumps強調的是「成群結隊出現的資料」,因此尋找此壞味道的重點在於「緊密相連的資料組」,重複出現這些緊密相連的資料組在data clumps這種壞味道中只是一種次要的現象,並非主要觀察的現象。

***

Data clumps之所以會是一個bad smell的原因(force)可歸類為:understandability、usability、modifiability這三點。

移除data clumps壞味道的方法,在《Refactoring》書中提到可以套用Extract Class、Introduce Parameter Object、Preserve Whole Object。

***

Primitive Obsession(基本型別偏執)

物件導向程式語言雖然名為「物件」,。但是程式語言中為了「執行效率」的考量,也提供了一些基本型別(primitive type),像是Java語言的int、double等。雖然這兩個型別也有相對應的物件Integer、Double,但是很多程式設計師還是被教導為「為了效率應該使用基本型別」。

這樣的訓練不見得都是錯的,但是可能造成一種副作用,就是開發人員內心會拒絕或擔心將一些看起來比較小的工作或概念使用小物件來處理。例如,用int來代表郵遞區號,而不是設計Zip類別;用double來代表金錢,而不會設計一個Money類別來處理它。

Primitive obsession放棄了物件導向技術「將行為與操作封裝再一起」帶來的好處,造成的影響就是:

  • Modifiability(修改性):直接使用基本型別而不使用物件,會將操作基本型別的責任交給客戶端程式來處理。若這些責任改變,客戶端程式也會受到影響而改變。當有多個客戶端都受到影響,也就產生了shotgun surgery壞味道。
  • Understandability(可理解性):必須同時閱讀分處不同地方的資料與函數,才能得知程式碼的意圖。此外,基本型別,例如int可以代表年紀、郵遞區號、順序編號等太多種意義。直接使用基本型別來代表某種領域概念也會增加閱讀程式者理解程式碼的認知負擔。  
  • Reusability(重複使用性):由於資料與行為沒有集中在一起,因此不同的客戶端可能會重複實作類似的操作資料邏輯,降低程式的重複使用性。

以上總結primitive obsession之所以會是一個bad smell的原因(force)可歸類為:modifiability、understandability、reusability這三點。

***

移除primitive obsession壞味道的方法,在《Refactoring》書中提到可以套用Replace Data Value with Object、Replace Type Code with Class、Replace Type Code with Subclass、Replace Type Code with State/Strategy、Extract Class、Introduce Parameter Object、Replace Array with Object。

***

友藏內心獨白:差不多快頭暈了。

沒有留言:

張貼留言