程式者的胡言亂語

pageicon 星期四 十一月 20, 2008

用嘴巴寫程式

「用嘴巴寫程式」是程式員圈子裡時常被提起的一個詞語。人們提到這個詞語時,有時帶著一些貶意。當人們說某人「不過只是用嘴巴寫程式」,多半暗指這個人只會出一張嘴,盡講一些空泛、摸不著邊際的虛話,實際撰寫程式碼的工作,卻是無論如何也不願動手去做,好似光動動嘴巴,程式碼就能夠生出來一樣。而這樣的人,通常就是位居管理階層的人。而「用嘴巴寫程式」,在大多數時候,就成了程式員諷刺管理者的一種用語了。

的確「用嘴巴寫程式」似乎是許多帶領程式員進行開發的管理者的一種共通的現象。也是程式員對管理者時常發出的怨言之一。對程式員們來說,他們的主管只知道出一張嘴,交待他們要完成某某功能,或是修正某某問題,甚至還押上很緊的期限,完全一付不食人間煙火的樣子,好像以為只需要下令,程式員就能沒日沒夜的加班,在期限內把程式完成。動嘴下命令容易,但底下的程式員搞不好得花上許多的時間才能達成。這階級待遇差別是如此的明顯,使得有些程式員心中最大的願望,莫過於早日「晉昇」到「用嘴巴寫程式」的角色,這麼一來,工作就輕鬆多了,只需要動動嘴巴交辦事情,底下的苦命工程師自然得乖乖的把程式寫好。面對不合理的制度,不是打敗它就是加入它。不滿的程式員們選擇加入「用嘴巴寫程式」的行列之中。

這便是許多人心目中對「用嘴巴寫程式」的看法,但卻是一個相當負面的看法。我則對「用嘴巴寫程式」有另一種不同的正面觀點。

我認為「用嘴巴寫程式」不是許多人想像中那樣輕鬆的工作,事實上,要做好這樣的工作,需要的條件資格更為嚴苛。許多程式員未曾感受到有一位「很會用嘴巴寫程式」的主管帶領是一件美好的事,也有許多程式員主管完全沒有發揮「用嘴巴寫程式」這個角色應有的價值。

之前曾經提過,做為一名技術型的管理者,有一個關鍵的心理障礙,便是不知道如何將工作分派出去,以致於時常把太多的開發工作攬在自己身上。所以,想要勝任他的工作以稱職的演出應有的角色,他必須讓自己不要涉入專案的具體開發工作過深。

但是,做為技術型的管理者,其實還有另一個關鍵的障礙就是讓自己跟專案的具體開發工作完全脫勾了。這一類的管理者,完全只以WBS以及專案時程表為核心,他只關心每一項工作交給了誰去做,何時應完成,或者已經延遲了多久,預計還要再延遲多久。而這樣的管理者,就是前段文中所提到的那一類「用嘴巴寫程式」的管理者,他們只負責分配工作、設定時程,時間到了,再來審查程式員是否已經如期的完成,倘若沒有完成,看是要調派其他的人力協助、或者多施加點壓力還是採取其他的途徑,以便讓工作盡早完成。在這樣的工作模式下,管理者和程式員好像分屬在兩個不同的世界,除了專案的進度審查會議外,二者好像沒有太多的關連。

這樣的模式,卻也沒有把握到「用嘴巴寫程式」的精神所在。根本原因在於只用嘴巴下指令,卻沒有用嘴巴提供程式員必要的協助。

在許多時候,程式員之所以需要花費許多時間來完成他的工作或者甚至無法完成,是因為他對他的工作缺乏方向感。程式員或許不知道他的工作應當用什麼具體的技術完成、不知道要完成他的工作,應該依序的採取那些步驟來完成。程式員或許會遭遇到一個對他來說根本完全無法理解的問題,即使耗費大量的時間仍舊無法解決,使得進度始終原地踏地。這都是因為缺乏一個知道如何「用嘴巴寫程式」的管理者,來為他們指引方向。

