代碼規范與讀寫可維護性


某公司員工小 A 即將離職,開始着手交接工作。員工小 B 被點名要求接手原先小 A 的工作。當小 B 打開小 A 獨立負責的項目后,瞬間驚呆了……半個月后,小 B 基本消化了小 A 遺留下來的代碼,此時業務部門發來郵件,說某系統出了一個 BUG,經技術部門排查發現可能出在原小 A 的代碼中,於是小 B 開始 Debug,卻無法確定 Bug 所在,幾欲抓狂……又過了半個月,市場部負責人和技術部門負責人一起走到小 B 處,告訴他有個新需求要加一下,不用擔心,只是一個小需求,於是小 B 開始在小 A 遺留的代碼里添加「小的新需求」,卻無法找到一些基礎的組件,幾欲抓狂……半年后,小 B 痛苦不堪,有了離職的打算……

上述場景是一個虛構的場景,假設了一個員工離開公司后可能對團隊帶來的影響。在這個虛擬場景中,我們可以歸納出該公司的一些問題:

  • 小作坊式的開發模式
  • 文檔缺失
  • 代碼不規范
  • 代碼難以被擴展
  • 項目結構不規范,不可避免地重復造輪子
  • 缺乏代碼審查
  • 團隊缺乏足夠的溝通和經驗交流
  • 項目管理令人絕望
  • ……

上述場景只是中國大陸 IT 行業的冰山一角,我相信還會有更加奇葩的故事等待着我們去挖掘。本文將重點講述代碼規范的重要性,以及做好代碼規范后能給我們帶來什么好處。本文不會告訴你代碼規范的詳細細節,這些細節因公司而異,因所使用的編程語言的不同而異,需要讀者在工作和經驗中進行總結,筆者避免越俎代庖。


開篇

高質量代碼的三大要素:

可讀性、可維護性和可變更性

做好代碼規范、提高代碼質量,能顯著增強代碼的可讀性、可維護性和可變更性。本文將這三大要素合稱為代碼的讀寫可維護性,努力提高代碼的讀寫可維護性,是做好代碼規范的必要非充分條件。代碼規范和架構設計是軟件的靈魂所在,代碼質量偏低,就像是人失去了三魂七魄中的一魄,就會喪失活力,影響正常運行,增加軟件交付后維護成本,出現推遲完成、超出預算、特性缺失等現象。

任何語言都需要強調編碼風格的一致性。只要是團隊開發,每個人都以相同的方式編寫代碼就是至關重要的。這樣大家才能方便地互相看懂和維護對方的代碼。
O'REILLY Maintainable JavaScript,Nicholas C.Zakas

實際上,每家公司都會有一份(或多份)代碼規范,因此提高代碼的讀寫可維護性的關鍵在於是否能落實公司的相關文檔,公司的技術總監、項目經理或相關代碼審查機關是否具有應有的執行力。如果不能落實,那么即便代碼規范畫得再美,具體的代碼也會丑到崩潰。

由於代碼規范和架構設計是軟件的靈魂所在,所以本文在介紹前者時將不可避免地涉及到后者。如果您不打算細讀下文,那么您可以直接跳過,因為下文並沒有向你展示一個全新的世界,也沒有為你提供一個更加精彩的世界。下文是基於現有世界的事實基礎上的再次演繹,不會顛覆你的認識,也不會告訴你斑馬不是馬而是驢,下文最大的特點是一而再、再而三地強調標題的重要性。因此筆者認為,如果您不是正在為公司內部演講或畢業論文准備素材而煩惱,您大可不必浪費時間通讀全文。


代碼規范

如果不想為以后挖坑,做好代碼規范是程序員和團隊負責人、項目經理的必修課。如何保證當前項目開發過程中壓力正常,而不是在后期面對過多的壓力、以至於噩夢纏身?最簡單的辦法就是照看好你的代碼,也就是落實好公司的代碼規范工作。每天為此付出一丁點的努力,便可以避免代碼「腐爛」,並保證代碼產品日后不至於變得難以理解(可讀性)和維護(可維護性)。

新項目開始着手開發時,它的代碼很容易理解和上手。然而,隨着開發過程的推進,項目不知不覺中演變為一個龐然怪物。發展到最后,往往需要投入更多的精力、人力和物力來讓它繼續下去。……開發人員在人稱任務時,可能會難以抵擋誘惑為節省時間而走「捷徑」。然而這些「捷徑」往往只會推遲問題的爆發時間……
via 高效程序員的 45 個習慣——敏捷開發修煉之道

