第 17 章 一致性
一致性是降低系統複雜性、使其行為更容易理解的有力工具。系統保持一致,意味著相似的事情采用相似的做法,不同的事情采用不同的做法。一致性讓已有知識可以複用:理解了一處的做法,就能立即理解其他採用相同做法的地方,不必從頭學習。如果系統的實作缺乏一致性,開發人員就必須逐一瞭解每種情況,花費更多時間。
本章概覽一致性為什麼重要,怎麼保持?
一致性還能減少失誤。系統缺乏一致性時,兩種實際不同的情況可能看起來一樣。開發人員看到熟悉的模式,可能會根據過去的經驗作出錯誤假設。反之,如果系統保持一致,根據熟悉情形作出的假設就有可靠依據。因此,一致性能讓開發人員工作得更快,失誤更少。
17.1 一致性範例
一致性適用於系統的許多層級,下面列舉一些例子。
名稱。 第 14 章已經討論了以一致的方式使用名稱的好處。
編碼風格。 如今,開發組織通常會制定編碼風格指南,在編譯器強制執行的規則之外,進一步約束程式的結構。現代風格指南涵蓋縮排、花括號位置、宣告順序、命名、註解等方面,也會限制使用被認為有風險的語言特性。風格指南讓程式碼更易讀,還能減少某些型別的錯誤。
介面。 同一介面的多種實作也是一致性的例子。瞭解其中一種實作後,其他實作就更容易理解,因為你已經知道它們應提供哪些特性。
設計模式。 設計模式是針對常見問題的公認解決方案,例如用於使用者介面設計的模型-視圖-控制器(MVC)方法。如果現有設計模式適合你的問題,採用它通常能更快完成實作,也更有可能奏效,讀者也更容易理解程式碼。第 19.5 節將詳細討論設計模式。
不變條件。 不變條件是變數或結構始終滿足的性質。例如,儲存文字行的資料結構可能會強制要求每行始終以換行符終止。不變條件減少了程式碼中必須考慮的特殊情況,並且更容易推斷程式碼的行為。
17.2 確保一致性
保持一致性並不容易,尤其是許多人長期參與同一專案時。一個小組可能不瞭解另一個小組的約定;新成員也可能因為不瞭解約定而無意中違反,甚至建立與之衝突的新約定。下面介紹一些建立和保持一致性的技巧:
文件。 用文件列出最重要的全域約定,例如編寫編碼風格指南。把文件放在開發人員容易看到的地方,例如專案維基(Wiki)的顯著位置。鼓勵新成員閱讀,也鼓勵已有成員不時回顧。網上有不同組織公開的風格指南,可以選一份作為起點。
對於區域性約定,例如不變條件,應在程式碼中找到合適的位置記錄。約定不寫下來,其他人就不太可能遵循。
強制執行。 即使文件寫得好,開發人員也很難記住所有約定。確保約定得到執行的最佳方法,是編寫工具自動檢查違規情況,並要求程式碼通過檢查後才能提交到儲存庫。自動檢查對低層級的語法約定尤其有效。
我最近的一個專案遇到了行終止符問題。一些開發人員使用 Unix,以換行符結束一行;另一些使用 Windows,通常以回車符加換行符結束一行。在一個系統上編輯另一個系統處理過的檔案時,編輯器有時會把所有行終止符改成當前系統的格式。這樣,檔案看起來每一行都發生了變更,真正有意義的修改反而難以辨認。我們約定只使用換行符作為行終止符,但很難確保每個開發人員的所有工具都遵守。每次有新成員加入,都會出現大量行終止符問題,直到他們適應約定。
最後,我們編寫了一個簡短腳本,在向原始碼儲存庫提交變更之前自動執行。腳本檢查所有修改過的檔案,只要有一行包含回車符,就中止提交。它也支援手動執行,將回車符加換行符替換為換行符,修正格式不符合約定的檔案。這個腳本一下就解決了問題,也幫助新開發人員熟悉了約定。
譯者圖解把換行約定變成提交門檻
程式碼審查也是執行約定、幫助新開發人員掌握約定的機會。審查者要求越嚴格,團隊成員就越快學會這些約定,程式碼也越整潔。
入鄉隨俗。 最重要的一條約定,是每個開發人員都應遵循這句古老格言:“到了羅馬,就按羅馬人那樣做。”在新的檔案中編寫程式碼時,先看看現有程式碼如何組織:公有變數和方法是否都宣告在私有變數和方法之前?方法是否按字母順序排列?變數名採用 firstServerName 這樣的駝峰命名法,還是 first_server_name 這樣的蛇形命名法?凡是看起來像約定的做法,都應遵循。作設計決策時,也要想想專案其他地方是否可能作過類似決策;如果有,就找到現有範例,在新程式碼中採用相同做法。
不要改變現有約定。 剋制“改進”現有約定的衝動。有一個“更好的想法”並不足以成為引入不一致的理由。 新想法也許確實更好,但保持一致帶來的收益,幾乎總是大於不同做法之間的優劣差距。引入不一致之前,先問兩個問題:你現在是否掌握了制定舊約定時尚無法獲得的重要新資訊,足以支援採用新做法?新做法是否好到值得花時間更新所有舊用法?如果你的組織認可這兩個問題的答案都是“是”,就進行更新,並在完成後徹底消除舊約定的痕跡。不過,其他開發人員仍可能因為不瞭解新約定,在今後重新引入舊做法。總的來說,重新討論已經確立的約定,通常不值得開發人員花時間。
17.3 做過頭了
一致性不僅要求相似的事情采用相似做法,也要求不同的事情采用不同做法。如果過分追求一致,強行對不同事物採用相同方法,例如給確實不同的事物使用相同變數名,或把現有設計模式套在不適合的任務上,就只會增加複雜性和混亂。只有當開發人員確信“如果它看起來像 x,它確實是 x”時,一致性才有益。
譯者圖解外觀一致,還要含義一致
17.4 結論
一致性也體現了投資思維。保持一致需要額外投入:確定約定、編寫自動檢查工具、查詢可供新程式碼參考的類似情況,以及在程式碼審查中幫助團隊成員掌握約定。回報是程式碼更容易理解,開發人員能更快、更準確地看懂程式碼的行為,從而提高工作效率,減少缺陷。