身為一位認真負責的開發者,總是希望且能盡力寫出優美的程式碼,只是這程式碼在其他開發者眼中,卻有可能是醜陋的程式碼。

若你曾經公開或非公開地訕笑過其他開發者撰寫的程式碼,那麼,不妨試著重構一下過去自己撰寫過的陳年程式碼,在默默嘲笑、感受自己無地自容,或者偶而發現過去竟也能神來一筆的過程中,評斷一下這些日子以來,自己對程式碼美醜標準的演變。

聞自己的程式臭味

要指出別人的缺點總是比較容易,在討論區上,若開始出現「各種神人的code」或者「看過哪些誇張的code」之類的標題,就會引來各路人馬圍觀並提供各式程式碼笑點。

當然,大部份情況下,這只是程式人間的閒聊或工作上的抱怨,不過換個角度來想,能夠看得出笑點,表示對這類程式碼有著一定的瞭解與經驗,也才能夠看得出程式中的謬誤或幼稚之處,只是,誰沒有過去呢?何不把自己多年前的程式碼拿出來重構一下,看是不是還笑得出來呢?

要能夠重構程式,必須能嗅出程式碼的臭味,只是這次是聞的不是別人,而是自己的程式碼臭味,翻出來的程式碼越舊越好,最好是舊到連自己都不記得生過這個程式,然後試著運行、操作一下,回憶當初為什麼要撰寫這程式,接著閱讀程式碼,把自己會沿路訕笑、咒罵的東西記錄下來,你的心中可能會不斷湧現關掉程式碼的衝動,一定要忍住,別忘了,這令人憤怒的程式碼可是自己寫的!

自己的程式到底能有多少臭味呢?

每個程式人在「年紀小」的時候,寫出來的程式碼多半是冗長得難以閱讀,也由於不熟悉程式思考方式,而使得程式中有許多愚笨邏輯,當時因為對語言、程式碼等技術的不熟悉,而寫出了許多錯誤的語法、函式呼叫等。

在閱讀的過程中,有時也會因為要瞭解某條流程的定義,而必須在數個類別的程式碼之間穿梭閱讀,讓自己都快搞不清楚現在身處何方了。

此時,要能說出程式碼美醜的標準就簡單多了,就像那些在討論區上被嘲笑的程式碼一樣,似乎自己該犯的錯誤都犯了,程式中的「可讀性」極差,充斥著完全蠻幹的「演算邏輯」,對「技術的熟悉度」不足,類別的「職責分配」混亂,程式中各元件的「相依性」極高。

而許多文件或書籍,討論關乎程式碼美醜時,差不多也就是這幾個標準,你完全可以確定自己的程式碼是醜的了。

培養程式美感

程式碼的美或醜其實是個綜合指標,隨著開發者程度之提升,對程式碼的美感標準也會有所不同,在程度不足時,太美的程式也會因為無法理解,而看不出其價值。

無論如何,不具可讀性的程式碼絕對稱不上美,《無瑕的程式碼》、《易讀程式之美學》等書,都直接指出了程式碼可讀性的重要性,可與藝術之美比擬。

過於冗長的函式幾乎都能確定其內容難以閱讀,冗長往往造成函式本身命名上的困難,或者是其中的參數、變數等命名上的困難,而幾乎每個談及可讀性的文件或書籍,都會強調正確命名的重要性,在平時撰寫程式時,就應該維持函式的簡短而明瞭,在簡短方面,《無瑕的程式碼》中的建議是「函式的長度不要大於20行」,在明瞭方面的建議是「縮排程度不應該大過一或兩層」、「只做一件事」,也就是「只有一層抽象概念」。

程式中的愚笨邏輯,大概是最常被拿出來在討論區訕笑的對象,我在〈跳入程式屎坑〉中也談過,削減笨邏輯是大量改善程式碼品質的重要方式,然而,開發者在不同時期,也會寫出不同程度的笨邏輯,舉例來說,或許過去對你而言,對null的判斷是理所當然之事,現在的你看到程式碼中充斥大量null判斷,卻可能會感到愚蠢而不耐。