因此公司有必要制定或修訂自己的代碼規范,以確保規范本身不存在太大疏漏,而后加強執行力度,確保程序員自覺編寫符合代碼規范的編碼產品。

每一種語言都有各自的特性,因此需要對每一種語言單獨制定代碼規范。但同一家公司的多份代碼規范不能差異過大,應在兼顧語言風格和官方編碼指南的基礎上進行統一。


代碼的可讀性

代碼的可讀性是指代碼讓人容易閱讀、跟蹤和理解的程度。提高代碼的可讀性可以為代碼閱讀者節約時間(避免閱讀時浪費過多無謂的時間)和精力(Debug、擴展功能或是性能優化的前提條件是你要讀懂這段代碼)。以下是摘選的可供參考的策略:

  • 編碼風格一致
  • 代碼清晰表達意圖
    • 寫人看得懂的單詞,如果選用英語,那么避免日語、法語和漢語拼音等,盡量使用語義化的命名組合;
    • PIE 原則:意圖清楚而且表達明確地編程;
    • 能夠讓人快速看懂(最低限度的要求是自己一個月后能快速讀懂);
  • 恰到好處的注釋
    • 不能太多或太少,注釋的形式根據代碼具體的情況有不同;
    • 避免用注釋包裹代碼;
    • 盡量留下簡明扼要的注釋;
  • 評估取舍
    • 避免寫一些現在不需要、將來也不太可能需要的功能:
      • 不完美主義:不多寫代碼(如會話存儲拆分);
    • 避免做沒有太大價值的優化工作;
    • 區分任務的輕重緩急:
      • 頭疼醫頭也醫腳:先容忍失敗,再解決問題(如節點關閉邏輯);
      • 不頭疼不醫頭:量化分析(如參數調整回滾等);
    • 綜合考慮一下性能、便利性、生產力、成本和上市時間……
  • 簡單就是美,避免簡單的功能寫出復雜的代碼;
    • 保持簡單的代碼遠比寫出復雜代碼要難得多,但這是值得的;
    • 不編寫討巧的代碼;
    • 避免無謂的條件嵌套和過度封裝;
    • 第一眼看上去就能知道其用處的代碼,才是簡單而美的代碼
    • 堅持操作方法的原子性,而后使用組合模式實現業務邏輯;
    • 避免大段代碼,要寫高內聚、低耦合的代碼;
      • 「如果在方法中還使用到了 #region...#endregion,那么你的方法需要拆分了」
        ——何鎮汐
  • 等等……

Hoare 談軟件設計
軟件設計有兩種方式。一種是設計的盡量簡單,並且明顯沒有缺陷。另一種方式是設計得盡量復雜,並且沒有明顯的缺陷。
——Charles Antony Richard Hoare
1934.1.11-,英國計算機科學家,排序算法中「快速排序」算法發明者,圖靈獎得主

當你期待別人寫出不讓自己犯暈的代碼的時候,你也要給別人帶去一縷陽光,閱讀這篇文章這篇文章以及這篇文章會讓你受益良多,這篇文章則介紹了項目依賴的一些技巧。


代碼的可維護性

軟件可維護性是指理解、改正、改動、改進軟件的難易程度。通常影響軟件可維護性的因素有可理解性、可測試性和可修改性。筆者這里將其分為兩大類:編寫時可維護性和運行時可維護性。

編寫時可維護性

編寫時可維護性是指在程序或系統上線后爆出 BUG,開發團隊能夠及時撲滅這個 BUG 且不會爆出其他 BUG。保持方法的原子性,提高代碼內聚,能使某處修改的影響降到最低,這樣某處方法出現 BUG,也不太會影響到其他模塊的正常運作。編寫時可維護性還包括了代碼的「可測試性」。

JavaScript Module AMD 標准執行者(如 require.js)和 CMD 標准執行者(如 sea.js)要求謹慎使用全局變量,將變量限制於一個個模塊之中,使得 JavaScript 代碼變得更有條理且更便於維護。

運行時可維護性

運行時的可維護性是指在系統運行過程中(或無需再次編碼發布、只需系統重啟一次)修改系統的某項配置並使其生效,且不影響現在正在進行的業務和用戶的操作。這要求軟件工程師不能把代碼寫死。例如配置文件、數據庫連接字符串、資源文件、日志等。

筆者曾有幸親眼目睹將配置寫死的后果:某系統會將處理完的圖片存到指定的盤符(F:盤),一次演示中,由於演示設備只有 C 盤,演示到這一步后軟件當場崩潰。


代碼的可寫性

代碼的可寫性包括「代碼的可變更性」,代碼的可變更性是軟件理論的核心,OOSE 花了極大篇幅都在講軟件的變更;敏捷開發則天然地要求軟件產品具有高逼格的可變更性。