一個懂得如何「用嘴巴寫程式」的管理者,會知道如何將整個專案內的工作,劃分成為若干個具體可執行並且前後連貫的工作項目。同時,他也會知道如何挑選正確的人選來執行相對應的工作。更重要的是,他會知道被挑選執行某一特定工作的程式員,倘若要完成該工作還缺少些什麼,進而在程式員執行工作的過程中,持續的提供必要的協助。

程式員可能缺乏某些技術背景,管理者最好自己就懂得完成該工作所需的技術,並且在程式員開始執行工作之前,已經完成好必要的教育訓練。假若一個工作需要AJAX技術,你總不能讓一個完全不會AJAX的程式員自行想辦法搞定吧?倘若管理者自己也不熟悉該技術背景,那麼最好也要能建議並提供必要的資源,例如書籍或參考資料,以免讓程式員有如身處茫茫大海中不知所措。但這卻是許多管理者最常發生的情況。

事實上,管理者最好還是自己也懂得該技術,否則這項工作的風險就很高,因為這意謂著當執行這項工作的程式員遇到難解的問題時,管理者不知道如何提供解決問題的方向。事實上,這是技術型管理者的一個重要的價值所在
對於技術的熟悉以及長久累積下來的經驗,管理者早就經歷過各式各樣的問題,這使得他可以「用嘴巴寫程式」寫的很好。當程式員遇上某個問題時,或許花上許久的時間,仍不得解題之門而入。但有經驗的管理者,或許一眼便能看穿問題所在,直指問題核心。他或許只需要程式員提供一個錯誤訊息、錯誤代碼、或問題的現象,便可以從過去的經驗中直接建議可能的發生原因。這能省去程式員大量的時間。

是的,指引程式員工作的方向便是「用嘴巴寫程式」最重要的價值。當你在交付一項工作時,應該要讓負責這項工作的程式員,知道完成這項工作的大略步驟。許多程式員拿到一個工作時,往往只知道終點在何處,卻不知道中間需要經過那些地方。身為「用嘴巴寫程式」的管理者,應當為這樣的程式員提供協助、指引他們,讓他們知道這個工作需要循序漸進的完成那些事情。

不論是在正式的專案進度審查會議,或是平日的相處,管理者都應該對程式員的工作保持一定的關心
不只是關心完成或沒有完成,更要關心知不知道怎麼做、知不知道接下來要做什麼、有沒有遇上什麼重要的問題,需不需要什麼樣的協助。如果你是管理者,在必要時,你可能需要親自下場為你的程式員寫一段關鍵的程式碼,或者和他一起除錯。你對技術的掌握度以及豐富的經驗,可以為他的工作提供寶貴的助益,同時節省大量的時間。

身為「用嘴巴寫程式」的你,不意謂著就可以和技術脫節。你或許不負責具體程式碼的產出,但卻要為整個程式碼的產生鋪好道路、建好基礎的框架。想要為你的程式員提供方向、指點迷津,你不僅不能脫離技術,而且要更熟悉技術,特別是對於新技術趨勢的掌握,因為你最好就是團隊中主要決定技術架構的人,而且最好也是主要技能的提供者。

許多人都認為一旦加入「用嘴巴寫程式」的行列時,便可以擺脫撰寫程式碼的勞力工作,但如果你本身未曾在程式設計上下過苦功,建立起深厚的基礎,即使能轉移至管理性的職務,多半也不容易將這樣的工作做好。一來,因為你無法提供技術性的方向,所以對團隊能貢獻的價值不高。二來,你不容易成為團隊真正的精神領袖,在管理上難以建立一定的權威。程式員某種程度像是江湖中幫派裡的幫眾,幫主最好武功高強、才德兼備,否則帶領一群臥虎藏龍的弟兄們,恐怕會相當的吃力。

從閱讀者心出發的註解寫作

如果說有許多程式員不喜歡撰寫文件,那麼應該也有為數不少的程式碼不喜歡為他們所寫下的程式碼撰寫註解。撰寫註解和文件的工作,時常被許多程式員視為是浪費時間的工作。對他們而言,將心力專注在程式碼的產出,才是最實在的,文件和註解不過只是自己工作外的額外負擔,尤其是註解,並不像文件幾乎都會被列在專案的工作分解結構(WBS)中,更加不會被視為是程式員份內必要的工作,這就使得註解的地位似乎成了軟體開發工作中的雞肋一樣,倘若有,大家好像會覺得心安一點,因為程式碼似乎會更容易讀懂;倘若沒有,那麼彷彿也無所謂,對的程式碼還是依舊正常的起作用。

雖然有些管理者腦海都有一個大略的印象
寫下愈多的註解就愈能夠提昇程式碼的可讀性,他們或許會要求他們的程式員盡可能的撰寫註解,甚至還會訂下某些撰寫的標準,但因為許多管理者本身也不知道看待註解的正確態度,反而訂下許多對程式員來說簡直是莫名其妙的規矩,更加深了程式員原本就對於註解這一類「額外負擔」工作的反感。

在上述的文字中,提到了兩項一般人對於「註解」常有的誤解:(1)註解是程式員額外的負擔,對於工作的完成沒有太多幫助(2)要求程式員撰寫愈多的註解,就愈能確保程式碼的可讀性。

我們所能接觸到程式語言,幾乎都提供了註解的語法,這足以證明註解在程式設計活動中的重要性。而事實上,註解應當被視為是程式的一部份,而非獨立於程式碼之外的組成。在本文中,我們便將探討程式設計活動中這時常被忽略的一環
註解。

要更妥善的運用註解,就必須先認識到,註解是在補充程式碼的不足之處,所以程式碼和註解有點互補的關係,當程式碼本身的說明力愈高時,那麼所需的註解也就愈少,反之,所需的註解量也就愈多。之所以需要註解,是因為程式語言語法僅能表達有限的豐富性,需要利用人類的自然語言來進行補充。此外,除了語法本身的表達力受限外,程式員所做的設計、以及撰寫程式碼的風格與方式,都會影響到程式碼的說明力,而當我們在探討註解時,免不了需要探討程式碼本身的說明力。

能自我說明(self-documented)的程式碼正是一種具有高說明力的程式碼。在理想的情況下,具自我說明能力的程式碼單靠程式碼本身,便足以表示出撰寫者期望讀者了解的部份。也就是說,這樣的程式碼毋需為它標上註解,便足以提供極高的說明能力。

因此,註解量究竟多不多,並不是一個關鍵的判斷指標。有時候,寫的糟糕的程式碼反而需要更多的註解。紊亂的結構、不一致又不具意思的變數函式命名、再上混雜在一塊的一堆程式碼,即使搭配大量的註解,閱讀起來想必仍舊令人十分頭痛。當你看到你的程式員在程式碼間穿插著滿滿的註解時,或許反而應該感到更為憂心。

究竟需要多少的註解量,取決於程式碼的品質。良好的程式碼具有良好且一致的命名、排版、風格、以及各式的寫作習慣。而良好的設計,多半都具有簡潔、清晰、易懂的本質。你或許會為你的變數、函式、或類別寫下註解,藉以說明它們的作用。但是,倘若你能為它們取一個好名字,在程式員間共通的隱喻(metaphor)下,這名字將使變數、函式、或類別的作用不言可喻。而註解存在的需要性,也就因為良好的命名而消除。如果你的程式充滿了太多間接、隱畮的設計,那麼你的程式碼便會形同自行搭建起來迷惑讀者的迷宮,需要更多的註解扮演指引圖的作用,才能讓讀者順利從中脫困。相反的,優雅的設計通常本身便充滿了直覺,毋需太多註解補充,便足以充份表達。

有需要重構之症狀的程式碼,多半在進行重構後都能夠提昇程式碼的說明力,例如將一個大型的函式拆解成若干個小型的函式,並賦予其適宜的名稱,將使程式碼更易於明白。你應該盡可能的先提昇程式碼的品質,接著才是輪到註解登場的時機。

