l
針對查詢「什麼是Pattern」依關聯性排序顯示文章。依日期排序 顯示所有文章
針對查詢「什麼是Pattern」依關聯性排序顯示文章。依日期排序 顯示所有文章

2015年6月3日 星期三

什麼是Pattern(8):兩種命名方式

May 19 17:45~18:10

螢幕截圖 2015-05-19 18.01.48

 

前情提要:

***

螢幕截圖 2015-05-19 17.35.13

改了這麼多回,範例8看起來總算長的比較像pattern的樣子。今天是這系列最後一集,pattern的六大元素只剩Name還沒有介紹。範例8這個pattern的名字就留給鄉民們幫它命名,本集Teddy想談pattern命名的兩種方法:

  • 名詞片語 (Noun-phrase):描述模式所建立或產生的結果,例如Singleton、Command、Model-View-Controller。
  • 動詞片語 (Verb-phrase):給定一個指令,描述如何達到模式解決方案所要求的狀態,例如Don’t Talk to Strangers、Separate Material Preparation from Integration。

這不是上英文課學習英文文法,名詞片語與動詞片語和pattern密切相關。這又要回到Alexander書中對於pattern的描述,請參考圖4:

螢幕截圖 2015-05-19 17.54.54

 

Pattern是一個雙面人,它的一面表示套用pattern的過程(流程),另一面表示套用pattern的結果(套用後所造出來的東西)。幫pattern取名字的時候,如果我們想表達套用pattern之後所完成的東西,就用名詞片語;如果想表示套用pattern的過程,就用動詞片語。

Pattern社群有一個習慣,盡量使用名詞片語來命名。確切的原因Teddy猜想可能是Alexander在《A Pattern Language》書中的253個pattern全部都是名詞,而GoF書中的23個pattern也都是名詞。仔細一想也很合理,原本Alexander就是採用pattern來描述建築領域所建造出來的「東西」,所以以名詞作為pattern名稱也是理所當然的事。例如半隱蔽花園(Half-Hidden Garden)、入口的過渡空間(Entrance Transition)、六英呎深的陽台(Six-Foot Balcony)、禪宗景觀(Zen View)等。

***

Teddy:考考你。

鄉民甲:儘管考!

Teddy:Martin Fowler的重構(Refactoring)是不是一種pattern?

鄉民甲:(又是陷阱題嗎?)我覺得不是,因為它不但是動詞片語,而且完全沒有符合pattern的寫作格式。

Teddy認為refactoring也是一種pattern。雖然refactoring全部都是動詞片語,例如提煉類別(Extract Class)、搬移欄位(Move Field)、重新命名函數(Rename Method)等,但每一個refactoring的內容至少滿足Pattern定義4,只不過Fowler在他的書中沒有採用Teddy所介紹的pattern格式來撰寫。只要細細體會Fowler書中每一則refactoring的內容,也可以將其改寫成符合本系列文章所介紹的pattern六大元素的格式。不信?請看範例9。

螢幕截圖 2015-05-19 17.58.22

 

如果要將範例9寫成更完整的pattern格式需要更多的細節與精煉的過程,但Teddy相信現有內容已足夠展示refactoring可以被改寫成pattern格式。

***

鄉民甲:你不是說大部份的pattern都採用名詞片語,為什麼refactoring要特立獨行採用動詞片語?

Teddy:這個問題很好,還記得我之前提到「A pattern is a process and a thing」這個觀念嗎?因為refactoring的定義就是「在不修改軟體系統外部行為的前提之下改善其內部結構」,透過一連串的小修改步驟以確保這樣的改善行動不會破壞原有的行為。既然refactoring本質上就是一連串的修改動作,所以強調「process」面向也是理所當然。

鄉民甲:原此如此。

Teddy:除此之外我認為還有另一個原因,就是refactoring根本沒辦法強調「thing」。以Rename Method為例,重新命名之後的函數可能性太多,根本無法用名詞片語來描述。如果真的要用名詞片語,會變成Intention-Revealing Name這個pattern,就沒有辦法強調refactoring原本要強調的「process」(修改動作)的面向。

鄉民甲:想不到光是名詞片語與動詞片語的差別,居然有這麼多名堂啊。

***

友藏內心獨白:這就是層次。

2016年7月7日 星期四

什麼是Pattern(9):Pattern的胚胎期

July 06 22:10~23:54

打個廣告,7月份【Design Patterns這樣學就會了入門實作班】招生中,早鳥優惠到7月10日。歡迎有興趣的朋友一起來進入Alexander的pattern世界與實作GoF的設計模式。

 

螢幕截圖 2016-07-06 23.51.26

***

今天想聊一下pattern的起源。這裡的pattern不是指GoF的23個design patterns,而是建築師Alexander所提出的pattern方法。GoF的design patterns是參考Alexander在建築業應用pattern的作法,借用到軟體設計領域而發光發熱。更深入了解pattern的起源,有助於處理 所有的 大部分設計問題。

在1980年之前,建築師Alexander一共寫了以下四本書:

  1. Notes on the Synthesis of Form, 1964.
  2. The Oregon Experiment, 1975.
  3. A Pattern Language: Towns, Buildings, Construction, 1977.
  4. The Timeless Way of Building, 1979.

一般人對於pattern的定義,大多參考《A Pattern Language》或《The Timeless Way of Building》的說法。簡單地說,pattern就是在一個特定情境(context)中,針對重複出現問題所提出有效地解決方法

今天要從《Notes on the Synthesis of Form》(形式綜合論)這本書來討論pattern。雖然在這本書中Alexander並沒有使用pattern這個字,但是用圖解(diagram)代表相同的意義。Alexander在思考設計問題,特別是如何設計出「完整產品」的這個問題,最後提出採用pattern方法。要了解pattern就要先理解Alexander對於設計的看法。

任何一個設計都必須考慮很多因素,以手機為例,設計者必須考慮成本、可靠性、易組裝性、零件可得性、耗電量、效能、尺寸、重量、耐用性、防水性等因素。Alexander將這些影響設計結果的因素稱為作用力(force)。這些作用力彼此互相影響,而且經常是互相牴觸。例如,耐用性高的手機(軍規)重量通常就不會太輕。便宜的零件其效能、可靠性通常較低。要減輕重量,可能需要許多特殊規格的零件,因此降低了零件可得性以及增加組裝困難度。

 

▼如下圖所示,將每一個作用力用一個黑點來表示,並且將這些交互影響的作用力之間用線連起來。如果同時考慮所有的作用力,設計將會變得極其複雜,超出設計師所能掌控的範圍。

螢幕截圖 2016-07-06 22.40.02

 

▼Alexander的想法很簡單,他相信如果可以只考慮一組彼此互動較緊密的作用力,將其他作用力先排除其外,則可以簡化設計的困難。

螢幕截圖 2016-07-06 22.52.58

 

▼以下圖為例,只考慮一小組作用力。針對這一小組作用力,可以得到一個實體關係(physical relationship)(也就是解決方案)滿足這些作用力。而pattern就是這個實體關係的抽像描述而以。換句話說,form(解決方案)是一組作用力的圖解(diagram),而pattern就是這個圖解的抽像描述。 所以pattern至少包含解決方案與作用力。

螢幕截圖 2016-07-06 22.56.15

***

看到這裡,如果鄉民們可以理解上述說法,可能會想:「這又沒什麼,這只不過是『分而擊之』的解題方法而已啊。被切割出來的作用力小集合,具有較高的內聚力。和其他作用力之間,則具有較低的偶合度。

沒錯,的確是如此。但Alexander進一步宣稱,他認為設計可以藉由一次套用一個pattern,而獲得具有整體性的設計(請參考《整體的感覺》)。至於這個宣稱的論述,就要參考在《Notes on the Synthesis of Form》問世之後15年所出版的《The Timeless Way of Building》書中尋找完整解答。

在《Notes on the Synthesis of Form》書中,Alexander還提到關於設計的定義。這個定義Teddy談過很多次:「設計就是決定form和context的界線。」Form就是問題的解決方案這個鄉民們應該可以理解,但怎麼又跑出個context出來?

▼Context中文可以翻譯成情境、環境、場合、上下文,也就是應用解決方案的地方。在真實世界中,存在一個問題,設計就是針對這個問題提出解決方案。但設計不能只考慮解決方案本身,還必須考慮這個解決方案應用於真實世界的環境(context)。根據Alexander的說法,context對於解決方案施加需求因而塑造出解決方案的樣子。

