寫出好維護的程式碼 — 透過註解讓程式碼更容易維護
2025年11月27日
要讓程式碼庫變得更容易維護,有良好的文件會很有幫助;對程式碼來說,除了額外寫相關的技術設計文件,在程式碼中的註解 (comment) 也是文件的一種。
每當提到在程式中寫註解 (comments),在社群中就會聽到有人表示「如果有註解就代表寫不夠清楚,應該要重構而不是加註解」。
然而,真的是這樣嗎?
事實上,許多維護過大型程式碼庫的人,會同意程式碼要寫清楚,但同時也同意註解有其存在的必要性。把程式碼寫清楚,跟寫註解兩者是不衝突也不互斥的,當有寫得清楚的程式碼,搭配對的註解,兩者是能相輔相成,共同提升程式碼的可維護性。
在這篇文章,我們會詳細來談,為什麼推薦在程式碼中寫註解,以及註解該怎麼寫、哪些註解不該寫 (沒錯,即使推薦寫註解,也不代表推薦什麼註解都要加,審慎地寫才會對可維護性有幫助)。
為什麼推薦在程式碼庫中寫註解?
首先,讓我們先來談為什麼推薦寫註解。過去社群中很多人認為不用寫註解,是基於「程式本身寫得夠清楚,就不用註解」這個理由。然而程式本身或許可以清楚表達該程式碼做的事,但不能解釋「為什麼」要這樣寫,也不能解釋在什麼情境可能比較適合某個方法。對於這些相對後設 (meta) 的內容,註解就是很好的幫手。
更進一步說,好的軟體設計,應該要把複雜度藏起來,要藏起複雜度,我們需要抽象化 (詳見 寫出好維護的程式碼 — 抽象化 (abstraction) 時該注意什麼? 一文),讓其他使用該段程式碼的開發者,可以不用去管背後的細節。因此,如果一個開發者,還要去讀程式的細節才能懂如何用該函式或方法,那就失去抽象化的意義。
舉例來說,假如今天某個函式的介面中有 start 與 end 兩個參數,只看參數名稱,其實沒辦法知道 start 與 end 是否分別包含該數值 (例如 end 為 10,是到 10 之前,還是剛好到 10?),也沒辦法說明如果 start > end 程式碼會如何處理。
如果寫註解,開發者就可以不用去看該函式的實作細節,也能知道這些對使用來說很關鍵的資訊,這才能達到抽象化的意義。因此不論程式本身寫的清楚與否,好的抽象化搭配好的註解,都會對整個程式庫的維護有幫助。
沒時間寫註解不再是藉口
另一個很常見的不寫註解的理由,是因為「沒時間」。在開發時,很多開發者會認為寫註解的優先順序比較低,因此會想把時間花在寫新功能,而不是為已經開發好的功能寫註解,這很可以理解。
然而在軟體開發中,永遠有寫不完的功能,如果說因為要開發新功能而沒時間寫註解,就永遠不會有註解。從長遠的角度來看,這樣的代價是程式庫的可維護性會降低。如果從效益與成本的角度來看,寫註解的時間,會遠比其他開發者花在弄懂沒註解的程式所花的時間要少很多。
進一步說,現在有 AI 協助,寫註解所需要的時間成本,跟過去比起來大幅降低。現在甚至可以直接在 Cursor 或 Claude Code 等工具,幫忙寫程式碼時,就順便寫註解,或者可以新增一個 /add_comment 的指令,然後一鍵請 AI 幫忙寫好,開發者只需要檢查即可。
因此,如果你在的團隊,過去也很常會因為時間為由不寫註解,推薦可以試著導入 AI 工具,並讓團隊成員知道寫註解對長期程式碼庫的健康來說,投資報酬率很高。
什麼該寫成註解? 有哪些推薦的註解種類?
在理解為什麼要寫註解後,接著讓我們來談什麼該寫成註解。
如上面已經有提到的,註解的最大好處在於,可以捕捉到程式碼沒辦法傳達的資訊,這能夠讓未來要維護這段程式碼的開發者,能夠更快速地上手。特別對於團隊中加入的新成員,程式碼中的註解可以大幅降低讀程式的認知負擔 (cognitive load),以及減少未知。
如果沒有記錄下這些脈絡與原因,未來的開發者就不會知道為什麼當初是這樣寫,這變得只能猜測原作者的意圖。這不僅更耗時,也可能會因為理解錯原本的意圖,導致在維護該段程式碼時出錯。很多時候,未來要維護程式碼的是自己,許多人在寫完某段程式碼幾個月後,可能忘了自己當初為什麼這樣寫,所以寫註解不僅是幫助其他開發者,也很可能是在幫助未來的自己。
因此透過註解,把最重要的「為什麼」記錄下來,對於未來的維護者來說,會非常寶貴。以我們先前實際的經驗為例,過去曾看過一段程式碼覺得寫得很怪,因為不是按照該框架推薦的方式寫;但好在那段程式碼有註解,談到相關原因,而在讀那段註解時,發現原本記下的原因後來已經不存在了,所以那時就放心重構,而不是卡在思考「為什麼這段這樣寫? 假如要重構的話,會不會有什麼沒考慮到」的泥淖中。
推薦寫的註解種類
先前 Redis 的作者 antirez 曾經寫一篇《Writing system software: code comments.》文來分析他認為推薦寫的註解種類,其中有幾個是我們特別推薦的。
第一種,介面註解,antirez 把這個稱為函式註解 (function comments),但如果仔細看定義,這類註解是適用於任何介面,不只是函式。所謂的介面註解,就是讓維護者可以只看介面,不需要去看程式碼的實作細節,就完整掌握這個模組在做什麼。這是推薦在程式碼庫中,一定要寫的註解類型。
以下面這段來說,即使把實作細節忽略,也能完全明白這個函式在做什麼。
/* 在當前節點的子樹中尋找最大的鍵。如果記憶體不足則回傳 0,
* 否則回傳 1。這是一個輔助函數,供下面不同的迭代函式使用。*/
int raxSeekGreatest(raxIterator *it) {
// 實作細節忽略...
}
第二種,設計註解 (design comments) 與原因註解 (why comments),這兩類註解的核心重點,都是要解釋某一段程式為什麼是這樣設計。這類註解能夠協助未來的維護者理解,某段可能不是那麼顯而易見的寫法,之所以這樣寫的原因,這對於維護來說幫助很大。
第三類,教學註解 (在 antirez 文章中的 teacher comment 與 guide comment 都有類似作用),這類註解的目的是解釋一些可能對熟知程式碼庫的人沒幫助,但是對於剛加入團隊的人來說很有用的資訊。這類註解不像前一類,會特別解釋不顯而易見的原因,而是偏向教學的方式,解釋程式碼的運作。
在 antirez 的文章中,有更多類別的註解,不過以我們的實務經驗來說,上面這三大類別是從可維護性角度來說,最值得寫成註解的內容。
閱讀更多
如果你想更了解如何寫好註解、什麼該寫註解、什麼不該寫,還有寫註解時有什麼注意事項,我們在 E+ 的主題文都有詳談。E+ 的《寫出好維護的程式碼》系列文與課程,也會談其他有助於寫好程式的要點,歡迎加入 E+ 觀看 (連結)