許多人為了寫註解而寫註解,他們並不試著明白註解的內容應該寫些什麼。例如,時常看到有些程式員的註解,其實只是程式碼的「換句話說」。註解多此一舉似的表達了讀者讀了程式碼之後也同樣能夠明白的事情。舉個誇張的例子:

        double f = d*2; // f 的值設為 d 值的兩倍

「將 f 的值設為 d 值的兩倍」是一般讀者讀了程式碼後即能明白的事實,並不需要額外的註解。在這個誇張的例子中,程式員浪費了時間寫下了註解,但卻沒有為程式增加更多的說明力。你應該利用註解解釋一些單從程式碼看不出來,或者是不易看出來的部份。

程式碼註解應該用來解釋「程式碼為什麼要這麼寫」,而不是「程式碼究竟寫些什麼」。程式碼寫些什麼,是讀者很容易從程式碼本身讀懂的,但讀者不容易在一時之間明白的,卻是你「為什麼」要這麼寫。例如,在一個排序的函式中,它在元素個數小於7時會使用insertion
sort
,而在元素個數大於7時則會使用quick sort。你並不需要寫下註解來說明這樣的事情,因為讀者閱讀程式碼時便能明白到這一層。那麼,註解應該寫些什麼呢?像「當元素個數小於7時,insertion
sort
運作較快,故使用insertion
sort
,反之則使用quick
sort
。」這樣的註解,說明了程式碼「為什麼」要這麼寫,而不單只是表面的「寫了些什麼」。

撰寫註解時,有一個很重要的態度便是要站在讀者的立場上來寫。你要設定你所寫註解的對象,並且猜想閱讀者的心,進而利用註解滿足閱讀者的需求。程式碼的讀者可能是和你一同共事的同事、有可能是日後接手你程式碼的人、更有可能是日後的你自己。當你撰寫任何一段程式碼時,你必須持續的在心裡想著「如果閱讀者看到我所寫下的這樣的程式碼,他是否能夠明白這段程式碼想要達成的作用?他是否能夠明白此刻我為什麼要這麼寫?」倘若不行,你是否有其他改寫程式碼的方式,使得讀者能夠明白。倘若你找不到更好的設計或更好的寫作方式,使得程式碼完全能自我說明,那麼就是撰寫註解的時機了,你可以利用註解來補充在程式碼之外想要表達的資訊。

此外,有些文件產生工具可以剖析固定的註解格式,藉以產生相對應的文件。例如javadoc便可以剖析Java原始檔中針對類別及函式的特定註解,並產生出十分實用的API文件。此類的註解,不僅有利於人類讀者閱讀,也有助於自動化產生說明文件。

有些人利用註解來標示日後幾乎無用或暫時無用的程式碼,千萬別這麼做,那會讓你的程式碼太過混亂。也有人在開始撰寫程式碼時發下宏願,立志要讓自己的程式註解看起來漂漂亮亮的,這也請適可而止。雖然註解本身也需要有一致而且清晰的形式,但這不意謂著,你需要花太多心力將它編排的十分美觀。註解本身的撰寫必須不能成為一件負擔太重的工作,因為這會使得你無法持之以恆。

另外,你不應該在註解中寫下一些應該留在版本控制系統上的資訊。例如,修正的記錄。有許多程式員會在程式碼中加上註解,來說明修改的歷程,包括修改日期、修改者、為什麼要修改、修改了什麼等等。這些應該是記錄到版本控制系統上的資訊。此外,當你修改你的程式碼時,請千萬要記得同步修改你的註解,使這二者隨時保持一致。

沒有人永遠能夠完全回到自己撰寫某一段程式碼時的心境,所以也沒有人能夠完全回憶起過去的自己究竟為什麼要這麼的寫下程式碼。基於自己隨時能快速回復記錄,也基於團隊合作時的程式碼共享,撰寫註解絕對是十分重要而且有實際功用的工作。重點不在於寫下多少註解,而是在於註解與程式碼是否能相搭配。好的註解就和好程式碼一樣,不僅形式一致而且清晰。好的註解從閱讀者的立場切入,並且切合閱讀者的心。

