山是不是山?

侯捷

2002/04/14


讀者 Edward 寫了兩封信給我。觸動了我寫此文的熱情。

●傳送日期: 2002年3月22日 PM 08:34
主旨: refactoring

老師:

在實驗室開發程式過程中,我有了 refactor 的經驗。我想稱之為 refine 也可。

帶領我們的學長,曾經待過一家公司,協助發展過兩套產品。他時常檢視我們所寫的碼,然後將邏輯重新整理一次,並且把主邏輯中太長的程式碼獨立成個別的函式,以便能專注於整個程式邏輯的思考。也就是說由 top-down 的角度來看程式。在我們的程式中,沒有複雜的 OO,最多只有依功能不同而切割開來的 class。更別提 polymorphism 和 generic 了 — 對我而言,這可能算是高階的東西了,與其說用不上,還不如說不知怎麼應用的自己的程式上。

我覺得寫程式,最終目的是在於解決問題。假設不涉及復用性,只針對特定問題來寫碼,而不是為提供一套 library 或 API,那麼 OO 和 generic 如何在程式中有所表現? 我這裡指的 OO 是指 patterns。

最近我開始對 Scott Meyers 的書感到困惑了。我覺得那些東西不是我們真正應該關心的。寫程式真正應該專注的是該用什麼樣的方式來解決問題,在撰寫的過程中
不斷地檢視程式邏輯。邏輯錯誤所付出的額外代價,遠遠大過於書中常常討論的少一次或多一次函式呼叫。(有一個印象很深的例子,在 Effective STL 中,討論的 map 的使用方式,就是在討論這樣的問題。還有關於 Object Counting 的那一篇文章也有這樣的討論。)

或許可以說這些是給高階程式員看的,但是在花了精力去編修程式以及抓臭蟲(邏輯上的)之後,還有多少時間去仔細思考那些所謂一次兩次所造成的額外負擔? 過於專注那些事情,我覺得是走火入魔,玩過頭了。

過於玩弄程式技巧,其實是沒有意義的。有一句話說的很對,要寫給電腦看的碼很容易,要寫給人看的很難。一個漂亮的碼應該是邏輯清楚,條理分明。而不應該使用太多語言本身所提供的特性。你並不知道接下來誰會接手你寫的程式,也不知道那個人對該語言特性的熟悉程度,能夠用最簡單的表達方式來撰寫,就用這樣的方式。

到底是該用漂亮的手法,還是容易讓人了解的手法來解決問題呢? 玩一些遊戲,除了騙騙人,說一聲中計了吧(Gotcha),這樣的把戲不應該在程式中出現。能夠避免讓人產生困惑就盡量避免。把那些遊戲當作是學習語言過程中的娛樂小點心,同樣的,過於專注那些事情,我覺得是走火入魔,玩過頭了。(看來我在挑戰 Herb Sutter?)

不可否認 Meyers 和 Sutter 應該都有豐富的程式開發經驗,但他們所寫下的東西,是他們在開發過程中最重要的心血結晶嗎? 程式員在開發過程中,那些真的是應該
要真正關心的事嗎?

每每看到老師的翻譯書單,就會把它變成我的書單,所以 Refactoring 我手上也有一本。 ;) 看了前面一小部份,我隱隱覺得這本書應該會有我想要的東西,對我平時的工作應該會帶來幫助。我相信這是一本從 real world 累積下來的心血結晶,而且會在實際開發程式過程中產生作用。前言所提和我目前的經驗類似,不斷的 refine 之後,便很容易加入擴充功能,程式碼也容易閱讀。我相信採用這種方式是正確的觀念。

我上面提的部分,很多是個人主觀因素,不過我想有些部分值得探討。


●傳送日期: 2002年3月25日 PM 01:13
主旨: 關於上一封信

老師:

感覺上前幾天寫給您的內容,關於 Meyers 和 Sutter 的書籍好像有點說過了頭。只能說我沒有到達他們的那個層次。或許這就是為什麼台灣軟體業起不來的原因(相較於硬體產業)。大家寫碼的時候都很輕率,以不擇手段的方式,完成所要的功能。事後也不太有很多機會進行修改,趕著出貨的時間表。

