Mar. 28 21:40~22:01
離開故宮之後來到馬路對面的景山公園,這裡是明朝崇禎皇帝上吊的地方。
景山公園面積23公頃,包含平面的公園,以及景山。景山上有五個亭子,亭內供奉佛像。其中四個亭子的佛像在八國聯軍的時候被洗劫一空。
山頂的萬春亭,從這裡可遠眺紫禁城、國家歌劇院、北海。
***
在萬春亭休息了一會,下山繼續逛景山公園。在這裡待到下午四點左右,逛了一天也累了,準備打道回府。
***
友藏內心獨白:原來崇禎皇帝上吊的地方是在山下。
Mar. 28 21:40~22:01
離開故宮之後來到馬路對面的景山公園,這裡是明朝崇禎皇帝上吊的地方。
景山公園面積23公頃,包含平面的公園,以及景山。景山上有五個亭子,亭內供奉佛像。其中四個亭子的佛像在八國聯軍的時候被洗劫一空。
山頂的萬春亭,從這裡可遠眺紫禁城、國家歌劇院、北海。
***
在萬春亭休息了一會,下山繼續逛景山公園。在這裡待到下午四點左右,逛了一天也累了,準備打道回府。
***
友藏內心獨白:原來崇禎皇帝上吊的地方是在山下。
Mar. 24 19:31~21:20
Switch Statements(Switch敘述)
鄉民們可能聽過類似的說法:「好的物件導向程式應該少用switch statements」,根據《Refactoring》書上的講法,switch statements會造成重複(duplication),因為很容易在程式中發現同樣的switch statements散布在不同的地方。但Teddy覺得對物件導向的程式來講,duplication應該是switch statements造成的第二嚴重問題,首要的問題應該是違反了open-closed principle,也就是降低modifiability。無論是duplicated code也好,是違反open-closed principle也罷,這兩者都會降低modifiability。
Switch statements還有另外一個問題是當switch statements很長,尤其是每一個case子句當中還有複雜邏輯的程式,則會降低testability。
關於switch statements也可以參考c2網站上面的討論。
***
綜合以上的說明,switch statements之所以會是一個bad smell的原因(force)可歸類為:modifiability和testability這兩點。
移除switch statements壞味道的方法,在《Refactoring》書中提到可以套用Extract Method、Move Method、Replace Type Code with Subclasses、Replace Type Code with State/Strategy、Replace Conditional with Polymorphism、Replace parameter with Explicit Methods、Introduce Null Object。
***
Parallel Inheritance Hierarchies(平行繼承架構)
《Refactoring》書上說parallel inheritance hierarchies是shotgun surgery的特殊情況,因為兩個平行的繼承架構彼此相關,因此當在某個繼承架構中增加了一個subclass,也必須為另一個繼承架構新增一個相對應的subclass。學過GoF Design Patterns的人一看就知道Factory Method與Abstract Factory這兩個設計模式就是標準的parallel inheritance hierarchies。
但是話說回來,《Refactoring》書上對於這個壞味道的說明實在太少也太抽象,不太容易理解。後來參考了《Refactoring in Large Software Projects》和《Refactoring Workbook》這兩本書才比較清楚一些,請參考下圖:
看完這個圖之後雖然移除了parallel inheritance hierarchies,但是一旦右邊的類別多了一個subclass,左邊的類別還是會新增一個class,只不過這個class透過composition的方式去使用相對應的那個subclass。這樣做真的有比parallel inheritance hierarchies要來的好嗎?這個問題當成作業請鄉民們自行思考看看(PS:也可以參考stackoverflow的討論)。
***
既然parallel inheritance hierarchies是shotgun surgery的特殊情況,造成它之所以會是一個bad smell的原因(force)應該也和shotgun surgery一樣可歸類為:modifiability、testability、understandability這三點。
移除parallel inheritance hierarchies壞味道的方法,在《Refactoring》書中提到可以套用Move Method和Move Field。
***
友藏內心獨白:針對Factory Method和Abstract Factory應該沒轍吧。
Mar. 24 13:20~14:23
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放棄了物件導向技術「將行為與操作封裝再一起」帶來的好處,造成的影響就是:
以上總結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。
***
友藏內心獨白:差不多快頭暈了。
Apr. 01 13:45~15:03
畫面節錄自「活用希臘哲學」課程。
繼續昨天的話題,在「活用希臘哲學」課程中,苑舉正老師提到希臘哲學與東方(中國)哲學的三點差異之處:
依據苑老師的解釋,「言必及物」的意思是說這個世界是由人所說出來的,所有思想的內容都必須透過語言的方式來表達。當我們看到外在的環境,一定會在我們的思想中想到這個環境是什麼。我們說它是什麼,它就是什麼。無論這個世界究竟為何,我們必須要用語言來和其他人溝通這個思想,因此說話必須要「言必及物」。
東方的思想則是「多言無益」,這個世界本來是怎樣,就是怎樣,人所說的話並不會影響這個世界的本質,反而可能會擾亂我們的思考。我們對於外在世界的結構,透過觀察與思考之後便心知肚明,不必說出來,心中自有體會。
***
有了言必及物的觀念,人有思想,透過語言來描述世界結構,但這個透過語言所建構的世界結構是一個「抽象」的世界結構,是一個經過語言所簡化、抽象化的世界結構。抽象思考的好處是,人的思維可以不受外在環境所限制,思想所表達的內容也比較自由。另外,語言本身不但可以釐清我們的思想,還可以進一步帶動我們更深入的思維。
實用思維則是強調「體用合一(體驗和用處合而為一)」,從實做中學習,將個人的體悟視為最重要的理解程度,將實作、體悟、用處三者合一。實用思維的好處就是以實際成果作為成敗標準,人做一件事情一定有目的,是否能達到這個目的變成為判斷好壞的標準。
***
聽完苑老師的解釋,讓Teddy想起Alexander的《The Timeless Way of Building》這本書。有人說Alexander的思想受到中國道家思想的影響,Teddy曾經在〈C. C. Agile 聚會Sprint 18 精華報導〉中介紹過《The Timeless Way of Building》這本書的大綱,如下所示:
其中前兩點:「世界上存在某種永恆不變之道,此道只能透過流程(實踐)自行產生,不可強取。它具備某種無法命名的特質(Quality without a Name,QWAN),任何言語都無法精確地描述此特質」,Teddy覺得這種精神和東方哲學所提到的「多言無益」與「實用思維」是一致的。
但是Alexander接著又說,雖然QWAN無法用言語形容,但是為了溝通這個概念,還是需要有一種「機制」,而他所借用的機制,就是「語言(Pattern和Pattern Language)」。透用語言來建構世界,則是又回到希臘(西方)哲學的作法。
接著Alexander談到實踐與套用「語言(Pattern Language)」的重要性,把實踐當成一種修練與體會QWAN的手段。
但是,最後,光是學習、實踐、體會「語言(Pattern Language)」還不足以真正得道,必須要忘記「語言(Pattern Language)」,達到天人合一的境界,方可真正得道。
***
在聽了苑老師對於東西方哲學的差異說明之後,Teddy感覺Alexander的最終思想是比較接近於東方的「多言無益」,也就是世界的本質不會因為語言而改變,人有能力透過自我內心的反省、反思,來體驗、領悟QWAN。但是,因為工業化與專業分工的關係,在傳統社會中,人們可透過世代模仿與學習的這種能力已經消失了。為了讓人可以重獲這樣的能力,於是他借用西方哲學的「言必及物」與「抽象思考」,透過語言(Pattern Language)這種手段,讓人們可以重新具備體驗與領悟QWAN的能力。
***
友藏內心獨白:經典就是每次讀都會有不同的感受。
Apr. 01 10:24~11:10
畫面節錄自「活用希臘哲學」課程。
因為Erica的推薦在coursera上面選了一門「活用希臘哲學 (Understanding the Greek Philosophy)」的課程,授課講師是台大的苑舉正老師。Teddy以前也買過幾本有關哲學的書,但應該是道行還不夠,看了幾頁之後就看不下去,書也不知道被丟到哪裡去了。
這門課進行的方式幾乎都是畫面一直對著苑老師的上半身,由他一個人口若懸河的一直講、一直講,久久才出現一次投影片畫面,但過不到幾秒鐘投影片畫面隨即消失,又回到苑老師的畫面。不過這門課並不會無聊,只要專心上課,仔細體會苑老師所說的內容,其實還蠻有趣的。
苑老師提到,哲學思想的主軸包含三點:
看到第三點Teddy突然想到在讀Alexander的書的時候,也有提到類似的觀念。Alexander提到Quality without a Name(QWAN)這個概念,在此姑且把追求QWAN類比為追求真理。但是要採用「正面表列」的方式來描述怎麼才算是達到QWAN的境界很難(因為無法用言語形容,只能用心體會),就好像要描述何謂「真理」很難是一樣的道理,所以Alexander提到,可以用「負面表列」的方式,只要一個環境或建築物沒有存在未被解決的force(作用力),我們就認為這個環境達到了QWAN。這個觀念和苑老師提到「追求真理以排除錯誤為主」的作法是一致的。
***
舉個軟體開發的例子,你要怎麼「證明」或是「說明」你的軟體設計得很好?如果採用正面表列的方式,你可以說你的設計滿足SOLID Principle,但是難道滿足這五個設計原則就夠了嗎?有沒有第六、第七…更多的設計原則被你忽略了?
如果用負面表列,你可以說你的設計裡面目前沒有發現(明顯)的壞味道,所以你認為這樣的設計就是一個好設計。也許你的Simple Factory的實作方式用了一個switch敘述,違反了OCP(Open-Closed Principle),也因此疑似存在Switch Statements這個壞味道。但你可以辯護說,在目前的context(情境)之下,這個存在於Simple Factory的單一switch敘述是可接受的一種resulting context(結果)。
***
同樣的思考模式可以應用在體驗設計(experience design)上面。怎樣的設計才算是好的體驗?這個問題好像不容易正面回答,但反過來想,如果一個產品或是服務使用起來沒有不順、卡卡、不爽、不舒服、不高興的地方,那這樣的體驗就可以被視為是一種好的體驗。因此,最後剩下來的問題就是如何「從現況中排除錯誤」。套用Alexander的說法,就是如何平衡作用力。電影中達摩大師有一句台詞:「看那看不到的東西,聽那聽不到的聲音」,也是同樣的意思。
畫面節錄自電影「達摩祖師傳」。
***
友藏內心獨白:人是哲學的動物。
Mar. 21 09:20~09:45
看過重新整理第二次的Factory Method與Singleton之後,今天輪到Facade。先看一下第一版的內容:
Name:Facade (take 1)
Context:當一個系統越來越龐大的時候,如果沒有好好規劃系統結構,整個系統內部物件之間的關聯性很容易變得過於複雜,最後導致牽一髮而動全身;除了影響開發速度,也很容易導致不預期的程式錯誤。一種常見的結構化方式是將系統依據功能劃分為若干個子系統,子系統內部的物件允許較緊密的關聯,而子系統之間則應該要儘量降低其相依性。
Problem:如何使用子系統?
Force:
Solution:提供一個存取子系統內部各項服務的單一介面,讓子系統變得更容易使用,並且可隔離客戶端程式對子系統內部元件的相依性。
***
重新整理Facade的過程中,發現原本第一版的內容暫時想不到有什麼需要修改之處,所以就先維持原狀,但是多寫了一個生活版的Facade。
Name:Facade (生活版)
Context: 一個中大型公司有數千名員工,分別隸屬研發、財務、行銷、業務、行政、銷售等部門。
Problem: 如何讓各個部門落實高階管理階層的命令?
Force:
Solution: 設置部門副總,負責將高階主管的命令轉達給部門內部的人員執行,讓高層主管可以更方便的交代任務,並隔離他們對部門內部組織、人員與工作執行細節的相依性。
***
友藏內心獨白:突然想到看門狗。
Mar. 28 17:12~17:36
珍寶館為北京故宮的常年展示館,館中有各式寶石、金銀器皿、珍珠、翡翠、象牙、玉雕等珍寶。
整個珍寶館區域還蠻大的,一入內先看到九龍壁。
經過萬壽門,來到皇極殿。
發現一隻「故宮貓」。
經過養性門,來到養性殿。
來到暢音閣與閱是樓。
繼續走到樂壽堂、頤和軒。
傳說中的珍妃井。
***
參觀的差不多了,要從神武門離開故宮。
友藏內心獨白:宮中之宮。