打造更穩固的程式碼先從思路方向著手

對程式員來說,撰寫程式的目標就是要完成功能,不論你的任務是要撰寫一整個系統、一個程式庫、一個模組、還是一個函式,不論你要撰寫的程式碼單位是什麼,在撰寫時,你總會有個功能性的目標,希望所完成的程式碼能夠提供特定的功能。而對初學程式設計的程式員來說,撰寫程式碼時,不可避免的會將所有的焦點以及心力放在達成功能,畢竟這是最起碼的要求,倘若連功能都不能完全實作出來,那麼更甭提其他事情了。

隨著經驗漸漸增多、技巧漸漸純熟,在撰寫程式碼時,所會關心的事情,慢慢的就會不僅僅限於如何實作出功能。你會關心能不能讓程式碼執行的更有效率,你也會關心如何讓程式碼更具可讀性、更容易維護,你或許還會關心如何讓程式碼容易修改、容易擴充。這些事情都是在滿足基本的溫飽(達成功能)以外的額外考量。

上述的幾個例子,都是許多初學者會漸漸涉獵到的進階議題。此外,或許有一個主題,是比較少會被探討到的,但我相信它的重要性,不在上述的這幾個進階議題之下。這個主題就是如何打造更穩固的程式碼。

所謂程式碼的穩固性(robustness),意指程式碼進到一個非常態的執行狀態時,能否適宜的因應。此處所指的非常態之執行狀態,有可能是資料庫連線無法建立,有可能是無法開檔或寫檔,有可能是所接收到的一個變數指標為NULL、等等。而所謂適宜的因應,或許是平和的終止系統並留下清楚的訊息以指出所遭遇到的異常狀態,或許是停止繼續執行並回傳相對應的錯誤代碼,也有可能是嘗試著修復所遭遇到的異常情境,使其再度回到正常的狀態。

當程式員投注所有的心力試著要達成程式的功能時,他的焦點幾乎都會放在程式的正常狀態。一般來說,我們會將所預期的正常執行路徑稱為晴天情節(sunny day scenario),而異常的執行路徑則稱為雨天情節(rainy day scenario)。當我們只關心如何達成程式的功能時,我們幾乎就只考慮到它的晴天情節,也就是假設所有的條件、參數、以及狀態,都落在我們預期的理想範圍中。

不知道你有沒有過這樣子的經驗,有些程式員總是能交出看起來似乎能夠運作的程式碼,倘若針對他的程式碼做一些簡單的測試,他的程式碼看起來就像是依照規格般的將功能實作完畢。但是,倘若將這段程式碼放到雨天情節下執行,你會發現它不僅不能正常的反應,有時甚至會讓整個系統無預警的終止(最常見的,莫過於存取空指標所造成的記憶體違規存取動作了)。

或許剛入門時,你會覺得光是在晴天情節下達成功能就是一件不簡單的任務。但是,當你的實作經驗愈多,你會發現,如何在各式各樣的雨天情節下讓系統生存下去,其難度相形之下更高。各式各樣的雨天情節,正是突顯出程式員間功力高下的關鍵因素。優秀的程式員所寫下的程式碼,在達成功能的同時,也一併考慮一些可能遭遇到的異常情境,並且適度的加以處理,不致於放任系統進入絲毫不可預期的狀態,並且做出不可預期的行為,甚至是無預警的墜毀。

這中間不僅僅只是技巧面上的差別,更重要的是思路方向上的完全扭轉。多年前,我曾寫過一篇名為「未慮對,先慮錯」的文章,便是在探討這種截然不同的思路方向。在這篇文章中提到,下棋的人其思考習慣是「未慮勝,先慮敗」,也就是在落子前還沒想到勝過對手的情境,卻已經把各種可能的失敗情況思慮透徹。撰寫程式碼時也是一樣,「未慮對,先慮錯」代表在你的思路中,對雨天情節的考量更在正常情況下的晴天情節之前。