這說明了,要能不寫出笨邏輯,其實是需要經驗與訓練,這可能是來自對大量程式碼的觀摩、各種程式語言語法的模仿或典範學習,事實上,也會來自一個經常被忽略的面向,也就是對資料結構、演算法甚至是數學上的訓練,在《程式之美》中,就將程式的美妙之處,著重在結構、演算法、數學等分析與訓練上,而不是只靠著基礎流程語法來組合蠻幹。

程式碼中展現的技術熟悉度,也表現出程式的美感,例如,過去可能因為不熟悉API而使用兩個List做一對一,現在也許會改用Map;過去使用索引跑迴圈,現在也許會改用for each語法,而處理數列相關的問題時,過去也許撰寫迴圈,現在能使用filter、map、reduce等方法。

必須謹記的是,對技術的熟悉度不應當是賣弄聰明,而故意寫得玄疑難解,Brian Kernighan說過:「除錯難度會是一開始寫程式時的兩倍,因此,如果你在寫程式時盡了力賣弄聰明,根據定義,你的智商會不足以進行除錯」。

自己的爛帳自己還

程式碼的品質該怎麼衡量呢?Thom Holwerda在2008年發表了一幅漫畫〈WTFs/m〉(http://goo.gl/rGF9UN),嘲諷對程式碼品質唯一有意義的評斷指標,就是程式碼審閱時每分鐘WTF的次數。看著別人的程式碼,可以指指點點,說我才不會這麼寫是很簡單的一件事。只是,換做自己來寫的時候,真的是如此嗎?

如果現在審閱的是自己的程式碼,而每分鐘WTF次數太高,那麼就是該還帳的時候了,如果有辦法看出自己的程式碼醜陋之外,也有能力清償自己的債務,也才能真的證明,自己對程式碼美感不單只是嘴砲,也具有建立美感時貨真價實的能力,畢竟若面對自己寫的舊程式,都不肯盡心盡力去重建美感,要能在面對他人程式時認真地面對,我想也是不太可能的事。

實際上,在自己的爛帳自己還的過程中,除了訓練重構能力之夕,也是在重新訓練美感。例如說,將冗長函式化為逐個小函式其實並不難,特別是有強力支援重構的編輯器在手的時候,真正的重構與美感訓練,也就發生在變數、函式的命名,重複演算的提取與重用之時。

最難的,或許是在職責的分配或相依性的隔離。經常發生的事情就是,某個函式搬到B類別重構之後,又重新搬回原類別,接著又發生重構,發現到函式又可放到C類別,這過程有時令人沮喪,但並不愚蠢,而是程式碼被磨練地越來越細膩。

不見得全然都是醜的

一起來看看〈The six months rule〉(http://goo.gl/8MIWUp)這篇短文,大意是說,每個程式人都應該回頭看看自己六個月前的程式碼,並應當對當時的作法感到作噁,如果是這樣,應當感到高興,這代表程式人一直在成長。

六個月的規則我想只是個比喻,這表示開發者偶爾要翻翻自己的舊帳,不要只是會笑別人,最好的方式是也不要怕人笑,現在利用GitHub等管道公開程式碼給大家看,是很好的一個管道,若在某個討論區發現被笑的是自己的程式碼,也應該高興,至少你知道了被笑的原因。

當然,若在評析自己的程式碼美醜時,能發現其實以前某些神來一筆的想法也不錯,那就更值得高興了,這表示過去寫出的不見得全然都是醜陋,而是有些許美感的程式碼了,這時可想想看美感是在哪呢?

這類的程式碼,若有機會重新看一次時,還會覺得美,或是略顯醜陋呢?

屆時覺得醜陋的原因,又是何在呢?

專欄作者

熱門新聞

Advertisement