身為程式設計者,應該時常會聽到 Dirty Code 這個名詞,像是「我剛接手的系統,裡頭竟然有一堆不可思議的Dirty Code」,或是「前人怎麼可以把程式寫得這麼Dirty呢?」之類的。顯然這個名詞已經是許多人的開發生活中,經常會出現的。

有趣的是,Dirty 本身就是一個不精準的描述方式,究竟什麼才算是Dirty?什麼又是不 Dirty ?兩段Dirty Code相較起來,究竟誰又比較Dirty?這些問題似乎也沒有一個明確的標準。

在本回中,就讓我們來探討和 Dirty Code有關的一些議題吧。

程式碼寫得不好,會變「髒」
首先,究竟什麼是 Dirty Code?從字面上的意思來看,那就是「骯髒的程式碼」。

我們都應該認真地思考,對於程式設計來說,所產出的程式碼,怎樣才算骯髒?為什麼它會被視為「骯髒」?

其實,不太容易找到一個確切的Dirty Code的定義,它似乎包括了大多數程式設計者,對於自己所不喜歡的程式風格或特性。

不過,一般來說,恐怕大多數的程式設計者都會同意,那些「可讀性低」、「不容易維護」、「不利日後修改」、「不利日後擴充」、「沒有考慮周詳完備,只求應急了事」的程式碼,是所謂的Dirty Code。

就像你在程式碼的內容中,如果看到有人「寫死(hardcode)」常數,你可能就會覺得這有點 Dirty,因為一旦想要修改這個常數,就得找出程式碼中所有用到的地方,並且逐一修改,這顯然滿足「可讀性低」、「不容易維護」、「不利日後修改」等標準。

又像是有人使用 goto 之類的指令,大肆在程式碼片段中任意地跳躍,或是使用未封裝的全域變數,放任程式碼四處加以修改、…… 等等。對於這些風格或寫法,相信讀者都會同意還滿 Dirty 的。

另一方面,自從「重構(Refactoring)」的方法問世以來,其中系統性的整理了若干所謂程式碼的「壞味道(Bad Smell)」,像是「重複的程式碼」、「過長的函式」、「過大的類別」、…… 等等。像在前一段中提到的,當你「寫死常數」(例如緩衝區的大小)時,一旦遇到這個常數必須修改,你就得找出所有用到的地方,並且同時做修改,一旦改漏了,就會出大問題,而這也正是程式碼「壞味道」裡的「霰彈式修改(Shotgun Surgery)」。

因此,重構方法中,對於程式碼「壞味道」的系統性定義,也指出了程式設計者可能會覺得程式碼 Dirty 的若干特質。

Dirty Code 會產生什麼負面的效應,使得程式設計者不喜歡呢?

首先,因為它可能是可讀性低,所以當然不容易被維護和修改,尤其當事情發生在Dirty Code被交接到後人時,更是會增加後人了解程式碼究竟如何運作的難度。即使自己就是寫下Dirty Code的原作者,也都有可能因為時間的推移,而忘了自己為何如此撰寫。

可讀性低的負面影響,不僅止於此,對於一些採用敏捷開發方法的團隊而言,程式碼的「集體共有」是很重要的一件事,他們希望團隊中的每個人都可以、也有能力修改任何一段程式碼。但是一旦程式碼中有所謂的Dirty Code,那麼那一段程式碼能被共用的程度就會降低,很有可能變成了特定的個人所專有,甚至沒有人可以擁有它了。程式碼的共有性會被Dirty Code給破壞掉。同時間,還會影響到團隊的情況,因為沒有人樂見自己必須參與含有大量Dirty Code的專案。

再來,更嚴重的是,低可讀性的程式碼,通常容易引發臭蟲。因為不容易讀懂,就自然容易成為培育臭蟲的溫床。寫出低可讀性程式碼的Dirty Code原作者,很有可能是本來就不懂真正的邏輯,所以才會造就Dirty Code。正因為他沒有真的搞懂,所以程式碼容易暗藏臭蟲。即使他沒有犯下錯誤,但日後修改的人,也會因為不易理解其中「奧妙」而做出了錯誤的修改,因而衍生出臭蟲。Dirty Code 不僅容易產生臭蟲,同時也很難將臭蟲於其中除去。一般認為,具備 Dirty 特質的程式碼,也不易測試。因為一些高度的相依性,使得程式碼牽一髮動全身,迴歸測試不易進行。

想掌握最新IT動態,歡迎按贊加入iThome粉絲團
程式碼髒掉的原因

程式撰寫的時間,往往不是開發中花去最多時間的一部份,測試和除錯,常常才是佔去了軟體開發大多數時間的活動。而愈 Dirty 的程式碼,不僅讓我們花更多時間來撰寫程式,也愈會讓我們在測試和除錯這兩個環節上付出更多的代價 。無怪乎,許多程式設計者講到Dirty Code都是如此咬牙切齒。但即使如此,Dirty Code 仍然在我們的開發生活中持續可以看到,這又是基於什麼原因呢?什麼原因導致程式設計者寫下 Dirty Code?

首先,是程式設計的知識和技能不夠。寫下Dirty Code的程式設計者可能是因為不知道這麼寫,會引發許多負面的效應,所以他才會這麼做,而這是一個很常見的原因。並不是每個程式設計者都明白程式碼的「壞味道」有那些,以及它們所能造成的糟糕局面。

即使明白,要有主動意識在撰寫程式的過程中加以規避,也不是一種十分簡單的事情。此外,程式碼在天性上總是朝著「腐敗」的方向在變化,Dirty Code 更是會愈來愈 Dirty,因此,才會需要「重構」的技巧來予以革新、淨化。

除了程式設計者的知識和技能不夠之外,另一個引發Dirty Code的重要原因,就是緊迫的時程。因為完成工作的時間不夠了,所以設計者顧不了以後、想不到未來,他只能看眼前了。有道是「頭過身就過」,眼前的難關先過再說,那裡能顧得了自己或別人日後能不能看得懂,那裡還想得到以後的維護或修改問題呢?

所以,我們也常會看到Quick and Dirty Code 這個名詞,原來 Dirty 是伴隨著Quick而來。為什麼想貪快而不顧髒?有時候是出自於天性,明明知道更不髒的寫法,但就是貪快;更多時候是因為時程壓力太大,為了縮短時間,也只好「冒險一髒」了。

避免Dirty Code出現的作法
因此,若是希望程式碼裡盡量避免Dirty Code的存在,就可以從這幾點著手:(1)加強程式設計者對於Dirty Code的相關知識及技能(2)「時時勤拂拭,莫使惹塵埃」,持續運用重構技巧,消除 Dirty Code(3)妥當地控制時程壓力。

說是要控制時程壓力,偏偏軟體開發的時程又是不易控制的。若是給定程式設計者太多的時程壓力,他為求自保,就很難保證他不會寫出不 Dirty 的程式碼出來。但是很多時候,的確時間就是真的如此緊迫,那又該如何呢?

在之前介紹過「技術債」的觀念,其實就是在講這種權衡的情況。你或許因為時間或其他因素的關係,寫下了一些 Dirty 的程式碼,或是做了 Dirty 的架構,但你自己內心明白這是需要付出多少代價的。你知道不同 Dirty 程度的程式碼,所欠下的技術債的輕重差異,更重要的是,你也有規畫好的「償債計畫」,對於持續要付出的利息,以及最後要償還本金的時間點,自己了然於胸。

在這種情況下,欠下技術債的Dirty Code,也就並非一無可取之處了。

想掌握最新IT動態,歡迎按贊加入iThome粉絲團

專欄作者

熱門新聞

Advertisement