有許多程式員處理一個物件時,不會考慮到這個物件可能是NULL的情況;當他們拿到一個陣列的索引值時,不會考慮到這個索引值可能超出陣列可允許的存取範圍;當他們開啟一個檔案時,不會考慮到這個檔案或許不存在;當他們試著建立一個網路連線時,不會考慮到連線可能會建立失敗;他們甚至不會取得他們所呼叫的大多數函式的回傳值,以進一步檢查這些函式的叫用動作是否失敗。因為他們的焦點完全就只放在最理想的正常執行路徑上。不過,天氣總不是天天都放晴,有時多雲有時陣雨,有時甚至還會颳颱風。

只考慮晴天情節的程式碼若是埋藏在系統中,像是隨時都可能被引爆的未爆彈。倘若測試案例的涵蓋範圍不夠大,那麼便有可能無法查覺潛在的問題。一旦遇上了下雨天,系統就要出事了。這樣的程式碼大大的降低了系統的穩固性。

當你撰寫程式碼的態度是「未慮對,先慮錯」時,基本上是以懷疑與不信任的眼光來看待你所面對的一切。對於每個所面對的變數,你會先在心中琢磨,它們的值是不是有可能是非法的值。對於每次的函式叫用動作,你都會假設它們有可能執行失敗。你甚至會考慮到,其他人所提供的函式或許還實作錯誤。當你實作你自己的函式時,你會假設使用你函式的客戶端程式員有可能根本就是胡亂使用,他所傳進函式的引數完全都是非法的值。當你實作與使用者相接的程式時,你會假設使用者根本就是毫無章理地胡亂輸入,或許你還假設使用者有可能是隻猴子。

近年來,有許多人(例如極限編程XP的愛好者)主張採用測試先行的開發方式。也就是說,在撰寫真正的程式碼前,先寫好測試這段程式碼的測試案例。事實上,這便是一種「未慮對,先慮錯」思考習慣的展現。撰寫測試案例和撰寫程式碼時會抱持的心態恰好相反。撰寫程式碼時容易正向思考,偏向思考如何在正常情況下達成功能。但撰寫測試案例時,腦子想的卻淨是如何提供各種程式可能沒有考慮到的情境條件。當你採用測試先行的開發方式時,會在撰寫真正的程式碼之前,仔細的在腦中將可能的各種情況一一展開。那麼,當你真正進到撰寫程式碼的階段時,自然而然的會將更多的可能情況納入考量並且加以處理。

有許多程式員會利用所謂的assertion(維護)來檢查程式所能處理的執行狀態。在某些語言中,它是以函式庫的方式實作,有些語言下它是巨集,而像在Java程式語言中,甚至提供了專門的算式語法。不論究竟是以何種方式實作assertion,其目的都是讓函式的撰寫者檢查函式執行時的狀態是否符合預期,例如檢查所傳入的某一指標是否不為NULL。雖然assertion僅在開發除錯階段才會起作用,並且被視為是一種開發時除錯的有用工具。而在正式的釋出版本中並不含assertion的機制,但是對程式員而言,養成在程式碼中運用assertion的習慣,意謂著你在撰寫程式碼的同時,總是思考了你所撰寫的程式碼所能夠因應的執行狀態,並且明白的表明了你的程式碼所不能接受的執行狀態。而這種思維方式,自然有助於你將思考的範圍擴展的更為廣泛,因而更有可能寫出較為穩固的程式碼。

 

pageicon 星期三 十月 22, 2008

投影片兒 - MSDN 開發人員講座– 從程式勞工邁向高階架構師之路講座 2008/10/16

上週很榮幸受台灣微軟的邀請,參與MSDN開發人員講座,並以「程式人與程式碼」為題,分享關於如何閱讀他人的程式碼 ,「開放原始碼的回收與再利用 漫談程式碼的相依性

等三個講題。投影片可於此處下載

