11/15/2024, 20:31

寫程式不只是對機器說話

Less is not always more.

先前無意間看到一個有趣的技術討論:「好的程式碼不需要註解」。這個說法乍聽之下似乎很有道理,但實務經驗告訴我,事情並非如此簡單,因此藉這個機會分享一下我認為寫程式的幾個原則。

為什麼我們需要註解?

在理想世界中,每一行程式碼都應該是自解釋的(self-explanatory)。但實務上的軟體開發往往充滿了各種特殊需求和業務邏輯,這些邏輯可能並不那麼直觀。舉例來說:

  • 某個特殊的計算邏輯可能是因應了特定的業務規則
  • 某個看似繞遠路的實作可能是為了處理極端案例
  • 某個暫時性的解決方案可能是考慮到了系統限制

在這些情況下,適當的註解不僅能幫助其他開發者理解程式碼的用意,更重要的是,它能幫助「未來的自己」理解當初的決策理由。

Code Review 的真正價值

很多人認為 code review 主要是為了找出程式碼中的錯誤。但事實上,「錯誤」的定義會因時空背景而有所差異,沒有人能寫出完美無缺的程式碼。過去面試的經驗也顯示,有些人抱持 只有資深工程師才能向下 code review。 然而,我認為 code review 最重要的功能其實是「資訊同步 🔁」。

透過 code review 這個過程,團隊成員能夠:

  • 分享系統現況的知識
  • 同步對業務邏輯的理解
  • 預防可能的誤解和重工
  • 建立共同的團隊認知

因此,即使是看似簡單的改動,也都值得經過完整的 code review 流程。因為不同開發者在不同時間接觸相似的修改時,如果缺乏這個資訊同步環節,很容易導致知識斷層,造成不必要的困擾。

分享一個真實案例,曾經在專案中,我們有一個下拉式選單,原本是由前端維護並負責管理多語系翻譯。後來因為需求變更,改為由後端 API 動態提供選項內容。這個改動導致前端的翻譯字典檔中的相關內容實際上已經失去作用,但由於時程緊湊,負責改動的開發者並沒有移除這些過時的翻譯內容,而這個 PR 當時也只有我看過,其他人可能是因為需求簡單,或甚至改動不多的關係沒看。 不久之後,另一位前端工程師接到了一張新票:「調整選單中的某段文字」。由於沒有同步先前改動資訊的關係,這位同事很自然地修改了各語系字典檔中的文字並提交了 PR。這個改動不僅沒有實際效果(因為文字是由後端提供),更糟的是透過這個 PR 可以得知修改者根本也沒確認過畫面是否符合預期,然後就擅自合併了 🤯 這樣的 PR 還有意義嗎?

TypeScript:更好的開發體驗

說到提升程式碼可讀性,不得不提到 TypeScript。即使不是很熟悉泛型或其他進階特性,TypeScript 的型別系統也為我帶來了顯著的開發體驗提升。

在使用 JavaScript 時,要理解一個屬性可能的值,往往需要翻遍整個程式碼庫。但在 TypeScript 中:

  • 型別定義清晰地告訴我們可能的值
  • 可以快速追溯型別的來源
  • IDE 的支援讓開發更有效率

在開發路上,或多或少都看過後端給出這種狀態碼

demo.jsx
        status: 0 // inactive
status: 1 // active
status: 2 // deleted

      

在沒有型別系統的情況下,要理解這個 status 可能的值,我們需要:

  1. 翻遍使用這個屬性的所有程式碼
  2. 查看 API 文件(如果有的話)
  3. 或是直接詢問後端同事

但使用 TypeScript,我們可以把已知狀況先定義清楚,把數字變成有意義的 enum 來增加可讀性

demo.jsx
        enum UserStatus {
  Inactive = 0,
  Active = 1,
  Deleted = 2,
}

      

結論

我們要認知到程式碼的第一讀者其實是,而不是電腦。電腦只關心指令是否正確,但人需要理解程式碼背後的思維和意圖。這就是為什麼我們應該摒棄 aabb_1 這種毫無意義的命名方式,因為節省打字的幾秒鐘,可能會讓之後的閱讀者花費數倍的時間來理解程式碼的用意。

很多開發者會說:「這是我的個人專案,不需要寫得那麼講究。」但實際上,我們永遠都在跟「未來的自己」協作。六個月後再回來看程式碼的你,基本上就是另一個開發者。當你必須修改半年前寫的程式碼時,你會非常感謝當初那個寫下清楚註解的自己。好的程式碼習慣不該因專案規模而打折。

TypeScript 的確為我們帶來了更好的開發體驗,但這不表示我們就可以完全拋棄註解。型別系統告訴我們資料的結構和限制,但它無法說明商業邏輯背後的原因。TypeScript 和註解應該是相輔相成的關係,一個告訴我們「是什麼 (What)」,一個告訴我們「為什麼 (Why)」。特別是在沒有 TypeScript 的專案中,清楚的註解更顯重要。

而 code review 的過程,不應該被簡化為找出程式碼中的錯誤。它是知識傳遞的重要管道,是團隊同步資訊的關鍵時刻。就算是微小的改動,也可能藏有重要的業務邏輯更動。透過完整的 review 流程,我們不只是在審視程式碼,更是在建立團隊的共同認知。

最後,程式開發是一門溝通的藝術。好的程式碼應該像一篇好文章,邏輯清晰,結構分明,讓讀者能夠輕易理解作者的意圖。不管是變數命名、型別定義、程式註解,還是 review 流程,這些都不是額外的負擔,而是寫給人看的必要元素。畢竟,程式碼終究是要給人閱讀的,而不是單純地給機器執行。

for en version: Writing code for people, not computers