連續寫了幾天的 exception handling,今天換個口味,介紹一本在台灣應該算是比較冷門的書:Smalltalk Best Practice Patterns, by Kent Beck.
雖然 Kent Beck 是 Teddy 的偶像,但是 Teddy 也不是『好野』到可以買下大師所寫得每一本書。當初看到書名想說這是一本談 Smalltalk 的書,而 Teddy 又完全不懂 Smalltalk,所以雖然書名也有 Patterns 這個字,但是也沒特別想買(在台灣好像找不到進口這本書的書商,當初是直接從 Amazon 買的)。那,為什麼最後還是買了,而且還要推薦?
記得當年 Teddy 在學 JUnit 設計的時候,看到 JUnit 使用到 『Collecting Parameter』這個以前沒有看過的 pattern (大膽,居然使用了 GoF 之外的 pattern....),而這個 pattern 正是 Kent Beck 在這本書中有介紹到的。此時 Teddy 猜想,這本書應該還有一些其他好料的,所以雖然看不懂 Smalltalk 還是買下來了。
先自首一下,這本書從 2002年5月17號拿到手,到現在 Teddy 只看了 1/3。不過這不是重點,重點是,2003 年 Teddy 在學 Eclipse 設計的時候,居然發現 Eclipse 還有 SWT 也用到好幾個在這本書中有提到的 patterns。由於買了這本書,所以就比較容易了解 Eclipse, SWT 裡面一些 patterns 的用法 (廣義的來說,應該是 Eclipse, SWT 受到了 Smalltalk 的若干影響...)。
舉一個例子,SWT 的 UI 實做了『Variable State』這個 pattern, Teddy 把書中關於這個 pattern 的說明引用一下:
Problem: How do you represent state whose presence varies from instance to instance?
Solution: Put variables that only some instances will have in a Dictionary stored in an instance variable called "properties." Implement "propertyAt: aSymbol" and "propertiesAt: aSymbal put: anObject" to access properties.
翻成白話文就是說,如果屬於同一個 class 的不同 instances 需要各自保有不同的狀態, 那麼請在該 class 中宣告一個 Dictionary (在 Java 裡面可以用 HashTable 之類的物件) 的 data member (attribute)。每一個由這個 class 產生的不同 instances 就可以用這個 Dictionary 來存儲各自所需的資料(鄉民甲:這只是從英文的文言文,換成中文的文言文啊)。
不知道鄉民們是否有這樣的經驗,有一個現有的 class 雖然符合你的需要,但是你還需要增加一,兩個 data member 來儲存其他狀態。如果這個現有的 class 沒有實做 variable state pattern,那麼你可能就必須要利用『繼承』來將你所要增加的 data member 寫在 subclass 裡面。鄉民們應該也都知道好的物件導向設計其實對於『繼承』的使用是很『節制』的,在上述例子中算是有點濫用繼承。舉的 SWT 的例子,在寫 GUI 程式的時候,有時候為了方便起見會把一些變數(或是物件)直接存在 UI 元件上面。假設你用了一個 Button 元件,因為否種原因你想把某個變數存在這個 Button 上面(至於是什麼原因,Teddy 也不知道..!$!@#%)。如果這個 Button 元件沒有實做 variable state pattern,那麼你就要寫一個 MyButton 的 subclass 來儲存這個變數,有點殺雞用火箭炮的感覺。
如果 Teddy 上面所講的鄉民們還是看不懂,沒關係。買一送一,再舉一個 .NET 的例子。有一次 Teddy 在研究 exception handling 的時候意外發現 .NET 的 Exception 類別好像是從 .NET 2.0 還是 3.0 之後,就實做了 variable state 這個 pattern。很可惜 Java 的 Exception 並沒有實做這個 pattern,所以假設你想要在 Java 的 IOException 上面多夾帶一些資料,以便於讓收到 exception 的人可以做進階的處理,很抱歉,你必須繼承 IOException 才行。
**************
好像有點離題,變成在介紹 variable state pattern。總之,這本書中還有很多在其他地方比較看不到的資料,例如,如何幫 instance variable (i.e., data member) 取名字和 pluggable selector 等等, 值得買來珍藏。
最後,引用書中一小段 Teddy 很喜歡的文字作為結尾。
To me, development consists of two processes that feed each other. First, you figure out what you want the computer to do. Then, you instruct the computer to do it. Trying to write those instructions inevitably changes what you want the computer to do, and so it goes. (PS:這一段是起頭,後面那一段才是重點)
In this model, coding isn't the poor handmaiden of design or analysis. Coding is where your fuzzy, comfortable ideas awaken in the harsh dawn of reality. It is where you learn what your computer can do. If you stop coding, you stop learning.
友藏內心獨白: 據說 "If you stop coding, you stop learning." 是 Teddy 的座右銘。
Java Swing其實用了蠻多的Variable State,但是Variable State用多了,其實也不需要定義class (或class也就不需要member data了),全部都用Map或Array來放資料就行了,有時候這取捨很難捉摩,另外用Variable State儲存狀態最大的問題是使用者並不一定會知道存取資料的key在哪裡。Java Exception的Constructor有一個傳入Throwable的版本,要提供類似Variable State的方式也不是不行,定義一個CauseReason類別,同時實作Map和Throwable介面,然後包裝一個HashMap類別,建立IOException時,把CauseReason實例當參數即可,只是取回cause時要判斷是不是CauseReason類別才能轉型比較討厭。
回覆刪除