這三個題目都是自本blog中的貼文中整理出來的 。我發現漫談程式碼的相依性在會後的迴響較大,可能是前兩個講題,我並沒有把自己的方法組織的很好的關係,希望可以再思考改進的方式

MSDN 開發人員講座都是免費入場,微軟大力舉辦這樣的活動,相信對台灣的開發人員來說,絕對是一大福音。也希望大家日後多多關注MSDN開發人員講座的消息,有機會多多捧場

投投

十年磨一劍

在一篇名為 “Teach Yourself Programming in Ten Years(花十年的時間學習程式設計)的文章(作者Peter Norvig)點出了許多程式員急於速成程式設計的現象。相信許多人看到這篇文章的標題,都會露出會心的一笑,因為相較於坊間許多標榜在幾天甚至幾小時之內可以學成某一程式語言或特定軟體技術的書籍而言,這篇文章標題中的「十年」,無疑的突顯出極大的對比。

已經記不得究竟是那本書籍開此風氣之先,但根據這篇文章的作者在文章中表示,他在Amazon上搜尋具有此種形式的書名,在搜尋結果的前兩百筆中,高達96%的書是和電腦技術相關。這實在是一個相當獨特而且有趣的現象。此類書籍大行其道,代表市場接受度高。為什麼唯獨電腦技術,特別是程式語言的學習者,這麼迫切的想要在極短的時間內學習完一樣事物呢?又是什麼樣的原因,使得人們也同樣期待在這麼短的時間內得以將它們學習完成?

許多程式語言本身即具備了易懂難精的本質。或許你可以在相對短的時間內了解、學會該語言的主要語法,並且讀懂典型的程式碼,但這不代表你確切的體會、掌握了該語言的核心及精髓。有些程式語言本身的設計,即試圖降低入門時的學習曲線高度及門檻,好讓新手程式員們也能輕易上手。而現代整合開發工具愈來愈先進,所打造的應用程式框架及現有元件更是日益完備,使得新手程式員只消自行撰寫極少量的程式碼,所得的應用程式便可產生極為炫目的效果。在許多開發工具的助陣之下,即使是剛入門的程式員,只需要拖拉幾個元件並略加設定,便能輕易的完成一個小型的資料庫應用程式,而且資料的新增、修改、刪除、查詢功能一應俱全。這樣的情況,讓許多程式員以及管理者產生錯覺,誤以為程式語言的學習、程式員的養成、以及軟體的開發,其實都不過是可以如此速成的事情。那麼,這些在若干天之內便教會其讀者學好某種程式語言或技術的書籍,其心態及動機,便也就不言可喻了,其大行其道也就不那麼的難以理解了。

除此之外,「軟體工程師」或「程式設計師」這樣子的職務,在現今的職場中,即使稱不上薪資優沃,但卻也是一份需求大過於供給的工作。這吸引了許多原先在校園中並不是修讀資訊相關科系的人們,競向轉職試著投入這一個領域之中。於是,許多教育訓練單位及機構,便推出各種滿足此種就職需求的課程,有的甚至是以取得各式證照為目標。而這類的課程,也促使了許多人意外的成為了程式員,而且對他們來說,能在愈短的時間內完成投入職場的準備,愈快找到合適的工作,是不可動搖的第一目標。在這樣的前提下,能夠「速成」,何樂而不為?

而上述的兩個例子,所呈現的便是社會上對於程式設計的某種觀感,有許多人甚至認為,程式設計是小道,而且速成不難。

程式設計真是一門可以如此速成的技藝嗎?相反的,我認為程式設計是一門需要投入大量的時間才能有所成的領域,而一名優秀程式員的養成更是需要十分漫長的時間,絕非許多人所想像的,透過速成的方式便可以達成。唐朝詩人賈島的《劍客》裡說「十年磨一劍」,用十年的光陰來磨出一名程式員,似乎也差不多。