我最近有很深的憂患意識,關於海峽對岸。他們就像一二十年前的台灣,想拼想追上世界潮流。

這一陣子一些科技公司都到校園裡進行徵才活動,我參了與趨勢科技的說明會。通常這種徵才活動,都會派出人力資源(Human Resource, HR)部的主管來和學生做說明,國際性的公司就是不一樣,和其他的 HR所表現的風範就是不同。即使並無意願加入他們公司,但以聽一場 50 分鐘的說明會,收穫不算少。她提到了去年趨勢在南京要成立一個研發團隊,照慣例為想來應徵的人舉行考試,想不到來應考對岸的程式員都是考滿分,而台灣那時候只有一個清華博士班肄業國防役考了 98 分。這樣的現象就值得好好反省了。

還有一件與科技產業無關,但與生命財產有關。高中同學畢業去當兵,在軍隊裡見到的一些可笑的事情。他認為一旦戰爭爆發,很可能就是打爛仗。

我覺得這是整個台灣社會缺乏憂患意識,對很多事情漠視,毫不在乎。

哎哎,希望是我想太多了,情況應該沒那麼糟吧 :)

一口氣看完老師譯的 refactor chap1 實在過癮。最基本的 extract method 和 move method 就是平日我經常做的工作。query method 也偶而會出現。當然這些工作我們並沒有賦予它們像書籍內的這些名稱。

書本雖然可以教我們許多事,但過度依賴書本,就失去了獨立思考和創新的能力了。我就犯有這樣的一個毛病。最近有一個新的體認,只要本著把事情做到最好,各方面的能力便能有所提昇。寫程式如此,任何事也是如此。有一句話,忘了從哪裡出來的,意思是一些天賦本來就藏諸自我本身,只是沒有受到外在刺激,便沒有發揮出來。所以我要改變做事情的態度,時時問自己,怎樣做更好?

 

●傳送日期: 2002年4月4日 PM 03:08
主旨: problem solving

老師:

您在 TASS 書後有推薦一本書 Algorithms, Data Structures, and Problem Solving With C++。我到華通走了一趟,發現這本書在 2000 年有出第二版但是改名為Data Srtuctures and Problem Solving Using C++,前面的 algorithm 字樣拿掉了。內容的差異是,和大部分1997 年以前的 C++ 書籍再版後一樣,將書中範例碼都改為遵循標準。另外,也將大量 STL 的納入作為參考,但我想應該沒有 TASS 挖的深。大體上來說,就是依標準和 STL 來重修上一版的內容。

我想 TASS 的最大貢獻,如您所說就是為演算法和資料結構課程提供了一個很好的參照。

我有一個疑問是,以 STL 而言,其設計目標是為了復用性,提供給廣大的 C++ 程式員使用。但是,以發展程式而言,目的在於以簡單的方式來解決問題,並不是要設計一套 library 供人使用,如果沒有了復用性,那麼泛型的價值何在?

最近因為一些實務上的經驗,讓我產生不少困惑,到底哪些才是重要的,哪些是不重要的。在資訊爆發的時代,注意力到底該如何分配,我想是很重要的。最近有一本書,《注意力經濟》,天下文化出版,就是討論這樣的一個主題。

●侯捷回覆:

深刻的讀者來信,常會引發我寫文章的熱情。

簡單地說,Edward,學習有三個境界。

《五燈會元》第十七卷,唐朝日本禪師青原惟信:
「老憎三十年前參禪,見山是山,見水是水。及至後來親自知悉有個入處。見山
不是山,見水不是水。而今得個休歇處,依然見山是山,見水是水。」

你還年輕,寫的程式少,看的世面少,一再以「現在的我」質疑「過去的我」,也是正常現象。任何技術,任何學習,都需要兩面夾擊:to-down and bottom-up. 要有上層的抽象,也要有下層的紮實。類似 Scott Meyers 這樣的書,把各種基本馬步闡釋鑽研到幾乎「窮究」的地步,是很好的書。但不是要你一味全部運用。任何事情都需要取捨與平衡,需要取乎中道。這中道就有賴你個人在自己應用領域上的特殊性、你個人的大局觀、你個人的基礎技術素養來決定。