代碼的可寫性是建立在代碼的可維護性上的,而代碼的可寫性與可維護性又都建立在代碼的可讀性上。如果代碼難以閱讀,那么 BUG 的修正將變得難以入手,新功能的添加就更是無從入手了。

不過前人已經為我們指明了許多方向,例如設計模式、RDD、TDD、DDD 等。使用設計模式可以顯著提高代碼的可寫性,盡管設計模式看上去難以理解且高深莫測,但通過多閱讀優秀代碼、優秀框架,多通過社區、群、博客、郵件組和小面積聚會與在此道經驗富於己者交流,能讓自己的水平快速上升。最關鍵的是多實踐,實踐是檢驗真理的唯一標准,也是掌握技術的唯一法門前文小結中言及道:「(程序員)富有探尋事物本質之精神」便是此理。程序員幾乎無一例外地會將自己看到的能使自己進步的知識與技巧立即(或不久之后)進行嘗試(實踐)。

代碼重構

代碼重構是代碼可寫性的一種特殊情況,把不穩定的積木塞塞緊。軟件開發的整個過程也是一個不斷迭代、不斷優化、不斷重構的過程。代碼重構旨在不改變現有功能的基礎上,通過調整程序代碼改善軟件的質量、性能,使其程序的設計模式和架構更趨合理,提高軟件的擴展性(可寫性)和維護性(可維護性)。

重構的目的是最大限度避免軟件走向生命周期的終結(維護開發成本高於開發一個全新產品的成本時,老的軟件便步入了生命周期的晚期)。通過不斷重構,糾正和改進軟件設計,使代碼更易為人所理解,有助於尋找到隱藏的代碼缺陷,使系統對新需求的變更保持較強的適應能力(可寫性)。

關於重構的知識就此打住,強烈建議感興趣的讀者購買《重構:改善既有代碼的設計》《大話重構》這兩本書。


代碼檢查

代碼檢查應采取自動化檢測與人工代碼審查相結合的方式進行,后者傾向於更為重要的設計錯誤上(如 BUG、競態條件和潛在死鎖等)。

代碼檢查的目的是理解代碼,改進代碼,確保代碼能正常工作,而不是批評任何人。

關於代碼檢查清單,可以閱讀這篇文章;關於代碼審查的專業知識與技能不是本文關注的重點,可以先閱讀這篇文章,然后購買相關的專業書籍進行學習。


編碼規范推薦

以下是一張可供參考的編碼規范示例,供讀者借鑒。


小結

自覺遵守代碼規范要求,確保代碼的讀寫可維護性,努力避免或緩解軟件代碼變質,是程序員的基本專業素質。同時落實好公司既有的代碼規范,提高領導層與執行層的執行力,是團隊負責人、代碼審查機關的必要權力體現。

我們接着補完本文開頭處小 B 的故事。小 B 經過謹慎思考后,最終決定離開這家公司,另覓東家。


參考資料與來源

  1. 編寫可維護的JavaScript,Nicholas C.Zakas,人民郵電出版社,2013
  2. 代碼規范的那些事兒,Kimy @CSDN,2012
  3. 代碼規范的重要性,Kdboy @ITEYE,2009
  4. 再談開發中的代碼規范,Zachaty_Fan @CnBlogs,2014
  5. 高質量代碼有三要素:可讀性、可維護性、可變更性,光輝飛翔,2012
  6. 高質量編程規范,火龍果
  7. 團隊項目開發“編碼規范”系列
  8. 8 種常見的 Java 不規范代碼
  9. C#代碼規范 程序員必備的秘笈
  10. O'REILLY Maintainable JavaScript,Nicholas C.Zakas,Posts&Telecom Press, 2013
  11. Optimize for readability first,Valentin Simonov,2014
  12. Practices of an Agile Developer,Venkat Subramaniam,Posts&Telecom Press,2010
  13. 編寫可讀性代碼的藝術,Boswell, D. / Foucher, T.,機械工業出版社,2012
  14. 防止代碼變質的思考與方法,QQ客戶端團隊博客,2014
  15. 我們如何進行代碼審查,InfoQ,2014
  16. 指數級增長業務下的服務器架構改造,梁宇鵬(環信首席架構師,前新浪微博通訊技術專家),2015
  17. 我理解的正確的代碼,B1ncer @CnBlogs, 2015

修訂歷史
0. 2015/06/25,完稿;

  1. 2015/06/27,第一次修訂。
  2. 2015/12/04,第二次修訂。

__EOF__


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM