程式碼撰寫原則(Programming Rules)

本部落格的文章「程式碼維護上的難題(The Challenges and Difficulties of Code Maintenance)」說明了程式碼若沒有好好撰寫時,往往會造成維護上的困難。於是筆者參考網路資源與自己經驗來整理出來一些常見的 Programming Rules 之要點,細節說明還請讀者自行閱讀參考資料。

這份規範整理了從程式風格、架構設計到效能優化的核心心法,是降低程式碼維護難度的關鍵指南。

🎨 一、 風格 (Style)

良好的程式風格是寫給「人」看的,而不是寫給機器看的。

  • 變數命名邏輯:全域變數(Global)因影響範圍廣,應使用描述性的名稱;局部變數(Local)則使用簡短的名稱即可。

  • 命名精確與一致:函式命名採用主動詞(如 calculateTotal, fetchData)。整體專案風格保持一致。

  • 結構與表達式

    • 利用清楚、一致的縮排與大括號({})風格來顯示程式結構。

    • 表示式使用符合人類直覺的「自然形式」。

    • 利用括號來明確定義運算順序,拆開複雜的表示式,保持語意清楚。

  • 避免副作用與潛在陷阱:當心函式內的副作用。避免使用函式巨集(Macros),若必須使用,務必將巨集主體和引數用括弧圍住。

  • 常數化(避免魔術數字):為程式中的魔術數字(Magic Numbers)取一個有意義的常數名稱。使用字元常數而非整數常數,並善用程式語言(如 sizeof)動態計算物件大小。

  • 智慧註解

    • 註解應用於解釋函式目的與全域資料,且絕對不能與程式碼行為牴觸。

    • 不要把時間花在註解明顯的事情上。

    • 不要註解爛程式碼,乾脆直接改寫它。 保持清晰,不要製造困惑。

🔌 二、 介面 (Interface)

好的介面設計能降低模組間的耦合度。

  • 封裝細節:隱藏實作細節,只暴露一小組剛好夠用的原始功能。

  • 誠實與一致性:不要在使用者(調用端)背後做些他們無法察覺的事。在每一個地方都用同樣的方式作同一件事。

  • 資源與錯誤處理

    • 對稱原則:以和配置資源(Allocation)相同的層級與模組來釋放資源(Deallocation)。

    • 分層防禦:在低階(Low-level)的地方偵測錯誤,在高階(High-level)的地方統一處理它們。

    • 例外的嚴格定義:只有在真正例外(Exception)的情況下才使用例外機制。

🔍 三、 除錯 (Debugging)

除錯是一門系統化的科學,而非盲目猜測。

  • 定位與重現:讓臭蟲(Bug)能夠穩定重現,顯示輸出(如 Log)來為你的搜尋定位。

  • 經典策略:先分化再征服(二分搜尋法定位錯誤)、尋找你熟悉的錯誤樣式、研究失敗數理學。

  • 除錯好習慣

    • 立刻除錯,不要等到以後;不要犯兩次相同的錯誤。

    • 檢視最近所做的程式更動,取得堆疊蹤跡(Stack Trace)。

    • 開始動手修改之前,先靜下心來閱讀程式碼內容。

  • 外部借力:向另一個人解釋你的程式碼(小黃鴨除錯法)、撰寫自我檢查碼、寫下一個日誌檔、畫一張架構圖、善用現代開發工具並保存紀錄。

🧪 四、 測試 (Testing)

測試能為重構與維護提供安全網。

  • 邊界與條件:在邊界條件(邊緣測資)測試程式碼。嚴格測試前置條件(Pre-conditions)與後置條件(Post-conditions)。

  • 防衛性程式設計:以防衛的態度設計程式,善用斷言(Assertion)並確實檢查每一次函式回傳的錯誤。

  • 測試策略

    • 以遞增、漸進的方式進行測試,優先測試結構簡單的部分。

    • 在測試前,必須先明白你預期的是什麼樣子的輸出。

  • 自動化與查驗:查驗保存的特性,比較兩個互相獨立的實作內容以檢驗正確性。評估測試所涵蓋的範圍(Code Coverage),並盡可能讓回歸測試(Regression Testing)自動化,建立獨立的測試。

⚡ 五、 效能 (Performance)

過早的最佳化是萬惡之源。先求正確,再求速度。

  • 科學化量測:使時間測定自動化,運用效能分析工具(Profiler),將注意力集中在真正的效能瓶頸(問題點)上。

  • 高階優化:畫一張圖理清結構,通常採用較佳的演算法或資料結構,比調整程式碼更有效。啟動編譯程式的最佳化功能(Optimizations)。

  • 程式碼調整(細節)

    • 無關緊要、非瓶頸的東西不要做最佳化處理。

    • 集中共同的子表示式,以廉價的操作取代昂貴的操作(如用位移取代乘除)。

    • 展開迴圈(Loop Unrolling)或是將它們刪除。

  • 空間與快取:以快取緩衝區(Cache)處理經常使用的值,緩衝處理輸入與輸出(Buffered I/O)。寫一個特殊目的之記憶體配置函式。

  • 計算策略:分開處理特殊案例、預先計算結果(Lookup Table)、利用近似值、甚至在必要時以低階語言改寫。

  • 空間優化:採用可能的最小資料型態來節省空間。不要重複儲存你能輕易計算出來的東西。

🌍 六、 移植性 (Portability)

確保程式碼在不同環境、系統與時間下都能正常運作。

  • 依循標準:遵循國際標準(Standard),以主流、常見的方式設計程式,多嘗試幾種編譯程式。

  • 函式庫與相依性:使用標準函式庫,只使用那些到處都有的跨平台功能。

  • 解耦系統相依:避免條件式編譯(Conditional Compilation)。把和系統相依(Platform-dependent)的事物分開在不同的檔案中,並隱藏在介面後面。

  • 資料交換:使用文字(Text)來交換資料。若用二進位,請用固定位元組順序(Endianness)來交換資料。

  • 相容與國際化

    • 如果你變更了規格,就改變名稱。與現有的舊程式及資料保持相容。

    • 不要預先假設使用的都是 ASCII,更不要以英文為預設的在地化角度。


若您覺得文章寫得不錯,請點選文章上的廣告,來支持小編,謝謝。

If you like this post, please click the ads on the blog or buy me a coffee. Thank you very much.

留言

這個網誌中的熱門文章