跳轉到主要內容
類別: 原則
類型: 軟體開發原則
起源: 軟體工程,1990年代 / 《程式設計師習語》,1999
別名: DRY、不要重複自己、單一真實來源
快速回答 — DRY原則(Don’t Repeat Yourself)指出,每一條知識在一個系統中必須只有一種明確的表現形式。該原則首次在安迪·亨特(Andy Hunt)和戴夫·湯瑪斯(Dave Thomas)1999年出版的《程式設計師習語》中闡述,已成為軟體開發中最有影響力的原則之一。該原則不僅適用於程式碼,還包括文件、資料庫結構、測試和任何其他系統工件。當資訊被重複時,修改需要在多個地方進行,增加了不一致性問題和錯誤的風險。

什麼是DRY原則?

DRY原則是一種軟體開發哲學,主張消除程式碼、文件和其他系統工件中的重複。其核心思想看似簡單卻非常有力量:任何知識片段——無論是業務規則、計算、資料結構還是使用者介面元素——都應該只存在於一個地方。當相同的資訊出現在多個地方時,開發者必須記得更新每個實例,造成持續的維護負擔,並引入錯誤的機會。
「重複是設計良好系統的主要敵人。」 — 安迪·亨特和戴夫·湯瑪斯,《程式設計師習語》
該原則透過《程式設計師習語:從工匠到大師》(1999年)獲得了廣泛認可,這本有影響力的書籍確立了軟體開發的許多最佳實踐。然而,這個概念早在这本书之前——程式設計師早就認識到複製邏輯會造成維護噩夢。亨特和湯瑪斯所做的是清晰地闡述了這個原則,並給了它一個令人難忘的名字。 DRY適用於多種形式的重複。程式碼重複發生在相同邏輯出現在多個地方時。文件重複發生在同一資訊在多個文件中被解釋時。資料重複發生在相同資料儲存在多個位置時。結構重複產生於資料庫結構相互鏡像時。該原則要求開發者為每條知識確定單一權威來源,並建立引用該來源的系統。

DRY原則的三個層次

  • 入門: 在複製貼上程式碼時停下來問:「我可以將其提取為一個可重用的函數或變數嗎?」即使是小規模的重複也會隨著時間累積。
  • 實踐: 在多個層面應用DRY——函數、類別、模組和服務。使用繼承、組合和配置管理等技術來集中知識。
  • 進階: 認識到過度積極的DRY會產生不當的耦合。有時重複比錯誤的抽象更可取。平衡DRY與YAGNI和KISS原則。

起源

DRY原則在安迪·亨特和戴夫·湯瑪斯1999年出版的《程式設計師習語:從工匠到大師》中正式介紹。這本成為軟體開發文獻基石的書籍將DRY描述為建立可維護軟體的核心原則。亨特和湯瑪斯認為,重複導致系統更難理解、修改和擴展。 該原則建立在軟體工程的早期概念之上。資料庫設計中「單一真實來源」的概念早於DRY,像在一個地方定義常數並在整個程式碼中參照它們的做法也是如此。DRY具有影響力的原因是它在所有知識重複形式中的廣泛應用,不僅在程式碼中,還包括文件、流程和組織結構。 DRY流行的時機意義重大。1990年代後期見證了大型軟體系統的增長,開發者越來越面臨重複程式碼庫的維護挑戰。DRY為做出設計決策提供了清晰的啟發式方法,這些決策將在系統的整個生命週期中受益。今天,DRY仍然是電腦科學課程和專業開發團隊遵循的基礎原則。

核心要點

1

單一真實來源

每條資訊應該只存在於一個地方。當資訊需要更改時,應該只有一個位置要更新,消除不一致的風險。
2

減少維護負擔

重複的程式碼需要重複的維護。錯誤修復、安全更新和功能更改必須一致地應用於每個副本,增加工作量風險。
3

提高一致性

當知識存在於一個地方時,所有消費者都參照相同的權威來源,確保整個系統的一致行為。
4

實現更好的抽象

識別重複迫使開發者思考程式碼的本質,通常導致更好的抽象和更優雅的設計。

應用場景

程式碼重構

將重複的邏輯提取到可重用的函數、類別或模組中。使用繼承或組合來共享行為而不重複實現。

配置管理

將配置值儲存在集中式檔案或環境變數中。避免硬編碼可能在不同環境中更改的值。

資料庫設計

標準化資料庫結構以消除冗餘資料儲存。使用外鍵和連接,而不是在表之間複製資料。

文件編寫

編寫一次解釋概念並在整個過程中參照該說明的文件。避免在多個地方重複相同的資訊。

經典案例

Ruby on Rails 框架著名地體現了DRY原則。Rails 引入了「約定優於配置」的概念,通用模式被定義一次並自動應用於整個應用程式。例如,Rails 中的模型定義自動生成資料庫存取方法——相同的邏輯不會在多個地方重複。當 Rails 開發者需要更改模型與資料庫的互動方式時,他們在一個地方進行更改,它會傳播到整個應用程式。這種方法使 Rails 應用程式的維護和修改變得非常容易,開發者報告稱,與不太強調 DRY 的框架相比,重複程式碼明顯更少。

邊界與失效場景

DRY原則雖然至關重要,但有重要的局限性。首先,過度熱情的DRY會產生不當的抽象。將不相關的概念強制放入共享程式碼會造成緊密耦合,使原始程式碼和「重構」版本都更難維護。 其次,過早的抽象是有風險的。DRY應該指導已證實重複的重構,而不是啟發投机性泛化。為可能有一天會被重用的程式碼建立抽象通常會導致複雜、難以理解的系統。 第三,有些重複是可以接受的——甚至是必要的。看起來相似的程式碼可能有不同的存在原因,強制它們在一起會造成虛假的統一性。測試程式碼經常因為正當理由從生產程式碼中複製結構:測試必須能夠獨立維護。

常見誤區

DRY是關於避免知識重複,而不是字面上的程式碼。有時最清晰的解決方案涉及重複語法,而底層知識保持單一來源。
錯誤的抽象會使維護變得更難。在提取重複之前,確保抽象準確地代表共享概念。
該原則擴展到文件、資料庫結構、API 設計和組織流程。任何重複的知識都是 DRY 處理的候選對象。

相關概念

KISS原則

DRY 通常簡化程式碼,使其更容易理解。KISS 透過強調簡單性來補充 DRY,指導如何消除重複。

YAGNI原則

不要建立可重用的元件,直到你需要它們。YAGNI 防止違反 DRY 精神的過早抽象。

單一真實來源

一個相關的資料庫概念,資料應該儲存在一個地方。DRY 是將這個想法應用到系統中所有知識的方式。

程式碼重構

改進程式碼結構的實踐,通常透過應用 DRY。重構是實現 DRY 的操作活動。

奧卡姆剃刀

兩個原則都偏向簡單性。DRY 消除重複,而奧卡姆剃刀消除不必要的假設。

一句話總結

不要重複自己——重複造成維護噩夢,因此將共享知識提取為所有系統部分參照的單一權威來源。