[程式設計] 你真的會寫函數註釋?這裡給你一個答案

2023-12-04 12:02:51

導論

軟體開發作為一項系統工程,其中最基礎而重要的一個環節就是程式碼編寫。然而,在程式碼編寫的順序上,業內一直存在著「先註釋後程式碼」和「先程式碼後註釋」兩種模式,關於哪一種模式更好,爭論一直未休。

事實上,這兩種模式各有利弊。「先註釋後程式碼」強調整體設計,注重可讀性和可維護性;但其操作成本高,效率低下。「先程式碼後註釋」注重快速驗證思路,但容易忽略設計細節,給日後維護帶來困難。文將從歷史演變和軟體工程實踐兩個角度,系統論述這兩種模式在不同階段的優劣勢,並給出更深入的分析,得出一個邏輯自洽的理論性編寫建議。

本文的觀點如下:

  • 隨著IDE和其他軟體工具的發展,兩種模式在歷史上都有過不同階段的應用
  • 從專案管理和程式碼質量兩個層面,它們各有利弊
  • 對註釋目的正本清源,才能正確寫註釋
  • 兩種模式本質上不是對立的

歷史上的演變

早期機器語言階段,由於編碼難度極大,程式開發主要注重設計與檔案記錄。這一時期,「先註釋後程式碼」成為主流模式。同時,隨著軟體工程學科的形成和發展,「先註釋」模式作為一種系統化的軟體開發方法也得到推廣和傳播,進一步成為主流看法。

隨著高階語言的出現,程式設計難度降低,但專案規模也日益擴大。為了提高開發效率,一些開發團隊開始採用「先程式碼後註釋」的方式來進行快速編碼與迭代。這種模式強調先按功能模組實現基本功能,後續再梳理註釋與設計檔案。

90年代,隨著網際網路的興起,軟體開發專案越來越多采用小型團隊的敏捷開發模式。這種模式下,快速交付產品成為首要任務。「先程式碼」模式因其高效的開發特性而得到廣泛採用。

總體來說,隨著技術水平和管理模式的變化,」先註釋「與「先程式碼「兩種模式在不同歷史階段都發揮過各自的優勢。它們也在不斷互相影響,共同推動著軟體開發正規化的演變。

更多的細節

其實爭論主要源自於對於專案不同階段的強調。其實雙方都承認整個專案,尤其是大型專案都需要整體的設計,對這一點雙方並沒有嚴重分歧。主要的分歧在於對於更小的,函數尤其是小函數級別的範圍上,究竟是否需要完備的事先設計並形成檔案化,還是快速進入編碼並在程式碼趨於穩定後回頭補充相關檔案。

在先編碼概念下,其中比較有名的一本2015年出版的書:《Code as Design: Three Essays by Jack W. Reeves》。在文章中作者指出:

  1. 編碼並不是機械得實現原始設計。編碼過程中程式設計師必須做出大量設計選擇和權衡,這才是設計活動的關鍵所在;
  2. 編碼階段的設計決策事實上會深刻影響最終軟體的結構。像命名、程式碼組織、控制流等都包含設計內容。因此不能認為編碼只是對映先期設計。
  3. 依賴設計檔案而不看實際程式碼,無法判斷軟體品質。因為檔案常常會與程式碼脫節。只有程式碼才是設計的權威表

而強調先註釋的一方則認為即使是最小的函數,也應該先進行基本的設計然後展開編碼。

幾種函數註釋模式

如果註釋的內容就是程式碼是如何實現函數的功能的,那麼顯然當函數的最終程式碼在實現過程中會被多次重構的話,那麼「先編碼」的觀點顯然是正確的。即使先進行設計,那麼99%的設計都是會被推翻的。然而我們不能因此就同意在最終函數級別就應該「先編碼」。這裡的核心問題是雙方對於註釋的理解不科學。

我們給出註釋可能的幾種模式

  1. 註釋所包含的資訊量完全和程式碼所包含的資訊量一致
  2. 註釋所包含的資訊量是程式碼所包含的資訊量的真子集
  3. 註釋所包含的資訊量中包含一個程式碼所包含的資訊量的真子集

如果註釋的內容就是程式碼如何實現,從資訊量角度兩者如果是等價的,那麼這樣的註釋其實就是資訊的冗餘。為了維護註釋和實際程式碼的一致性,顯然需要更多的工作量。此時我們需要的僅僅是一個自動化工具,能自動將註釋對映成程式碼,或者自動將程式碼對映成註釋就可以了。幾十年來這樣的工具都沒有出現,足以證明第一個模式並不是事實。這個推理對於第二種模式同樣適用。註釋如果只是程式碼資訊的一個真子集,那麼用剛才的工具也基本能解決問題。

函數及函數內註釋的定義

從需求到程式碼,是一個資訊量逐漸丟失的過程,也是一個資訊量逐漸增加的過程。有些設計意圖背後的原因不會在程式碼中被展示,具體程式碼的實現方式幾乎不可能在業務需求中被指定。註釋究竟需要描述什麼東西?我們把註釋分為兩類,一類是偏業務端的資訊描述,另一類是偏技術實現端的描述資訊。基於現有的討論分析,我們給出以下的建議

什麼時候寫註釋

  • 函數註釋必須先於實際程式碼編寫而完成

註釋寫什麼

  • 函數註釋的核心內容是函數的業務目的,不涉及函數的具體實現方式和處理過程
  • 函數內註釋的核心是具體業務操作步驟、相關演演算法或技術實現的資訊

遵守以上的建議,那麼我們的函數註釋將處於一個比實現程式碼更穩定的狀態,不會因為具體功能的實現方式在實際編碼過程中的優化和重構而變化。並且提供了實現程式碼所不能體現的實際業務上的目的和描述資訊,使得整個專案從上到下的設計目的的描述得以連續和完整。同時明確了業務描述和技術描述兩種不同目的的註釋資訊的編寫位置。

如果我們進一步遵守函數職責單一化的建議,那麼實際上函數內註釋幾乎就不會出現需要描述業務操作資訊的情況了,因為每個函數內很可能最多隻出現一個條件語句了。

總結

本文分析了程式設計行業中常見的「先編碼」和「先註釋」觀點的歷史成因和理念差異,指出兩者其實並非完全對立而是相輔相成。並且給出了更為系統化理論化以及邏輯自洽的關於軟體中函數註釋資訊應該如何編寫的指導性意見。