螢幕截圖 2016-07-06 23.25.38

***

最後整理一下,為了解決一個設計問題(problem),找出一小組彼此緊密互動且衝突的作用力(forces),以及可以平衡這些作用力的解決方案(solution),這個解決方案必須發生在一個特定的環境(context)。將以上四個元素記錄下來,幫它一個名字,就成為pattern了(對照Teddy之前提過的pattern六大元素還少一個resulting context,可以先忽略它)。

經過一番討論,不知道鄉民們有沒有發現一件事,就是GoF的《Design Patterns》並沒有特別探討每一個pattern所要處理的作用力到底是什麼?甚至連每一個pattern要解決的問題都交代不清。弱化問題與作用力,很容易讓人只看到解決方案,發生誤用pattern的情況。就好像工具箱擺了一堆工具,如果不知道每一樣工具的用途(在什麼情境中用來解決什麼問題),很可能發生拿螺絲起子敲打釘子的情況。

***

友藏內心獨白:頭暈了。

***

延伸閱讀

2015年6月1日 星期一

什麼是Pattern(7):Resulting Context

May 19 17:00~17:38

螢幕截圖 2015-05-19 17.37.40

 

前情提要:

***

Pattern六大元素講了四個,今天要解釋Resulting Context。鄉民們有看過電視上賣減肥藥的廣告嗎?廣告一開始通常是一位身材豐腴的年輕小姐,正在困擾因為太胖而缺乏自信心,因此交不到男朋友。更慘的是,可能因為體重過重導致身體健康出現問題。(Context)

要如何減重呢?(Problem)

你很懶無法靠運動減肥,也受不了美食和甜點的誘惑。你怕痛,也不敢嘗試侵入式的減重方法,像是抽脂或埋線。(Force)

每日三餐飯前服用三顆「腰瘦牌減肥藥」,連續服用30日,保證一個月後體重減輕10公斤以上。「腰瘦牌減肥藥」由Dr. T耗時10年,耗資上億元所研發成功,不但獲得全球180個國家與地區的專利,還通過美國、歐盟與日本的檢驗。「腰瘦牌減肥藥」是由有機純天然植物油,經過高溫真空殺菌、現代奈米技術過濾與高壓濃縮製造而成,不傷身體,老人小孩皆可安心服用。(Solution)

服用「腰瘦牌減肥藥」不須運動也不用忌口。因為成份天然,保證不傷身體,而且同時有養顏美容之效。讓你輕輕鬆鬆瘦身,找回自信與異性緣。服用期間若有嗜睡、噁心、食慾不振、拉肚子、小便偏黃等症狀,代表身體正在排毒。此為正常現象,請安心服用。(Resulting Context)

Resulting Context就是在原本的Context之下,套用Solution之後的結果。這個結果如果鄉民們可以接受,就代表選對了pattern。如果沒辦法接受,可能是選錯pattern,或是要再套用另外一個pattern,來平衡Resulting Context沒有被妥善處理的Force。

***

再舉個例子,假設鄉民們感冒流鼻水,服用「泰迪牌感冒藥」之後的Resulting Context如下:

  1. 3分鐘之內流鼻水現象立刻停止,且藥效可以維持8小時。
  2. 嗜睡。
  3. 會刺激胃酸。

請問「泰迪牌感冒藥」適合你嗎?Resulting Context的第一點正是你所想要達到的藥效,這一點比較沒有爭議。接著討論第二點嗜睡現象。假設你是一位上班族,正因為連日得流鼻水導致失眠。如果在睡前服用「泰迪牌感冒藥」,嗜睡剛好是你所需要的。但是如果你是一位卡車司機,正在上班的時候,就不適合吃「泰迪牌感冒藥」。

最後討論刺激胃酸的副作用。如果你「胃好壯壯」,沒有胃病的紀錄,這一點對你也沒有影響。但如果你平常就有胃酸過多,甚至是胃潰瘍,那就要考慮換另一種藥物(選擇其他pattern),或是搭配制酸劑一起服用(再套用另一個pattern來解決未解的問題)。

在這個例子裡面,乍看之下Resulting Context第一點是正面的,其餘兩點是負面的。但實際上Resulting Context本身是中立的,是好是壞端看使用情境(白天或夜晚服用)或使用者(有沒有胃酸過多的問題)而定

***

看到這裡鄉民們應該對Resulting Context很清楚了,接下來幫〈什麼是Pattern(6):回應Force,調整Problem與Solution〉的範例7加上Resulting Context,請參考範例8。

螢幕截圖 2015-05-19 17.35.13

***

友藏內心獨白:吃藥要考慮副作用。

2015年5月20日 星期三

什麼是Pattern(5):加入Force

May 19 09:06~09:07

螢幕截圖 2015-05-19 09.45.16 

 

打個廣告先,6月份【Design Patterns入門實作班】早鳥優惠到5/24日,歡迎有興趣的朋友一起來進入Alexander的pattern世界與實作GoF的設計模式。

***

前情提要:

***

螢幕截圖 2015-05-17 23.03.27

不知道鄉民們是否覺得範例4比起之前的版本已經清楚許多?如果僅是根據Pattern定義4來評斷,範例4算是跨越及格標準。但是Teddy要進一步追問,難道pattern的內涵就僅是Context、Problem、Solution而已嗎?

Pattern定義5A pattern is a proven solution to a recurring problem in a specific context, and more(模式是在一個特定情境之下,針對一個重複發生問題的成熟解決方案,和更多。)

鄉民甲:…, and more?這算是什麼爛定義啊。

***

Pattern的格式有很多種,Teddy採用的是以下包含六個元素的格式:

  • Name:模式名稱,增加開發者的設計字彙。
  • Context:描述問題發生的地形地物。
  • Problem:描述問題本身。
  • Force:作用力,用來指出問題的限制或特性。
  • Solution:解決方案。
  • Resulting Context:又稱為consequence,套用解決方案之後的結果。

六個元素之中的Context、Problem與Solution都已經介紹過了,接下來解釋其他三個元素。首先討論Force,它是這六個元素中最抽象也最難解釋的一個,因為它看不到,摸不著,只能「用心體會」,藉由觀察Solution來推敲Force

Alexander在他的書中用不同的講法來解釋pattern。首先看到圖2的說法,這個講法和圖GoF的講法一致(A pattern is a solution to a problem in a context),只提到Context、Problem和Solution。

螢幕截圖 2015-05-19 09.35.57

 

圖3是Alexander書中對於pattern的另一種敘述。在這個敘述中,Problem這個元素不見了,取而代之的是Force。

螢幕截圖 2015-05-19 09.36.33

Force告訴我們為什麼pattern所要解決的「問題」是一個真正的問題。為什麼這個問題很難?為什麼需要一個聰明的,甚至是違反直覺的解決方案?Force也是了解為何會採用此種解決方案的關鍵 [POSA5]Force是pattern很重要的一個元素,簡而言之它讓Problem更明確,也讓Solution 更加完整與成形。

考慮Force這個元素,將範例4改寫為範例5。請問,範例5是一個好的pattern嗎?(範例3-5

螢幕截圖 2015-05-19 09.43.19


***

友藏內心獨白:觀察Force的能力真的很重要。

2012年5月31日 星期四

Pattern是個雙面人(上)

May 30 23:18~May 31 00:20

image

 

如果有人問你:「什麼是pattern?」,你會怎麼回答。

 

鄉民甲:(跳、跳)選我,選我。

Teddy:請作答。

鄉民甲:A pattern is a proven solution to a recurring problem in a specific context。

Teddy:還有沒有其他的解釋嗎?

鄉民甲:糟糕,只背到這一句。ㄟ,沒有,等你教。

***

關於pattern,除了上面那一句常見的解釋,還有另外一句鄉民們可能比較少聽到,但卻也是很重要的觀念,那就是Alexander在《The Timeless Way of Building》書中提到的:A pattern is a process and a thing。

蝦米?Pattern是「流程」也是「東西」?此話何解?

一個pattern本身表達一件「東西」,這個東西,以建築領域來說,可能是一張代表該pattern意境的照片;如果是軟體的pattern,可能是高階的設計圖或是程式實作的邏輯描述。

如果鄉民們手邊剛好有《A Pattern Language》這本書(應該是沒有人會有…XD),翻開書中的每一個pattern,第一眼看到的就是一張代表該pattern的照片。看一下這本書第548頁代表Entrance Transition(入口的過度空間)這個pattern的圖,再接著看這個pattern的目的。

螢幕快照 2012-05-30 下午11.47.01

 

Buildings, and especially house, with a graceful transition between the street and the inside, are more tranquil than those which open directly off the street.

看完圖之後再讀這個pattern的意圖就比較容易理解。

很可惜GoF的Design Patterns並沒有像Alexander一樣在每個patter開始之前先給張圖瞧瞧。不過Design Patterns裡面的Structure某種程度也扮演著類似的角色。畢竟軟體設計的patterns有時候不是那麼容易可以用一張圖或是照片來表達它的意涵。但是,如果鄉民們patterns的書看得夠多的話,就會發現有些人所寫的patterns是會參考Alexander原本的風格,在開始用文字描述pattern之前先提供一張照片。例如,《Patterns For Fault Tolerant Software》這本書的patterns寫作方式就是採用Alexander在《A Pattern Language》書中的寫作方式。

總之,pattern的第一個面向就是:要能夠讓人讀了之後知道這個pattern所代表的「東西」是個什麼樣的玩藝兒(請捲舌)。

***

Pattern的第二個面向就是:它是一個流程。鄉民們心中可能會想:「拜託,pattern是一個東西我勉強還能夠接受,pattern是一個流程這又是那招?」流程,是waterfall還是RUP這種流程嗎?還是Scrum?

都不是,這裡說的流程是指「讀了pattern的解決方案之後,鄉民們應該有能力能夠把這個pattern給實做出來」。如果做不到,就表示這個pattern可能寫得不夠好(迷之音:當然也有可能是讀pattern的人太笨…Orz)。

總之,pattern的這兩個面向,是在學習撰寫pattern時很重要的觀念。以Teddy自己的經驗,要同時把「東西」跟「流程」都描述得很好其實並不容易(寫作本來就是一件很難的事情)。姑且先不管寫作pattern,畢竟大部分的鄉民都屬於「pattern使用者」,而非「pattern產生者」。請鄉民們思考一下,「A pattern is a process and a thing」這個事實對於「學習pattern」這件事有何幫助?

下集待續。

***

友藏內心獨白:難不成patterns是黑白郎君嗎?

2012年7月26日 星期四

Scrum框架下的跨界開發(8):寫到這邊突然想到Pattern Languages

July 25 22:33~July 26 00:21

螢幕快照 2012-07-25 下午10.50.21

 

先說明一下,本集內容有點玄,看不懂為正常現象(迷之音:文「玄」慎入,請勿越級打怪XD)。

話說跨界開發這件事寫到第八集,Teddy突然想到Christopher Alexander的pattern languages理論。先解釋一下上面這張圖,和昨天畫的那張圖很像,只是有些地方稍微修改一下。先解釋一下幾個名詞:

  • World:真實世界,也就是問題發生的地方。有問題,就代表有需求,所以才會有人說「需要為發明之母」。例如,鄉民們要開發甚麼ERP系統、汽車控制系統、體重控制軟體、雲端殺豬系統。這些系統都是因為要解決真實世界的某些問題而產生的,也就是說這些系統的「需求」發生在真實世界。
  • Machine:開發軟體以解決某個發生在真實世界的問題,就相當於製造一台「機器」。所以,這個Machine就是所謂的Solution。事實上,Teddy可以大膽說,鄉民們在學校或是工作中所受的訓練,絕大多數都屬於Solution的範疇,只有一小部分與Problem有關。例如,OOAD,A的部分(分析)是屬於Problem,其餘D的部分(設計),以及後來的實作、測試、寫手冊等等,都屬於Solution的範圍。再舉敏捷實務做法為例子,什麼持續整合、單元測試、pair programming、建構管理、shared code、測試驅動開發,這一些全部都是Solution。更別提程式語言、演算法、資料結構,當然也是Solution。
  • Application Domain:真實世界很大,而你所製作出來的機器很小…Orz。你的機器與真實世界相關的這個部分,就稱為Application Domain(應用領域)。例如,鄉民們可能有聽說過,某人是在負責銀行業、保險業、物流業、IC設計業等等。這些不同的「業別」,就可視為不同的Application Domain。看到這邊鄉民們可能會為:幹嘛分什麼Application Domain?很簡單,因為真實世界太大,而鄉民們(工程師)又太渺小,不可能做出一個可以解決全世界問題的機器出來。所以才要把世界切成不同的Application Domain,這樣問題變得比較小,而鄉民們才有辦法可以把機器給造出來。

World與Machine之間的箭頭,Machine的建造需要從World獲得需求。而隨著Machine的建造,應用到World中,則可以讓鄉民們更清楚的了解需求。

由上圖可以看的出來,很明顯的World和Machine各是一個孤島,要把World所發生的問題,轉成一個Machine,這中間的過程有一個很大的鴻溝,因此需要一座橋樑,讓這兩個孤島上的人,可以互相往來。這是從World到Machine的「跨界」。World的內部和Machine的內部也存在著跨界的問題,關於Machine內部的跨界問題Teddy在《Scrum框架下的跨界開發(2)》曾經提過,這邊就不在重複。

現在的問題是,「誰」,或者是「什麼東東」,可以扮演這個Bridge的角色?想到這個問題,Teddy的腦海中浮出兩個答案:

  • 流程:不管是傳統的結構化分析與設計、後來的物件導向分析與設計、RUP、敏捷方法(例如Scrum),都是在告訴鄉民們,如何從A—>D的過程。也就是從分析(What to do。要做什麼東東,也就是把問題搞清楚)到設計(How to do。問題清楚了,那接下來要怎麼做,解決方案是什麼。)所以,流程本身是一個很好的Bridge。
  • :10幾年前Teddy剛開始接專案的時候,從需求分析、系統設計、實作、測試、寫手冊、到客戶端裝機,全部都是一個人包辦。所以,人也是一種很好的Bridge。

***

寫到這邊和pattern languages有何關係?Teddy想到當初Alexander發明pattern languages的出發點,其實跟上面這「流程」和「人」有很密切的關係。話說Alexander觀察到,在農業社會,絕大多數的人所居住的房子,其實都是自己蓋的。古時候沒有什麼「建設公司」幫忙蓋集合住宅,也沒有政府提供合宜住宅。再加上大部分的人口都是務農,也沒多餘的錢請人家蓋房子。所以,要房子嗎?好,爸爸蓋給你XD。

但是,現代工業社會因為強調所謂的「效率」,因此產生了「專業分工」以便於大量生產。所以,建商出現了,仲介出現了,原本人類具有的蓋房子能力,也因為專業分工的緣故而消失殆盡。

在此Teddy先插花一下,專業分工的這個觀念很重要,因為,傳統上大家都認為專業分工是很好的。但是請注意到Scrum的cross-functional team,以及XP的pair programming與shared code,其實多多少少存在著打破專業分工的精神。

簡而言之,Alexander希望人們可以重拾以往「具備自己蓋房子」的能力,而他所提出的方法就是pattern languages。鄉民們還記得pattern的最簡單的定義是什麼嗎?

A pattern is a proven solution to a recurring problem in a specific context.

一個模式是在特定領域中,針對一個重複發生的問題,已被證明有用的解決方案。

Pattern包含了problem和solution,所以一個pattern就是一個什麼?想到了沒?

每一個pattern就是一個小小的bridge,可以解決一個小問題。一堆相關的pattern,就形成一個pattern language,可以解決一個較大的問題。

***

Alexander在他的書中說過,pattern is a process and a thing。這個觀念Teddy在《Pattern是個雙面人(上)》和《Pattern是個雙面人(下)》有解釋過。Teddy認為Alexander當初要解決的問題,基本上就是一個「跨界」的問題:讓沒有具備建築能力的廣大鄉民們,能夠在學習pattern之後,具備這樣的能力。這不是跨界是什麼?不只跨界,還跨很大哩。

鄉民甲:我以前是水電工,去了鋸匠之後,我現在是建築師XD。

Teddy:這也是一種跨界喔。

***

寫到這邊Teddy自己也不知道在寫些什麼…Orz。最後一個重點,為什麼繼Scrum課程之後,Teddy要在8/25開「Design Patterns這樣學就會了:入門實作班」這門課?Design Patterns不是寫寫程式,或是買本書看一下就懂了嗎?10幾年前Teddy剛學Design Patterns的時候,Teddy只是把Design Pattern看成是一種高深的物件導向設計招式。但是讀了Alexander的書之後,慢慢覺得pattern與pattern language方法其實是一種很好的分析問題工具,可以幫助工程師們把困難的問題經過pattern的訓練,深刻了解問題的本質。

但是,為什麼要深刻了解問題的本質?每天跟派大星一樣爽爽地過日子不是很好?!答案很簡單,因為要成為一個更好的工程師。聽起來很無聊,但是Teddy認為,這是一個很重要的能力。曾經有人問Kent Back,XP的做法是否會排斥能力很強,但是可能不喜歡跟其他人合作的人。Kent Beck說:什麼叫做很強的人?從他的角度來看,能夠讓你的同事把原本認為很難的問題,經過你的協助之後,馬上開竅,具備解決問題的能力。這種人才是Kent Beck所認為的很強的人,而非自己很強但卻不管別人死活的那一種人

Teddy認為Alexander的pattern language方法可以協助工程師們變成Kent Beck所說的那種很強的人。但是,此方法有點抽象,直接學習可能會死人XD。其實是怕說開這樣的課應該沒人來上。所以Teddy只好循序漸進,先從比較實用的Design Pattern開始教起,在課程中慢慢灌輸一些Alexander最原始提出pattern的想法。

難道課名叫做「Design Patterns這樣學就會了」是一種幌子,實際上是要在課堂上傳授邪教?

想太多,來了就知道。

***

友藏內心獨白:怎麼本篇又被置入性行銷啦XD。

2015年5月18日 星期一

什麼是Pattern(4):修正Context

May 17 22:20~23:06

螢幕截圖 2015-05-18 00.05.44

 

經過幾次修改之後(請參考〈什麼是Pattern(1):第一個例子〉、〈什麼是Pattern(2):修正Problem〉、〈什麼是Pattern (3):修正Solution〉),範例3的內容已經比範例1改善很多,快要到達及格邊緣。

螢幕截圖 2015-05-13 11.10.40

 

螢幕截圖 2015-05-14 17.00.25

 

鄉民甲:什麼!改成這樣還沒及格?

現在請鄉民們先忽略Context,把焦點放在範例3的Problem與Solution。除了提供免費遊戲然後靠販賣道具營利之外,難道沒有其他方法嗎?市場上明明有些公司可以直接向玩家收取月費。別人可以,為什麼我們不行?

***

再看另一個例子:

Problem:如何讓玩家願意掏錢玩線上遊戲?

Solution

1. 推出著名大作,讓玩家非買不可。

2. 採用免費遊戲策略,但如果要升級則玩家就必須要花錢購買道具。

3. 推出賭博或18禁的情色遊戲。

請問以上三個解決方案,哪一個比較好?這麼無厘頭的問題,很難回答。因為少了Context,也就缺少了問題發生的背景知識,因而無從判斷哪一個解決方案比較合適。

***

Pattern的三個元素,其中Problem與Solution都被挑剔過了,接下來該輪到Context。從範例1到範例3,Context的內容全部都是:「你是線上遊戲業者」。這是一個「你家住海邊」的情境(管很大),包含太多可能性。小從個人手機APP開發商,大到自己有幾百人研發團隊的公司,或是只負責線上遊戲營運的廠商,又或者是國際知名老牌遊戲大廠,全部都符合Context的描述。

顯然問題出在Context過於一般化,讓我們修改pattern定義來避免這個問題。

Pattern定義4A pattern is a proven solution to a recurring problem in a specific context(模式是在一個特定情境之下,針對一個重複發生問題的成熟解決方案。)

根據的Pattern定義4修正範例3的Context與Problem,改寫為範例4。請問,範例4是一個好的pattern嗎?(鄉民內心獨白:怎麼還來啊!)

螢幕截圖 2015-05-17 23.03.27

***

友藏內心獨白:怎麼還來啊!。

2015年5月27日 星期三

什麼是Pattern(6):回應Force,調整Problem與Solution

May 19 16:00~16:57

螢幕截圖 2015-05-19 16.56.27

 

前情提要:

***

螢幕截圖 2015-05-19 09.43.19

 

加上兩點新增的Force之後,我們發現範例5的Solution並沒有回應它們所指出的問題,也就是安裝繁瑣或費時的遊戲玩家根本連玩都不想玩,以及光是付費將會減少玩家對於同一款遊戲的黏著度。為了回應這兩點force,將範例5的Solution改寫成範例6。

螢幕截圖 2015-05-19 16.51.01

***

拜Force所賜,我們得以將範例6的Solution改的更完整。此時再回頭修改Problem讓它更明確,請參考範例7。

螢幕截圖 2015-05-19 16.52.49

***

Teddy之前說過:「Force讓Problem更明確,也讓Solution 更加完整與成形。」範例6與範例7正是反應這句話的具體範例,前者讓Solution更加完整與成形,後者讓Problem更明確。

***

友藏內心獨白:平衡Force的Solution才是一個好的Solution。

2014年2月12日 星期三

Pattern的修練途徑:從The Timeless Way of Building看起

Feb. 10 14:33~15:58

螢幕快照 2014-02-10 下午3.57.40

 

有鄉民問Teddy:「為何台灣不少軟體公司有恐design pattern症?」Teddy覺得可能是因為以下的原因:

  • 學會GoF的23個Design Patterns本身就需要一點門檻。
  • 學會GoF的Design Patterns之後,要能夠靈活運用在專案之中又需要一些時間的磨練。
  • 能夠靈活運用GoF的Design Patterns之後,發現怎麼世界上還有各式各樣的「Design Patterns」存在,要等到哪一天才學的完啊。

***

套用pattern在軟體、架構、介面等領域的設計,已經是一種主流方法。但是「如何活用pattern」的答案,並不存在GoF的《Design Patterns》這本書裡面,而是要回到pattern的創始者:Christopher Alexander 的書中去尋找。

這個過程,依據《The Timeless Way of Building》的說法,有五個階段:

  1. The Timeless Way:首先必須要知道一個有形的物體或是無形的專案,唯有依循「永恆之道」才可能會完整、有生氣、持久存在。「永恆之道」是一種「流程」,它無法被求取,但只要順應它,它便會自然出現。
  2. The Quality:為了探求「永恆之道」,必須先了解無名特質(quality without a name,QWAN)。這種特質清楚明確,但卻無法被命名。為了定義這種特質,我們必須了解每個地方(或是專案、團隊、公司)的特徵是由不斷發生在哪裡的事件模式(patterns of events)所賦予。這些事件模式與空間中的幾何模式(geometric patterns)相連接。而組成建築、城市(專案、團隊、公司等)的特定模式可以是有活力的,也可以是死氣沉沉的。具有越多有活力的的模式,就越具有無名特質的自我維持特性。
  3. The Gate:為了達到無名特質,我們必須建立一個有活力的模式語言(living pattern language)作為大門。
  4. The Way:一旦建好了門,我們可以通過它進入到永恆之道的實踐。
  5. The Kernel of the Way:永恆之道並未完結,直到我們把大門(pattern language)拋在身後,才有可能徹底產生無名特質。

***

以上五個步驟有點抽象,打個比方,QWAN是一種修練的境界,到達這種境界,就可以讓所創造出來的物品(建築物、城市)達到永恆之道。就好像修練「成佛」之後,便可脫離輪迴,進入永恆之道。

但是,要怎樣才能「成佛」,很難解釋「成佛」的特質是什麼。於是我們需要佛經,來做為修練的大門(the gate)。熟念經典,並且在日常生活中實踐經典的教義,就是到達永恆之道的修練(the way)。

最後,把這些經典拋諸腦後,無招勝有招,大概就離悟道不遠了。

Alexander的想法,是藉由pattern來達到或是探求QWAN,所以他在《A Pattern Language》這本書整理了253個pattern。繼續往下追問,什麼是pattern?Pattern就是一堆force的集合,pattern的solution平衡了這些force,使得它的外在世界(context)達到某種(有活力的)特質。所以「整理pattern」本身就是一種很重要的修練,一種觀察force、體驗QWAN的修練。這也是為什麼Teddy在每一次的「Design Patterns這樣學就會了:入門實作班」都會安排將近一整天的時間,來讓學員練習撰寫pattern、尋找force、觀察solution是否平衡每一個force、resulting context又變成如何。

這種練習,從GoF的《Design Patterns》是學不到的,在台灣也很難找到人教導。

***

除了缺少整理pattern的自我練習以外,GoF的《Design Patterns》還少了一個很重要的因素,就是「它只是23個pattern的集合,並不是一個pattern language」。一個pattern解決一個小問題,要解決大的問題,需要套用一組pattern,形成一個pattern language。很可惜在GoF的書裡面,每一個pattern解釋得很清楚,但卻沒有強調pattern language的觀點,這也可能是導致很多人學完23個pattern之後,需要比較長的一段時間,才可以融會貫通的原因。

***

市面上各種各樣的pattern數量應該早就破千了,不了解Alexander原始的想法,個別去研究每一個pattern,很可能會事倍功半,更糟的可能會徒勞無功。要在短時間內入門並立即可活用pattern,最快且有效的途徑,就是請報名參加:

***

友藏內心獨白:為了生活,還是要打個廣告挑眉質疑

2014年4月16日 星期三

重新整理Factory Method Pattern,Take 2

Mar. 19 09:10~10:50

螢幕截圖 2014-03-19 10.47.07

 

這幾年心中有一個心願,想要寫一本Design Pattern的書,先談談Alexander的Pattern理論,再依據context、problem、force、solution、resulting context等元素,把GoF Design Patterns這本書裡面所介紹的23的pattern重新整理一遍。希望經過這樣的整理,可以讓鄉民們用不同於現有大部分文獻、書籍的角度,以比較「系統化」且相對「輕鬆」的方式,來學習與重新檢視pattern。

結果2012年先出版了《笑談軟體工程:敏捷開發法的逆襲》,而第二本書《笑談軟體工程:例外處理設計的逆襲》也預計即將在今年四月出版。但是這個「整理pattern」的工作卻比想像中要來的艱鉅,到現在八字都還沒一撇。

鄉民甲:GoF Design Patterns都出版快20年了,網路上的文章、市面上的書也那麼多,何難之有?

困難的地方在於:

  1. Alexander的Pattern理論:Teddy在部落格上面談了好幾次關於Alexander的Pattern理論,還有它對於「到底什麼是設計」的看法。這個問題乍看之下很抽象,過於理論,好像沒什麼實用價值。但對於一個「(軟體)設計師」而言,弄清楚這種抽象觀念的助益卻是難以想像的大。弄懂Alexander的Pattern理論需要一些功夫,弄懂之後再用鄉民聽得懂的方式轉述一次,又是另外一種挑戰。
  2. 重寫每一個GoF Design Pattern所謂「重寫」的意思不是找個看起來很有趣且通俗的「程式範例」來解釋pattern,而是要用context、problem、force、solution、resulting context的格式來「重新包裝」這23個pattern。不管是哪一本書,只要是教導GoF的23個design pattern,提到每一個pattern定義的時候,一定會列出GoF書中關於pattern的intent(意圖)。如果鄉民們仔細閱讀GoF書中關於每一個pattern的intent,這些內容的敘述,大部分是指solution,而pattern的problem與形成這些problem的force則是散布在其他內容之中,要靠自己慢慢去「提煉」。鄉民們可能都知道pattern是一個problem-solution pair(一個pattern包含一個問題的解法),學過pattern的各位,對於每一個pattern的解法必定非常熟練,但有辦法很清楚地用一句話說出每一個pattern的解決什麼「問題」嗎?隱隱約約好像知道,但卻又不太容易說明白。如果可以把GoF的每一個pattern重新整理一遍,對於學習、套用design pattern,會有很大的助益。

***

2013年8月花了點時間重新整理了幾個pattern:

最近對於Alexander的pattern理論又有一些比較不同的想法,所以想要把這些看法加入「Design Pattern這樣學就會了」的課程教材,因此又回頭看了一下之前整理的pattern,順便看看有沒有可以改進的地方。看到之前整理的Factory Method,覺得context寫得不好,想要修改一下,沒想到這個「修改一下」的念頭,居然花了兩整天的時間。

以下是修改前的內容:

***

Name:Factory Method (修改前)

Context:許多物件導向程式語言提供我們用new表示式來產生物件,但並非所有的物件都可以簡單地透過new來產生。

Problem:如何產生一個物件?

Force:

  • 你有一群繼承自相同介面的產品物件,
    • 你想要將產生哪一個具體產品物件的責任交由子類別來決定,可能是因為在編譯期間你並不知道要產生哪一個具體類別,又或者是你想要提供子類別產生具體產品類別的彈性。
    • 你允許客戶端傳入參數來選擇所要產生的具體類別。
  • 物件產生之後尚須經過適當的設定步驟才可以傳回給客戶端使用,如果可以將產生物件的過程從客戶端抽離出來,則可以避免客戶端產生重複的程式碼。

Solution:將產生物件的詳細步驟封裝在一個factory method裡面,讓客戶端程式透過這個factory method來得到新的物件。

***

以下是修改後的內容:

Name:Factory Method (修改後)

Context: 你有一個抽象的「產品介面」,該介面通常有多種不同的具體實作,稱為「具體產品」。你的程式將會使用到這些「具體產品」。

Problem: 如何產生物件?

Force:

  • 在設計階段(編譯期間)你並不知道會使用哪一個具體產品類別。
  • 需要依賴另外一個物件來決定要產生哪一種型別的具體產品物件。
  • 讓客戶端直接產生具體產品物件是最簡單的方式,但會造成兩者關係過於緊密(耦合性太高),限制日後替換具體產品物件的彈性。
  • 你可以套用Simple Factory,把產生哪一種「具體產品」類別的條件式判斷集中在一起(套用Simple Factory,)。但是只要有新的「具體產品」類別加入,你還是必須修改Simple Factory的條件式。

Solution: 將產生物件的過程封裝在物件的某個函數(factory method)裡面,客戶端程式必須透過這個函數來取得物件。新增建構者(Creator)類別,將負責產生具體產品物件的責任交由它負責。在建構者身上定義一個專門回傳「具體產品」物件的函數(Factory Method)以實作此責任。

透過繼承,建構者的子類別可以覆寫Factory Method,以便傳回特定的具體產品物件。在這種情況下,一個具體建構者绑定一個具體產品。建構者也可以透過泛型程式設計(generic programming)技巧,來實作Factory Method,以取代僅是為了覆寫Factory Method就必須新增建構者子類別的做法(減少不必要的建構者子類別數量)。

***

關於Factory Method其實還有很多東西可以說,以後有機會再談。最後只說一點,在GoF的書中,Factory Method的定義(意圖)是:

Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.

這個定義裡面,有一句話「let subclasses decide which class to instantiate」(讓子類別決定產生哪一個類別的實例)剛開始Teddy在整理Factory Method的時候,被這句話困擾許久。因為「讓子類別決定產生哪一個類別的實例」只是一種實作Factory Method的方法,並非導致形成Factory Method這個solution的關鍵force,真正影響Factory Method的force另有其人。但是這句話又被放在Factory Method的意圖裡面,應該不能忽視它才對啊挑眉質疑。最後思考了許久才再度體會到「盡信書不如無書」這件事,不必拘泥於原本書中對於每一個pattern意圖的描述。

仔細看GoF的書,在Factory Method的實作敘述中就提到可以不透過繼承實作Factory Method的方法。以前讀書的時候沒觀察到,書中對於Factory Method意圖的描述其實還「不夠抽象」。如果改成這樣也許會比較清楚一些:

Define an interface for creating an object, but let its clients decide which class to instantiate. Factory Method lets a class defer instantiation to its clients.

這個client,可以是subclass,也可以是透過composition關係來使用Factory Method的其他物件。

***

友藏內心獨白:寫書搞得好像要出paper一樣,也太累了吧挑眉質疑

2014年2月25日 星期二

如何選擇第一個Pattern來設計軟體架構?

Feb. 24 13:00~14:40

螢幕快照 2014-02-20 下午2.36.00

先打個廣告,「第六梯次Design Patterns這樣學就會了:入門實作班」已經確定開課了,早鳥優惠到今天(2014/2/25 23:59)結束。

***

Teddy每次上「Design Patterns這樣學就會了:入門實作班」都會舉一個如何以「一 次套用一個pattern」的方式來設計軟體架構的例子,這個方法就是Alexander在《The Timeless Way of Building》所提到的Pattern Language方法。

前幾天在C. C. Agile Sprint 18活動中Teddy也快速介紹這個方法,有人問Teddy:「一次套用一個pattern,請問如何選擇第一個pattern?」

螢幕快照 2014-02-24 下午1.27.32

 

Pattern和Pattern Language的關係,就好比「英文單字」和「英文」的關係。要學英文(或是其他語言也一樣),總是需要先「背單字」,累積足夠多的字彙量。這個「背單字」的學習過程就類似學習單一pattern的過程。學習GoF Design Patterns、Kent Beck的Implementation Patterns、Martin Fowler的Enterprise Application Architecture Patterns和Analysis Patterns、《Pattern-Oriented Software Architecture》與《Pattern Languages of Program Design》這一系列的書,都是在「背單字」。

背單字有兩層涵義,不是把pattern的名稱,例如MVC、Observer、Command這些名字記下來就好了,還要知道怎麼做。

螢幕快照 2014-02-24 下午1.45.11

 

Pattern同時具備process與thing這兩個面向,thing代表「要做出什麼東西」,process代表「要怎麼做」。學習pattern如果不知道這兩個面向,花再多時間K書、參加讀書會,也是枉然不要告訴別人

***

Teddy發現,不少人學pattern,只學得process,「我知道怎麼實作Observer、Command、Singleton」,但卻不知道「為什麼要套用這些pattern」,那就是對於要產生什麼東西(thing)沒有真正理解。也就是說,沒有觀察到pattern的force。

另外一種情況,則是「說得一口好pattern」,知道每一個pattern所要達成的目的,但卻沒有實作能力。這種情況,也只能算是「投降輸一半」挑眉質疑

回到原本的問題:「一次套用一個pattern,請問如何選擇第一個pattern?」。會有這樣的疑問,首先一定是pattern的單字量不夠多,或是pattern的單字量夠了,但是學習的「質」不夠,沒有了解pattern的process與thing這兩個面向。大部分的人,都還處於這個階段。

***

如果pattern的單字量與質都夠了,還是存在「一次套用一個pattern,請問如何選擇第一個pattern?」的疑問,這時候才牽扯到pattern language層次的問題,也就是如何以pattern作為單字來講出一段話(做出一個設計)

螢幕快照 2014-02-24 下午2.00.59

***

Alexander說,套用pattern形成pattern language的精神是一種「整體先於部分,然後透過差異化的過程將整體逐步展開」。這句話聽起來有點玄,弄清楚之後卻覺得很簡單。就跟講話一樣,一定是在腦中先有一個想法(整體先於部分),然後在由上而下用一個字、一個字,一句話、一句話慢慢將想法(整體)逐步展開。

無法一次套用一個pattern來設計軟體架構的原因,大的方向就是Teddy上述提到的這樣。其實要學會pattern language,概念很簡單,但是「箇中修行之道」還是有一些小竅門。很可惜在台灣,絕大部分的軟體開發人員在學習pattern的時候,大概只看過下列這幾本書(中文英不拘)。只知道背單字,卻不知為何背單字,不要說一個打十個,就連「釘孤支」都有點勉強啊。

Image (8)

***

Alexander說:「If your language is empty, your buildings cannot be full. If your language is poor, you cannot make good buildings until you enrich your language.(如果你的語言是空泛的,你的建築物不可能充實。如果你的語言是貧乏的,你不可能造出好的建築物直到你豐富你的語言)」

結論就是:快去背單字吧。

***

友藏內心獨白:不是要先學ABCD還有五十音嗎?挑眉質疑

2012年9月28日 星期五

尋找Force實驗2:State Pattern篇

Sept. 27 14:51~16:40

image

 

昨天Teddy在《尋找Force:Observer篇》中舉了Observer pattern為例子,說明GoF的pattern寫作格式中,Motivation章節相對於Teddy之前提到的pattern六大元素裡面的force。如果《尋找Force:Observer篇》鄉民們有看懂的話,可能會有一個疑問:

這該不會是碰巧運氣好才在Observer pattern的Motivation找到force的吧?!

昨天寫完《尋找Force:Observer篇》之後Teddy也有同樣的疑惑,那今天就找另外一個有點小複雜但卻十分有用的State pattern來做第二個實驗。今天先從Intent改起(把Intent改成Problem)。

Intent

Allow an object to alter its behavior when its internal state changes. The object will appear to change its class.

修改後:How do you allow an object to alter its behavior when its internal state changes? (後面那句可省略)

中文:要如何讓一個物件的行為隨著內部狀態改變而跟著改變?

接下來看一下GoF書中State pattern的Motivation。

Motivation

Consider a class TCPConnection that represents a network connection. A TCPConnection object can be in one of several different states: Established, Listening, Closed. When a TCPConnection object receives requests from other objects, it responds differently depending on its current state. For example, the effect of an Open request depends on whether the connection is in its Closed state or its Established state. The State pattern describes how TCPConnection can exhibit different behavior in each state.

The key idea in this pattern is to introduce an abstract class called TCPState to represent the states of the network connection. The TCPState class declares an interface common to all classes that represent different operational states. Subclasses of TCPState implement state-specific behavior. For example, the classes TCPEstablished and TCPClosed implement behavior particular to the Established and Closed states of TCPConnection.

The class TCPConnection maintains a state object (an instance of a subclass of TCPState) that represents the current state of the TCP connection. The class TCPConnection delegates all state-specific requests to this state object. TCPConnection uses its TCPState subclass instance to perform operations particular to the state of the connection.

Whenever the connection changes state, the TCPConnection object changes the state object it uses. When the connection goes from established to closed, for example, TCPConnection will replace its TCPEstablished instance with a TCPClosed instance.

抱歉,Teddy能力有限,從上面的段落中完全找不到任何一個force…Orz。

請問一下鄉民,State pattern的Motivation章節看起來比較像什麼?

沒錯,比較像是Solution的範例

***

既然在Motivation找不到force,請問鄉民下一個尋找的章節是哪一個?

答對了,就是Applicability

鄉民甲:為什麼?

Teddy:還記得Teddy在《Force是什麼?》有提到一個問題「force和context很像耶,好像可以把force放到context裡面,也可以把context裡面的東西變成force。要如何判斷?」先不要管這個問題的答案,至少這個問題提供給鄉民們一個線索,在Motivation找不到force的話,那就到Context去找吧。GoF的pattern寫作格式中,Applicability相等於Context,所以接下來看一下State pattern的Applicability。

Applicability

Use the State pattern in either of the following cases:

  • An object's behavior depends on its state, and it must change its behavior at run-time depending on that state.
  • Operations have large, multipart conditional statements that depend on the object's state. This state is usually represented by one or more enumerated constants. Often, several operations will contain this same conditional structure. The State pattern puts each branch of the conditional in a separate class. This lets you treat the object's state as an object in its own right that can vary independently from other objects.

GoF書中記錄的Applicability有兩點,第一點翻成中文的意思是「一個物件的行為和物件本身的狀態有關係;在執行期間,物件的狀態若是改變,則其行為也會跟著改變」。這一點是描述一個事實,比較像是Context。第二點就比較可以找到force,請觀察這一句:

Operations have large, multipart conditional statements that depend on the object's state. This state is usually represented by one or more enumerated constants. Often, several operations will contain this same conditional structure.

為了讓物件的行為可以隨著狀態改變,一個很簡單的做法就是物件的operation(method或是member function)程式碼裡面有著一個很大的條件判斷式(if-then-else或是switch case)。在不同的物件狀態之下,程式會執行條件判斷式的不同區塊。這還不打緊,問題是相同的條件判斷式結構,會出現在這個物件身上好幾個不同的operation中。這就形成了眾所皆知的duplicated code這個程式碼壞味道了。

扯這麼多,那State pattern的force是什麼?以下是Teddy所推敲的force:

  • 在物件的operation中使用條件判斷式,並依據狀態改變物件行為的這種作法雖然很直覺且簡單,但是會造成物件不同的operation中會出現多處重複的條件判斷式,造成日後維護與擴充的困難度。
  • 由於物件的行為隨著狀態而變,因此若是一個物件的所有行為全部都放在物件自己身上,則容易造成單一物件程式碼太長,同樣增加維護與擴充的困難度。
  • 當物件狀態很多的時候,如果狀態改變的邏輯無法很清楚的被表達出來,則程式可能不容易被理解。

***

State pattern的解決方案Teddy就不在這裡說明(鄉民:不在這裡說明那是要在哪裡說明?挑眉質疑),不然這一篇會寫不完啊。如果知道State pattern的鄉民們,請看一下這三個force,然後思考一下State pattern的solution是否有解決上面這三個force?

螢幕快照 2012-09-26 下午5.25.40

圖片來源:http://upload.wikimedia.org/wikipedia/commons/e/e8/State_Design_Pattern_UML_Class_Diagram.svg

***

做完這個實驗,Teddy才發現一個問題。GoF的《Design Patterns》這本書Teddy也買了超過15年,看了不下N次。這本書寫的真的很棒,但是說真的不是很容易讀懂(有些鄉民讀起來覺得在看天書)。之前Teddy的第一個反應是:「啊,這本書中的C++例子舉的不是很好,所以不容易理解」。但是,就算是讀了其他書籍,像是《大話設計模式》,書中有比較淺顯易懂的C#程式例子,再回頭讀《Design Patterns》,還是會覺得有許多「理解漏洞」無法填補起來。所以,

例子是一個因素,但要深入理解《Design Patterns》,例子非常重要,但並不是決定性的因素。

那到底是什麼問題?從今天的討論中,鄉民們應該可以發現,《Design Patterns》這本書在寫作上其實存在著一些問題。例如,章節定義不清。在昨天的實驗中,Observer pattern的Motivation雖然也有夾雜著example與若干對於solution的說明,但Teddy還是在其中找到了兩個force。在今天的實驗中,Teddy發現State pattern的Motivation只包含了solution的example,並沒有找到任何的force。有一個force跑到了Applicability(Context)章節裡面,經由Teddy把它給拯救出來之後得以和世人見面 XD。另外兩個force是Teddy觀察State pattern的solution與resulting context所歸納出來的。

***

今天又是扯了一大篇。鄉民們可能會想:So what?沒有force又怎麼樣?force跑到Context裡面又怎麼樣?Teddy再幫鄉民們複習一下force的涵義:

  • Force是問題的限制或特性。
  • Force告訴我們為什麼模式所要解決的「問題」是一個真正的問題;為什麼這個問題很難,為什麼這個問題需要一個聰明的,甚至是違反直覺的解決方案。Force也是了解為何會採用此種解決方案(而非其他方案)的關鍵。
  • The often contradictory considerations to be considered when choosing a solution to a problem. Each solution considers certain forces. It optimizes some and may totally ignore others. The relative importance of the forces is determined by the context.

在Teddy的經驗中,很多學習design patterns的程式設計師,在應用design pattern的時候,經常會發生「套錯pattern」的問題。當然這個問題的原因很多,Teddy認為最重要的原因,就是:

  • 沒有弄懂每一個pattern要解決的problem與問題發生的context是什麼。
  • 沒有思考到自己的問題領域中,存在著那些force;在套用某個pattern之後,這些force是否被解決或是平衡了。

這句話再重複一次:

Force告訴我們為什麼模式所要解決的「問題」是一個真正的問題;為什麼這個問題很難,為什麼這個問題需要一個聰明的,甚至是違反直覺的解決方案。Force也是了解為何會採用此種解決方案(而非其他方案)的關鍵

沒有認清force,就很難判斷自己所設計或是挑選的solution是否合適。

***

友藏內心獨白:《設計模式的逆襲》這本書的種子快要發芽了 XD。

2012年10月2日 星期二

設計模式的逆襲:種子篇

Oct. 01 15:48~17:20

image

 

今年八月底Teddy開了為期三天的「Design Patterns這樣學就會了:入門實作班」。課程的講義內容與範例是Teddy自己準備的,但是這個課程有贈送每位學員一本《大話設計模式》讓學員們在課程結束之後可以回家 窒息 自習。其實Teddy的內心裡,是希望學員們能夠讀GoF的《Design Patterns》這本書,但是基於以下幾個理由改送《大話設計模式》。。

  • GoF這本書,不管是英文版,或是翻譯的中文版,其實都不是很容易理解(有看沒有懂)。
  • 《大話設計模式》這本書前一陣子Teddy有快速讀過一遍,裡面的例子相較之下很容易理解,算是一本寫的還不錯的書。
  • 《Design Patterns》英文版比《大話設計模式》貴很多 XD。

由於《大話設計模式》繁體中文版是由「悅知」出版,Teddy的《笑談軟體工程:敏捷開發法的逆襲》也是由「悅知」出版,因此Teddy就請認識的出版社編輯小姐幫忙訂購書籍。結果編輯小姐就建議「Teddy自己寫一本,自己賺版稅 XD」。當時Teddy看了編輯小姐的建議心裡就在想:「嘿嘿,想害我。寫一本書版稅真的賺不到多少錢,但花費的時間卻非常的多,完全不成比例」。

後來因為Teddy又開了「模式入門第一堂課:30 分鐘寫出一個模式」,投資了更多的時間在pattern上面,慢慢發現市面上的書籍存在著一些問題。

  • 太難理解:如果要深入學好Design Patterns,首選的書籍當然是GoF的《Design Patterns》。但是現代人通常沒什麼時間也沒什麼耐性(這是一個很強的force啊),要慢慢地把GoF的《Design Patterns》看懂並吸收裡面的日月精華,是一件費時又費力的事情。有誰願意至少花個3-5年來「精通」《Design Patterns》?
  • 太過範例導向《大話設計模式》、《設計模式之禪》、《王者歸來:品味Java的21種設計模式》(剛好這三本都是大陸同胞所寫的書 XD)這三本常見的中文書,都是以「範例」為出發點,用簡單易懂的範例來說明每一個pattern。這種以範例解釋設計模式的方法,算是對每個設計模式提供一種操作型定義」,這其實是一種很不錯的教學切入點。但是讀完之後又覺得有些在GoF的《Design Patterns》針對每個模式所想要表達的「抽象定義」觀點好像不見了。
  • 長得太像:最後一點不知道算不算是一個問題,就是上面提到的這三本中文書,怎麼內容與結構都如此的「雷同」啊!除了用範例導向的方式來解釋個別的pattern以外,都剛剛好「順便」介紹了Open-Closed Principle、Single Responsibility Principle等幾個物件導向設計原則。難道這就是傳說中的「山寨 英雄所見略同」?

***

少了什麼?

如果Teddy真的去寫了一本有關設計模式的書,而這本書的內容表現方式只是台灣搞笑版的《大話設計模式》,或《設計模式之禪》,或《王者歸來:品味Java的21種設計模式》,那就不值得一寫。畢竟寫一本中文的專業電腦書,「經濟上」的代價實在是太少,必須要有「其他的意義」,才值得一寫。

這個「其他的意義」是什麼,Teddy一直遍尋不著,所以也就沒有寫書的念頭。一直到這幾個禮拜,Teddy在思考force的問題,似乎慢慢發現「其他的意義」:

從Pattern的原點思考,回到pattern的六個基本格式,發現從GoF的《Design Patterns》的撰寫格式,其實Teddy沒有辦法立即很清楚的回答幾個簡單的問題。例如,每一個pattern要解決的問題是什麼?這些問題中存在那些force?鄉民們如果願意花點時間去讀一下GoF的《Design Patterns》,會發現其實GoF的書中,很多篇幅都在談solution。包含Intent與Motivation,仔細閱讀很容易發現solution的影子,但是卻不容易找出problem是什麼。Problem經常是需要讀了一大段文字之後,讀者必須要自己去推敲。無法用一或兩句話寫出problem是什麼,這其實是一個很嚴重的問題,代表說讀者腦袋中無法用簡單且抽象的概念,來記憶、說明、比較這每一個pattern要解決的問題是什麼。做軟體的人應該都知道,要先了解問題,再探討解法才有意義。所以,無法直接指出每一個pattern的problem,這就是一個很嚴重的problem XD。

***

從Teddy上面所講的這一堆有個沒的事情,對於「如何寫出一本好的設計模式書籍」這個問題,可以找到幾個force:

  • 原本GoF的《Design Patterns》書中所要表達的「抽象定義」觀點,不能因為採用「操作型定義」的寫作方式而消失。
  • 只強調「抽象定義」而沒有容易理解的範例,讀者透過實作來理解pattern的過程將會遇到困難。
  • 每一個pattern的問題如果無法被清楚的被描述,讀者將不容易比較相似pattern之間的差異,也容易發生誤用的情況。

要解決上面這幾個force,Teddy提出的solution是:

  1. 以容易理解的範例說明pattern六個基本元素(Name、Context、Problem、Force、Solution、Resulting Context)的概念,
  2. 將GoF的《Design Patterns》重新整理之後,用新的格式來表達,
  3. 提供完整且容易瞭解的範例程式,使得讀者有能力夠過實作來加強理解每一個pattern。

第1點和第3點Teddy都有初步的資料,所以接下來的工作就是把每一個pattern重新整理,用新的格式來表達,這樣就新書的雛型就出來了。講是這樣講,23個pattern要一個、一個整理,也是頗花時間與心力的工作。但無論如何,這樣的一本Design Patterns新書,才不會流於「又是另外一本設計模式的書」,花時間去寫也才有意義(希望有朝一日完成後可以反攻大陸 XD)。

***

友藏內心獨白:Force好像少寫了「搞笑」這一點啊 ?!

2016年5月20日 星期五

兩棲動物

May 18 10:10~11:15

螢幕截圖 2016-05-18 14.00.56

▲畫面節錄自Google搜尋結果


兩棲動物,就是那種可以在水中也可以在陸地生存的動物。往好的方面看,水陸兩棲,具備兩種能力,勝過哪些只能待在水中或陸地的生物。往壞的方面看,在水中遊不過水生動物,在陸上跑不過陸生動物,只能算是個半吊子。

Teddy有時候覺得自己也很像兩棲動物,博士畢業也在研究所兼課但卻沒有從事學術研究。在業界服務但目前從事的卻是敏捷開發培訓與顧問工作,沒有上課或是顧問工作的時候,每天宅在家裡寫作、讀書,發呆,玩貓 思考,和身陷於專案泥沼中的上班族又有點區別。往壞的方面想,學術比不上真正做研究的專任教授,實務比不上每日打仗的工程師。

***

但是,做人總是要樂觀進取,不能只看壞的一面。所以在學校教書的時候,和學生少談點理論,多帶點業界的「專業態度」要求。Teddy常告訴修課學生:「如果你可以受得了我的碎碎念,畢業後大概沒有什麼老闆(主管)的要求可以難得倒你。」當然Teddy指的是老闆(主管)在專業態度上對你的要求,如果是因為公司政治因素或是個人心理 變態 狀態與修養不足所導致一些狗屁倒灶的奇怪要求,那就不屬於專業態度的範圍,只能靠哲學佛法來化解。

同樣,在業界從事培訓工作,Teddy也不會只是教教「工具使用」或是「套套招式」,也不會只是空談「心法」。從學術研究的角度來分析,每一門課程Teddy先問自己:「這個課程最核心、最困難的問題是什麼?」先確立這些困難的問題是什麼,然後找到用日常生活中相對的例子來解釋給學員知道,這才是課程的精華。例如,在教「Design Patterns這樣學就會了–入門實作班」,最重要的重點不是GoF書中的那些pattern,它們只是第二重要的概念。比GoF那23個design patterns還重要的事情要先從最基本的「課程名稱」開始談起。既然課名叫做design pattern,那麼請問:

  • 什麼是設計(design)?
  • 什麼是好設計(good design)?
  • 軟體設計的產出物是什麼?
  • 什麼是模式(pattern)?為了回答這個問題衍生出pattern的六大元素:
    • name
    • context
    • problem
    • forces
    • solution
    • resulting context
  • 套用模式來解決設計問題的流程是什麼?
  • 怎麼知道是否套對模式?是否過度設計(over design)或設計不足(under design)?

以上這些問題都和GoF Design Patterns這本書沒有直接關係,但卻是學習GoF Design Patterns,乃至於所有種類patttern的基本知識對於某些「業界人士」而言,可能覺得這些都是「理論」,沒有實際幫助。但實際上,這些被視為「理論」的東西,才是最「實務」的基礎。

***

兩棲動物,只要在適當的環境發揮所長,也是可以活得很好。

***

友藏內心獨白:乖乖當靈長類不行嗎。

2012年8月27日 星期一

Design Patterns這樣學就會了:入門實作班,Day 1

August 26 22:35~August 27 00:14

螢幕快照 2012-08-27 上午12.25.01

 

8月25日星期六是「Design Patterns這樣學就會了:入門實作班」第一天上課,此次報名的學員比Teddy原先預期的要多,有兩位還遠從高雄北上來上課,這也是出乎Teddy原本的預料之外(因為Scrum的課程都沒有南部來的朋友啊…挑眉質疑)。

學pattern方法十幾年,Teddy覺得光是講GoF書中的pattern,雖然對學習軟體設計非常有幫助,但如果僅止於知道GoF書中的pattern,並不足以發揮Alexander原本「pattern」和「pattern language」的威力,所以Teddy特別在這次的課程中,花了四個小時的時間,從「什麼是軟體設計的產出物」這個問題開始談起,然後以一個一般鄉民都看得懂的例子,一步、一步帶領學員,透過說明下面這個觀念,進入pattern的世界。

螢幕快照 2012-08-26 下午10.39.02

 

這個pattern的例子一開始長成這樣。

螢幕快照 2012-08-26 下午10.58.45

 

改到第5.1版之後,變成這樣(還沒改完喔)。

螢幕快照 2012-08-26 下午10.55.03

 

把例子講完之後,再仔細說明與分析pattern六大元素之間的奧妙關係,學員們在30分鐘之內就有能力寫出一個pattern出來。

螢幕快照 2012-08-26 下午11.05.14

 

寫得好認真啊 很棒

螢幕快照 2012-08-26 下午11.07.32

 

接著Teddy解釋一個很重要的觀念,為什麼要學pattern(這裡所說的pattern,不是GoF的Design Patterns,而是Alexander在The Timeless Way of Building一書中所談的pattern喔)?。Pattern是一種思考與解決複雜問題的方法,可以幫助鄉民們從「加班到死的programmer」,慢慢轉變成「programmer」、「designer」、「architect」的一個過程。這種pattern方法的核心精神,可以應用在各種不同的領域之中。

螢幕快照 2012-08-26 下午11.09.39

 

以上內容就算是不會寫程式的人來聽,都可以理解並且實際應用pattern來作為一種思考與設計的工具。所以之後Teddy會將這部分的內容獨立出來,單獨開一門介紹如何使用Pattern來作為思考與設計工具的課程。

***

接下來的內容慢慢轉移到軟體身上,先講物件導向設計觀念。

物件導向的觀念Teddy講了可能快有20年的時間了(比學pattern的歷史還要長久啊)。光看這兩張投影片可能會覺得沒什麼,現場聽完之後,保證會讓很多人懷疑:「我以前學過的東西,真的是物件導向的觀念嗎?」

螢幕快照 2012-08-26 下午11.24.58

螢幕快照 2012-08-26 下午11.24.29

接下來就進入GoF的design pattern範圍,第一天介紹的是Singleton與Observer,當場要把程式給寫出來。

(迷之音:JUnit的jar檔放在哪裡…Orz)

螢幕快照 2012-08-26 下午11.31.35

***

第一天課程結束之後,Teddy覺得教這個Design Pattern的課比上Scrum還要累大概5倍以上啊(所以日後學費也要乘以5)。已經有好一陣子沒有體會到武俠小說「射鵰英雄傳」中,「一燈大師」幫「黃蓉」治療內傷之後,那種虛脫的感覺了…Orz。不過說真的,Scrum的確比pattern要容易了解太多了(雖然要把兩者都學好,個別來講都是很高難度的一件事)。

來上這門課的學員,有好幾位在工作上是用C在寫程式,對於物件導向的觀念並不是很熟。也有工作上使用C++、Python和Delphi的學員,但是基本上在課堂上並沒有遇到什麼嚴重的困難,這也是讓Teddy感到很高興的一點(因為之前Teddy有「放話」,只要曾經會寫程式,對於pattern有興趣的人,都可以來上這門課,沒有限定要對Java或是物件導向很熟悉才可以學)。

***

友藏內心獨白:還是要花時間寫一本《設計模式的逆襲》,讓沒錢上課的學員可以自己買書回家看?!