你說把主邏輯中太長的程式碼獨立成個別的函式...
噢,你說的是函式,那麼,這種動作在 procedural based programming時代大家就常常做,和OO沒有任何關係。至於 Object Oriented和Procedural based兩者的差異,應該不需要我再說了。

你說我覺得寫程式,最終目的是在於解決問題。假設不涉及復用性,只針對特定問題來寫碼,而不是為提供一套 library 或 API...
軟件的最終目的在於提供功能,這是對的,但這是不是最重要的一點,很難說,通常不是,至少不全是。

軟件要不要維護?不要,那就什麼都別考慮了,埋頭幹吧,把功能做出來,拍拍屁股走人,今生再也不必回頭看一眼。

軟件大不大?不大,那就別什麼OO、CMM了,埋頭幹吧。

軟件要不要團隊合作(team work)?不要,那就別什麼OO、CMM了,埋頭幹吧。

現今商業軟件要不要維護?大不大?要不要團隊合作?答案都是肯定的。你還認為「提供功能」是最重要的嗎?沒有好辦法(例如現今的OO),你連功能都做不出來(因為dead line到了,你那100萬行的、100人合作的貨交不出來)。就算你做出來,沒辦法維護,也是徒呼負負 — 你只能賣第一版,並且因為沒有新版、沒有修正,沒有服務,影響了商譽,進而影響了生意,最後關門大吉。

你提到復用性。並不是做出一個API或一套library,才是具有復用性。復用性可以就存在你自己的程式內,給你自己使用,讓你自己得利。你把自己的程式組織成復用性高的小組件(不論它是什麼型式),你的程式就愈有順利完成的可能,也愈好維護 --> 效能愈好 --> 競爭力愈高。

你說寫程式真正應該專注的是該用什麼樣的方式來解決問題...
那的確很重要,但程式如何組織一樣重要。

你說過於專注那些事情,我覺得是走火入魔,玩過頭了。
我同意你的看法。但是以你所舉的 Scott Meyers 書籍為例,作者扮演窮究的角色,讓你知道極限。他在做教育,而你在學習。他告訴你 100 分的東西,而你只需其中的80分,這樣很好,可你卻反過來認為那20分多餘。


時而我會憶起,你考上三校研究所,在台清交之間抉擇未定時,我給你的意見。當時我說如果你選擇清華,在大陸上...那些話你還記得嗎?我寫那些建議的當時,心想,你大概會覺得這離你太過遙遠。現在,這些考量離你一點都不遙遠了 :)

不在其位,不謀其政。大環境如何,不是現在的你能夠改變的,那麼就關心它但別管它。好好充實自己。也許有一天你發現你可以改變這個環境,再來操這份心。

我一直欣賞你的積極主動。好好做,好好學,你會很有前途。學生的日子不多了,好好把握完全學習的日子。把一天當兩天用,把一個人當兩個人用。你還年輕,狠狠地操練自己,為將來做準備。

 

 

 

程式並不一定都得自己寫出來,精讀這些東西,知道「實際上怎麼寫」,也就等於自己寫了這些東西(前提是「精讀而徹底理解」)。寫程式不需要比快(愛因斯坦恐怕也通不過高考),「架構漂亮」更重要。

有一種說法是「優越的程序員寫程式都很快」,「通過速度上的優勢,在與別人相同的時間內重構精練其程式,達到good甚至excellent的境界」。這種說法大約98%成立,另2%不適用於「通過另一種學習方式來鍛鍊自己」的程序員 ?/FONT> 這種程序員博覽群書,把精力花在思想架構上,以及對好作品的透徹理解上。他們不需要多寫程式,而把時間多花在思考與融會貫通上;真要實作程式,拿名家作品改一改,又快又漂亮。這種學習和鍛鍊方式,比較像「學者」。兩種學習和鍛鍊方式,沒有高下優劣,只要能成為一個優秀程序員(廣義的),哪一條路線都好。當然後者看起來可能更從容,理論基礎更雄厚些。過去那麼多年,大陸程序員接觸不到最好的書籍,無法走第二條路,現在情況已經改觀,非常可喜。

 



-- the end