> ## Documentation Index
> Fetch the complete documentation index at: https://meta.niceshare.site/llms.txt
> Use this file to discover all available pages before exploring further.

# DRY原則

> DRY原則（不要重複自己）倡導消除程式碼和文件中的重複。了解其起源、應用場景以及DRY如何提高可維護性。

<Info>
  **類別**: 原則<br />
  **類型**: 軟體開發原則<br />
  **起源**: 軟體工程，1990年代 / 《程式設計師習語》，1999<br />
  **別名**: DRY、不要重複自己、單一真實來源
</Info>

<Note>
  **快速回答** — DRY原則（Don't Repeat
  Yourself）指出，每一條知識在一個系統中必須只有一種明確的表現形式。該原則首次在安迪·亨特（Andy
  Hunt）和戴夫·湯瑪斯（Dave
  Thomas）1999年出版的《程式設計師習語》中闡述，已成為軟體開發中最有影響力的原則之一。該原則不僅適用於程式碼，還包括文件、資料庫結構、測試和任何其他系統工件。當資訊被重複時，修改需要在多個地方進行，增加了不一致性問題和錯誤的風險。
</Note>

## 什麼是DRY原則？

DRY原則是一種軟體開發哲學，主張消除程式碼、文件和其他系統工件中的重複。其核心思想看似簡單卻非常有力量：任何知識片段——無論是業務規則、計算、資料結構還是使用者介面元素——都應該只存在於一個地方。當相同的資訊出現在多個地方時，開發者必須記得更新每個實例，造成持續的維護負擔，並引入錯誤的機會。

> 「重複是設計良好系統的主要敵人。」 — 安迪·亨特和戴夫·湯瑪斯，《程式設計師習語》

該原則透過《程式設計師習語：從工匠到大師》（1999年）獲得了廣泛認可，這本有影響力的書籍確立了軟體開發的許多最佳實踐。然而，這個概念早在这本书之前——程式設計師早就認識到複製邏輯會造成維護噩夢。亨特和湯瑪斯所做的是清晰地闡述了這個原則，並給了它一個令人難忘的名字。

DRY適用於多種形式的重複。程式碼重複發生在相同邏輯出現在多個地方時。文件重複發生在同一資訊在多個文件中被解釋時。資料重複發生在相同資料儲存在多個位置時。結構重複產生於資料庫結構相互鏡像時。該原則要求開發者為每條知識確定單一權威來源，並建立引用該來源的系統。

### DRY原則的三個層次

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

## 起源

DRY原則在安迪·亨特和戴夫·湯瑪斯1999年出版的《程式設計師習語：從工匠到大師》中正式介紹。這本成為軟體開發文獻基石的書籍將DRY描述為建立可維護軟體的核心原則。亨特和湯瑪斯認為，重複導致系統更難理解、修改和擴展。

該原則建立在軟體工程的早期概念之上。資料庫設計中「單一真實來源」的概念早於DRY，像在一個地方定義常數並在整個程式碼中參照它們的做法也是如此。DRY具有影響力的原因是它在所有知識重複形式中的廣泛應用，不僅在程式碼中，還包括文件、流程和組織結構。

DRY流行的時機意義重大。1990年代後期見證了大型軟體系統的增長，開發者越來越面臨重複程式碼庫的維護挑戰。DRY為做出設計決策提供了清晰的啟發式方法，這些決策將在系統的整個生命週期中受益。今天，DRY仍然是電腦科學課程和專業開發團隊遵循的基礎原則。

## 核心要點

<Steps>
  <Step title="單一真實來源">
    每條資訊應該只存在於一個地方。當資訊需要更改時，應該只有一個位置要更新，消除不一致的風險。
  </Step>

  <Step title="減少維護負擔">
    重複的程式碼需要重複的維護。錯誤修復、安全更新和功能更改必須一致地應用於每個副本，增加工作量風險。
  </Step>

  <Step title="提高一致性">
    當知識存在於一個地方時，所有消費者都參照相同的權威來源，確保整個系統的一致行為。
  </Step>

  <Step title="實現更好的抽象">
    識別重複迫使開發者思考程式碼的本質，通常導致更好的抽象和更優雅的設計。
  </Step>
</Steps>

## 應用場景

<CardGroup cols={2}>
  <Card title="程式碼重構">
    將重複的邏輯提取到可重用的函數、類別或模組中。使用繼承或組合來共享行為而不重複實現。
  </Card>

  <Card title="配置管理">
    將配置值儲存在集中式檔案或環境變數中。避免硬編碼可能在不同環境中更改的值。
  </Card>

  <Card title="資料庫設計">
    標準化資料庫結構以消除冗餘資料儲存。使用外鍵和連接，而不是在表之間複製資料。
  </Card>

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

## 經典案例

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

## 邊界與失效場景

DRY原則雖然至關重要，但有重要的局限性。首先，過度熱情的DRY會產生不當的抽象。將不相關的概念強制放入共享程式碼會造成緊密耦合，使原始程式碼和「重構」版本都更難維護。

其次，過早的抽象是有風險的。DRY應該指導已證實重複的重構，而不是啟發投机性泛化。為可能有一天會被重用的程式碼建立抽象通常會導致複雜、難以理解的系統。

第三，有些重複是可以接受的——甚至是必要的。看起來相似的程式碼可能有不同的存在原因，強制它們在一起會造成虛假的統一性。測試程式碼經常因為正當理由從生產程式碼中複製結構：測試必須能夠獨立維護。

## 常見誤區

<AccordionGroup>
  <Accordion title="DRY意味著永遠不複製程式碼">
    DRY是關於避免知識重複，而不是字面上的程式碼。有時最清晰的解決方案涉及重複語法，而底層知識保持單一來源。
  </Accordion>

  <Accordion title="DRY總是提高可維護性">
    錯誤的抽象會使維護變得更難。在提取重複之前，確保抽象準確地代表共享概念。
  </Accordion>

  <Accordion title="DRY只適用於程式碼">
    該原則擴展到文件、資料庫結構、API 設計和組織流程。任何重複的知識都是 DRY
    處理的候選對象。
  </Accordion>
</AccordionGroup>

## 相關概念

<CardGroup cols={3}>
  <Card title="KISS原則">
    DRY 通常簡化程式碼，使其更容易理解。KISS 透過強調簡單性來補充
    DRY，指導如何消除重複。
  </Card>

  <Card title="YAGNI原則">
    不要建立可重用的元件，直到你需要它們。YAGNI 防止違反 DRY 精神的過早抽象。
  </Card>

  <Card title="單一真實來源">
    一個相關的資料庫概念，資料應該儲存在一個地方。DRY
    是將這個想法應用到系統中所有知識的方式。
  </Card>

  <Card title="程式碼重構">
    改進程式碼結構的實踐，通常透過應用 DRY。重構是實現 DRY 的操作活動。
  </Card>

  <Card title="奧卡姆剃刀">
    兩個原則都偏向簡單性。DRY 消除重複，而奧卡姆剃刀消除不必要的假設。
  </Card>
</CardGroup>

## 一句話總結

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