如今所有的Opening,只要有點底氣,都會要求candidate有OOD的能力、熟練運用各種設計模式。然而在筆試及面試中,卻只能通過形如,“列舉GoF書中你知道的設計模式”,“畫出strategy模式的UML圖”之類的問題來進行測試,在如今實習生都把GoF書翻爛的年代,這樣的問題如同,“請說出final, finally, finalize的區別”一樣,只能浪費雙方的時間。綜觀面試經驗,對于“闡述一下你對OOD的看法”的回答,無非兩類:“封裝、多態、繼承”或者“GoF的模式”,這樣的回答恰恰代表了候選人對OOD理解的層次。
在OOD這個domain里面,類比數學公理,我認為Robert.C.Martin的
OOD Principles已經說的非常清楚,當中最為核心的一條,就是SRP。所有其他的編程原則如同在五大Principles中的OCP、DIP更多的是基于SRP的一些推論,更不必說
DRY原則等等一系列五花八門,變化多端的buzz word。我認為所有的程序設計工作,其實最終的目標都是為了達到隔離關注,將特定的需求交給專門的組件去完成。這里的組件在不同的上下文中含義不同,小至在單個系統模塊內部,組件指的可能就是完成特定功能的Class/Function,大至SOA(另外一個buzz word)中,組件指的可能就是某個業務域服務系統。當明確了SRP是終極目標之后,OCP說的,只不過是“部分特定條件下的情況已經被本組件解決完畢并隔離,如需要處理其他特殊邏輯,請通過擴展的方式在特定的地方完成”;DIP則說“本實現所依賴的組件的具體實現選擇過程應該由專門的選擇策略組件完成,本類的主要關注是利用這些依賴完成本類所標稱需要解決的問題”;至于那個DRY原則,則更顯淺易懂了,本來就已經有特定的組件把特定的關注解決掉了,還有必要重新解決一次么?
那么所謂的封裝、多態、繼承,甚至是GoF的各種模式,到底是什么呢?同樣的,類比數學中的概念,它們就是一些基于數學公理的推論,雖然我們可以通過公理一步一步的將所有的定理推論都推理出來,但極少數人會在實際運用計算的時候這么做,因為太慢了。同樣的,這些類似Best practice的東西的價值也僅僅在于,解決某一特定前提下的某一特定問題,這樣,你就明白為什么我深惡痛絕
模式驅動編程:模式是為了解決特定問題而產生的,但這幫人的做法是為了運用某種模式,而去創造該模式所符合的問題,這讓我想起那個關于數學家的
笑話。然而我經歷的團隊中,這樣的情況屢屢發生,成為
過度工程的頭號原因。
之前經常有人問,如何鍛煉設計能力?我就會建議他們看一下那幾個principles,每天讀,讀通讀透,讓它們成為你的條件反射。在做設計和review設計的時候,不停的問自己,我一共有多少個問題?正在考慮的這個組件要解決什么問題?在它所處的粒度來看,它是否只有單一職責?等到每個問題的答案都是Yes的時候,我認為這個設計至少不差。我之前看到過很多這樣的設計,大多數情況下,它們不會有一些fancy的設計模式名稱在里頭,但卻滲透著一股身經百戰的老練,比如
JQuery的core。
同樣的,有一種顯而易見的bad smell:當你的代碼庫中充斥著大量的設計模式名稱,而實現代碼卻看起來極其幼稚(我認為至少得讀過
Implementation Patterns或者
Clean code),那么百分百的,你的團隊中就至少有著一個急于想證明自己卻又適得其反的成員,該是時候找他談談他的定位和成長計劃了。