不論你是在學校中修讀程式設計及電腦科學課程,或者是憑藉著書籍或課程自修入門,程式設計在本質上是一種全然需要在實戰中累積經驗和技巧的功夫,閱讀(甚至是少量且走馬看花般的閱讀)以及課程,不過只是踏進這個領域的敲門磚,書本中及課程上所告訴你的,都必須透過一次又一次的實作,才能不斷的從中有所體會。

許多程式員厭倦煩悶的撰寫程式碼的工作,他們期待著早日「晉昇」成為系統設計師、系統分析師、甚至管理職務,以便擺脫像工人一般的角色。一來,對撰寫程式碼容易感到厭倦,就難以成為一名優秀的程式員。二來,系統設計、系統分析之類的角色,都是建立在有優秀的程式設計基礎之上,而優秀的程式設計能力,除了透過持續、大量的程式撰寫工作之外,大概也沒有其他的方式可以達成。

大量的程式碼撰寫實作就像是蹲馬步的功夫,有時看起來很單調、枯燥,甚至沒有什麼學問在裡頭。大家都討厭反覆無聊的動作,但馬步蹲久了,下盤自然穩固了,也會更明白使力出力的法門。而這些都不是單靠老師點撥提示,或自修讀書就能夠輕易體會的。

例如,在書本裡頭、在課堂上,多半是教導你如何達成你想要的功能。對於各種可能會遭遇到的異常情況、該如何處理,以及程式撰寫時可能會犯下的意外錯誤與這些錯誤可能會有的癥兆,只能透過實戰來一一的磨練。一名有經驗的程式員,最大的資產之一在於他犯過更多的錯誤,使得他在撰寫程式的同時,知道如何預先的避開可能會犯的錯誤,同時在同樣的錯誤再度發生時,能夠很快的透過錯誤顯於外的癥兆,明白究竟是發生了什麼樣的錯誤,進而得以快速的解決。

過去的程式碼,就像鏡子一樣的映照出自己過去所犯下的錯誤。程式員透過審視自己舊有的程式碼,更容易察覺自己所犯下的缺失。在實戰中,程式員會親身體驗到自己拙劣不成熟的程式碼所帶來的苦果,並且在反省後力圖改善。這樣的感受格外深刻,因此也就永誌難忘。所有書中告訴你的良好寫作形式,都會在親身犯過錯誤後,有了更深一層的體會。愈是大量撰寫程式碼,也就愈能印證書中所言,也愈能自行發掘出書中所未能告訴你的事情。

在長期大量的實作下,程式員才能更深刻從自己最初的笨拙設計中,體會良好設計的重要性,也才能更明白如何透過好的設計優雅的解決問題。也只有在長期大量的實作下,程式員才能培養出洞察重覆需求的能力,撰寫出可重覆運用的程式碼,藉以提昇開發的效率。更只有在長期大量的實作下,才能夠將程式架構及程式碼的各種可能變化了然而心,面對可能會有的各種改變,預測出其動向,並預先做出反應。

本文標題訂為「十年磨一劍」並非指程式員必須訓練十年之久方能派上用場,而是想強調,程式員的養成並非一朝一夕之功,程式員對於自我的要求及訓練必須放到更長的時間軸上來看,而不能從速成的眼光限制了自己不斷成長的可能性。另外一方面,我更想強調,程式設計的訓練絕對是需要以長期且大量的實戰為基礎的,倘若只是紙上談兵,或者以為「熟讀唐詩三百首,不會作詩也會吟」,只需要大量的閱讀書籍,程式設計功力自然有所提昇,那麼絕對難以有所大成。

賈島的《劍客》,說的是「十年磨一劍,霜刃未曾試」,磨劍磨了十年,卻未曾真正的於實戰中試過。程式員的十年磨一劍,卻是要天天試劍,讓劍的鋒芒愈試愈利。

把對母乳媽媽的感謝與支持傳出去

« 十一月 2008
星期日星期一星期二星期三星期四星期五星期六
      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
21
22
23
24
25
26
27
28
29
30
      
今日

Search this blog

Links

Weblog menu

Today's referrers

Feeds