剛開始程式設計的時候是在高中,那個時候計算機課上老師教的是pascal。一種典型的面相過程的語言。那個時候懵懵懂懂的認為:程式還是一個蠻神奇的東西,敲幾個英文字元進去,就能夠有反饋。即使這個反饋只是非常簡單的輸出了一個“Hello World!”。
而大學開始比較系統的學習計算機這個東西。但是現在回想起來,貌似沒有系統的學過程式設計這個東西啊。即使上了很多叫做《XXX程式設計》的課程之後,對於程式設計這個東西還是有種霧裡看花的感覺。而且學的都是像彙編了,C了這樣的一些比較底層的語言。主要是語法吧,設計層面的東西真的很少。造成很長一段時間內,我對程式設計的認知停留在高中pascal的水平,程式設計就是你輸入個東西,然後設計一系列序列的邏輯,然後等著輸出。
後來上了一個叫做《C++物件導向設計》的課,在上課之前以為這是一個高大上的課程,結果到最後老師把c++講成了一個好用的c,比c優秀的地方主要就是在加了一些支援物件導向的語法。現在回想一下,那些叫做《XXX程式設計》的課程,基本上都是一些語言課程,貌似和程式“設計”這個東西有點不著邊際。而也未能讓我,對於“物件導向”或者“面相過程”構建起基本的概念。
寫程式的時候,更多還是停留在pascal那個層次中。序列的邏輯。那個時候的夢想就是能夠讀完knuth四卷本的《The Art of program》還有他為這本書寫的輔導書《基本數學》。因為大家在程式=資料結構+演算法的世界觀中,這幾本書如同聖經。最後花了大概四五年吧,只讀了第一卷的300多頁。好吧,貌似我不是一個很虔誠的信徒。
有幸的是,大二開始跟著一個老師給他們當碼農,敲程式碼。就這樣稀裡糊塗,斷斷續續的以一個碼農的角色在他們的專案中敲敲打打。那時作為一個新手,得到最多的就是“埋汰”。他們看著你寫的c或者c++程式碼,說這個太不優雅了。當時,我就想:靠,就是一串程式碼,又不是什麼畫,還能用優雅來形容啊。之後,他們開始說一些設計模式了之類如同天書的東西。大三下班學期的時候,有個哥們在搞magic linux的安裝程式的重構。我就聽著他天天在和我白活寫第一版安裝程式的是如何如何牛逼哄哄的。模組劃分的多麼多麼清晰,模組間通訊竟然都是用的xml。設計的可擴充套件性多麼多麼好,模組間高耦合地內聚了。。。。當時就覺得,靠,真的很牛逼啊。用現在的一個詞就是:不覺明歷。不過當然,得向牛逼的人學習。於是買了本c++版的《設計模式》,就是最經典的那本。記得那個時候,讀起來,略覺生澀。很多概念都是囫圇吞棗的嚥下去了。在以後的程式設計中,也能偶爾用用什麼觀察者了,單例了之類的模式。偶爾,能夠針對一些問題提出一些看似非常符合設計模式的“設計”。
在接觸到設計模式並能夠稍微懂點的時間內,以為物件導向這個東西的主要內容就是“設計模式”了吧。你看用了設計模式之後,腿也不酸了,要也不疼了,一口氣能上十層樓了。寫程式碼也開始有點那種玄乎的“優雅”的感覺了。切以為自己在碼農這個職業上已經算是入門了。直到有一天看了一本叫做《敏捷開發》的書,才猛然間驚醒。他媽的,在設計模式之上還有六大原則:單一職責、里氏替換、開閉原則、迪米特法則、介面隔離原則、依賴倒置原則。原來設計模式被設計出來的時候也是按照一定的指導原則的,那就是六大原則。好吧,現在我的物件導向程式設計的思想庫中又多了一批非常不錯的概念:六大原則。而且驚喜的發現,隨著對這六個原則尤其是單一職責原則的深入理解。自己開始,能夠慢慢跳出原先那種刻意去使用設計模式的牢籠。開始去關注程式設計本身,或者說具體情況相關的東西。而不是為了設計去設計。這個時候,才開始慢慢的體會到其實程式設計這個東西真的並不是簡單的邏輯羅列,而是思想的結晶。是必須經過深思熟慮之後,才能完成的事情。不再一聽到別人高談闊論高內聚低耦合,就不覺明歷,開始嘗試著去思考他們所謂的高內聚低耦合到底是個什麼東西,用這個標準來評判一個面相物件的設計是否合適。這個面相過程的遺留品在物件導向的設計範疇內到底能夠發揮多大的作用。漸漸的發現,其實高內聚低耦合和單一職責與迪米特法則是那麼的貌離神合。講的都是我們一段程式碼的職責一定要純粹,而且越純粹越好。不要染指其他程式碼的職責。登陸的程式碼就負責登陸,不需要管介面上的事情。介面上的程式碼就負責展示內容就好,不要負責業務邏輯。當能夠清晰的指出系統中每個模組,每個類,甚至是每個函式那“單純”的職責的時候,那麼整個系統應該說是優雅的了吧。
而這個時候,進行分析與設計的時候總是有種捉襟見肘的感覺,一個類的設計,甚至一個方法的定義與實現沒有什麼規矩可言。有些時候從上面說的六大原則和設計模式入手,大概構想出了軟體的模樣。但是到了一些編碼細節上的時候,總是有種力不從心的感覺。簡而言之,就是看手氣寫程式碼。最終是否能夠真實的還原自己的設計,完全是個靠經驗吃飯的事情。而比較悲劇的是,作為一個程式設計經驗沒有十年二十年的人來說,這似乎有點不太靠譜。作為一個數學系的學生,那種定理情節油然而生。難道就沒有類似與定理一樣的東西能夠幫助我有效的還原設計,定義一個類,定義一個方法。於是又開始了狂看書的路程。
c++之父Bjarne Stroustrup的《The Design and Evolution Of C++》中一句話給了我方向:c++語言在眾多語言的角逐中能夠勝出,本質上是一種哲學思想的勝利。乍一看可能認為是物件導向在實踐中戰勝了面相過程開始主導軟體開發語言。但是,當去仔細品味的時候,發現這種哲學思想是一種實用主義的思想。他以目標為導向,以最終效果為評判標準。中間所做的一切努力,都是為了達到最後的目標。就像物件導向誕生的時候,正是軟體規模不斷擴大,軟體複雜性已經超出了人類可控制的範圍。人們急需要一種能夠合理的控制整個軟體複雜性的方法,於是就有了物件導向。而複雜性控制這個概念是來自於軟體工程的東西。頓時你就覺得腦海中的很多概念開始高度重合面相物件、軟體工程、複雜性控制、面相過程。。。。。。。定理沒找到,反倒是燉了一鍋佛跳牆。七葷八素裡面什麼都有。
偶然的機會在WIKI上看到了一個詞——工具理性。才有點開始懵懵懂懂的覺得看到了一點曙光。原來一個Code Monkey廢了半天勁塞進腦瓜裡的所有東西,都是工具而已。程式語言是工具;物件導向設計是工具;敏捷工程是工具。。。。我們只是合適的使用這些工具來完成目標而已。恍然大悟,其實根本就沒必要糾結於在編碼的時候用的是物件導向還是什麼,沒有必要糾結用沒用設計模式,沒有必要糾結開發過程到底敏捷不敏捷。。。只要能夠實現最終的目標就好了。只是實現目標的這個過程還是依舊曲折。如何選擇工具,並且如何有效的使用工具依舊是一個很重要的問題。但是已經有了一個大概的能夠指引以後學習方向的思想——瞭解目標、瞭解工具,懂得如何合理而且有效的使用工具,並且Keep it simple。發現在程式設計這個事情上,真正難的不是你寫出了些什麼東西,而是你沒有寫什麼東西。難的不是你進行復雜的設計與編碼,而是儘可能少的設計和儘可能少的編碼。這有點像國畫中的留白,那些真正簡單的東西才是最複雜的東西。能夠把設計最到最簡才是真正的功力。一個Redis才幾千行程式碼,sqlite也不過3w行左右的程式碼。這兩個東西做的事情不可為不復雜,但是設計的人之功力可見一斑。
最後用一幅畫與大家共勉: