軟件設計的哲學:第十七章 一致性

一致性是降低系統複雜性和使其行爲更加明顯的強大工具。如果一個系統是一致的,這意味着相似的事情以相似的方式完成,而不同的事情以不同的方式完成。 一致性創造了認知槓桿:一旦你學會了在一個地方如何做某件事,你就可以利用這些知識立即理解其他使用相同方法的地方。如果系統沒有以一致的方式實現,開發人員必須分別瞭解每種情況。這需要更多的時間。

一致性可以減少錯誤。 如果一個系統是不一致的,兩種情況可能看起來是相同的,但實際上它們是不同的。開發人員可能會看到一個看起來很熟悉的模式,並根據之前遇到的模式做出錯誤的假設。另一方面,如果系統是一致的,基於熟悉的情況做出的假設將是安全的。一致性使開發人員工作更快,錯誤更少。

17.1一致性的例子

一致性可以應用於系統的多個級別。這裏有幾個例子:
命名: 第14章已經討論了以一致的方式使用名稱的好處。

編碼風格: 現在開發組織通常有樣式指南,它將程序結構限制在編譯器強制執行的規則之外。現代風格指南解決了一系列問題,比如縮進、大括號放置、聲明順序、命名、註釋和對被認爲是危險的語言特性的限制。樣式指南使代碼更容易閱讀,並可以減少某些類型的錯誤。

接口: 具有多個實現的接口是一致性的另一個例子。一旦您理解了接口的一個實現,任何其他實現都會變得更容易理解,因爲您已經知道它必須提供的特性。

設計模式: 設計模式是某些常見問題的普遍接受的解決方案,例如用戶界面設計的模型-視圖-控制器方法。如果您可以使用現有的設計模式來解決這個問題,那麼實現將會進行得更快,更有可能工作,而且您的代碼對讀者來說也更容易理解。設計模式將在第19.5節中詳細討論。

不變量: 不變量是變量或結構的一個總是爲真的屬性。例如,存儲文本行的數據結構可能強制一個不變式,即每行以換行字符結束。不變量減少了必須在代碼中考慮的特殊情況的數量,使對代碼的行爲進行推理變得更容易。

17.2 確保一致性

一致性很難保持,特別是當許多人長時間從事一個項目時。一組人可能不知道另一組人建立的慣例。新來者不知道這些規則,所以他們無意中違反了這些約定,並創建了與現有約定衝突的新約定。以下是一些建立和保持一致性的建議:

文檔: 創建一個文檔,列出最重要的總體約定,比如編碼風格指南。將文檔放置在開發人員可能看到的位置,例如項目Wiki上的顯眼位置。鼓勵新加入團隊的人閱讀文檔,並鼓勵現有的人每隔一段時間就閱讀一次。各種組織的一些風格指南已經在網上發佈;考慮從其中之一開始。

對於更本地化的約定(如不變量),請在代碼中找到適當的位置來記錄它們。如果你不把這些慣例寫下來,其他人就不太可能遵循它們。

強制規約: 即使有很好的文檔,開發人員也很難記住所有的約定。執行約定的最佳方法是編寫一個檢查違規的工具,並確保代碼不能提交到存儲庫,除非它通過了檢查器。自動檢查器對於低級語法約定特別有效。

我最近的一個項目有行終止字符的問題。一些開發人員在Unix上工作,行被換行終止;其他的工作在Windows上,行通常由一個carriage-return後跟一個換行來結束。如果一個系統上的開發人員對先前在另一個系統上編輯過的文件進行了小的編輯,那麼編輯器有時會將所有行終止符替換爲適合該系統的行終止符。這給人的感覺是文件的每一行都被修改了,這使得跟蹤有意義的更改變得很困難。我們建立了一個約定,即文件應該只包含換行,但是很難確保每個開發人員使用的每個工具都遵循這個約定。每當一個新的開發人員加入這個項目,我們就會經歷一連串的線路終止問題,而那個開發人員就會適應這個約定。

我們最終通過編寫一個簡短的腳本解決了這個問題,這個腳本在將更改提交到源代碼存儲庫之前自動執行。該腳本檢查所有已修改的文件,如果其中任何一個包含回車,則將中止提交。該腳本還可以手動運行,以修復損壞的文件,方法是用換行替換載波返回/換行序列。

這立即消除了問題,並幫助培訓了新的開發人員。

代碼審查爲執行約定和對新開發人員進行約定教育提供了另一個機會。 代碼評審人員越是吹毛求疵,團隊中的每個人就會越快地瞭解約定,代碼就會越乾淨。

入鄉隨俗: 最重要的慣例是,每個開發人員都應該遵循這句古老的格言“入鄉隨俗”。在處理新文件時,請查看現有代碼的結構。是否所有的公共變量和方法都在私有變量和方法之前聲明?這些方法是按字母順序排列的嗎?變量在firstServerName中使用“camel case”還是在first_server_name中使用“snake case”?當你看到任何看起來可能是約定的東西時,跟着它走。在做設計決策時,問問自己是否在項目的其他地方也做了類似的決策;如果是,找到一個現有的示例,並在新代碼中使用相同的方法。

不要改變現有的慣例 抵制“改進”現有公約的衝動。有一個“更好的主意”並不足以成爲產生矛盾的藉口。你的新想法可能確實更好,但是一致性對不一致性的價值幾乎總是大於一種方法對另一種方法的價值。在引入不一致的行爲之前,問自己兩個問題。首先,您是否有重要的新信息來證明您的方法是正確的,而這在舊的約定建立時是沒有的?第二,新方法是否更好,值得花時間更新所有舊的用法?如果您的組織認爲這兩個問題的答案都是“是”,那麼就繼續進行升級;當你完成的時候,應該沒有任何舊的慣例的跡象。但是,您仍然面臨其他開發人員不知道新約定的風險,因此他們可能在將來重新引入舊的方法。總的來說,重新考慮已建立的約定很少能很好地利用開發人員的時間。

17.3 別做過了頭

一致性不僅意味着相似的事情應該以相似的方式去做,還意味着不同的事情應該以不同的方式去做。如果您過於熱衷於一致性,並試圖強制將不同的東西放在相同的方法中,例如對真正不同的東西使用相同的變量名,或者對不適合該模式的任務使用現有的設計模式,那麼您將創建複雜性和混亂。只有當開發人員確信“如果它看起來像x,那麼它實際上就是x”時,一致性纔會帶來好處。

17.4 結論

一致性是投資心態的另一個例子。確保一致性需要一些額外的工作:決定約定的工作、創建自動檢查器的工作、尋找類似的情況以在新代碼中模擬的工作,以及在代碼評審中培訓團隊的工作。 這種投資的回報是您的代碼將更加明顯。開發人員將能夠更快、更準確地理解代碼的行爲,這將使他們工作得更快,bug更少。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章