DRY原則を適用すべきではないとき
DRY(Don't Repeat Yourself)原則の過度な適用や安易な共通化に関する「明確な基準」は、具体的な状況や文脈に依存するため、すべてのケースに適用できる単一の絶対的な基準は存在しません。
しかし、DRY原則の提唱者やソフトウェア設計の専門家は、その限界と適切な適用について、いくつかの判断軸や条件を提示しています。これは、あなたが感じている「後のことや目的、ドメインを考える」といった曖昧な指針を、より具体的にするためのものです。
判断基準を以下にまとめます。
1. DRY原則の本来の意図と限界
考え方
DRY原則の提唱者であるアンディ・ハントとデイブ・トーマスは、著書 『達人プログラマー ――システム開発の真髄』 において、この原則を次のように定義しています。
「システム内の知識のあらゆる断片は、単一の、曖昧さのない、権威ある表現をもたなければならない」
ここで重要なのは、「知識の断片 (knowledge)」 の重複を避けるべきだということです。
避けるべき「誤ったDRY」
過度な共通化が問題となるのは、「知識」ではなく、「たまたま同じ形をしたコードの行」 を機械的に共通化してしまう場合です。
-
異なる知識・異なる変更理由 (Concern) の共通化:
- 例: ユーザーの表示形式 に関するロジックと、ユーザーの 認証 に関するロジックがたまたま同じ文字列操作を使っていたからといって共通化すると、それぞれの機能の変更理由(表示形式の変更や認証方式の変更)が異なるため、片方の修正が予期せずもう一方に影響を及ぼし、保守性が低下します。
- この場合、コードの見た目は似ていても、それが表す 「知識」 は別物です。
2. DRY原則適用のための明確な判断基準
過度な共通化を避けるための判断基準は、主に変更の理由(変更容易性) と 知識の性質 に基づきます。
| 基準 | 詳細な質問(条件分岐) | 適用すべきアクション |
|---|---|---|
| A. 知識の一致性 | 2つのコードが 「たまたま同じ処理をしている」 のではなく、「本質的に同じ知識・概念」 を表現しているか? | YES → DRYを適用し、共通化を検討する。 |
| B. 変更理由の独立性 | 2つのコードの一方だけを 修正する可能性 があるか? (将来、片方が別の振る舞いをする可能性があるか?) | YES → 安易な共通化は避ける(違反する)。 |
| C. ドメインの一貫性 | 2つのコードが 同じドメイン(関心事、責務) に属しているか? (単一責任の原則 (SRP) に反していないか?) | NO → 共通化は避ける。 |
| D. コスト vs. メリット | 共通化することによる 将来の修正コスト (影響範囲の増大、認知負荷)が、現時点のコード量削減メリット を上回らないか? | 上回る (コスト高) → 共通化は避ける。 |
重要な補足: A-B-C の関係
DRY原則の限界を考える際、多くの専門家が基準として言及するのは、「知識の一致性」 と 「変更理由の独立性」 です。
- 知識の断片が同一 であること (基準A: DRYが推奨される状態)。
- その断片が将来も同じ理由で、同時に変更される可能性が高いこと (基準B: 変更理由が独立していないこと)。
- その断片が 単一の責務 を果たしていること (基準C: 凝集度 が高いこと)。
これらの条件が揃っている場合に限り、共通化は技術的負債ではなく、保守性の向上 に繋がります。
3. 具体的な解決策: WETの適切な活用
過度な共通化の解決策は、曖昧な共通化を避けるという意味で、一時的に WET (Write Everything Twice/We Enjoy Typing)、つまり 「重複を許容する」 アプローチを取ることです。
段階的な抽象化の推奨
初めからDRYを厳密に追求せず、まずは具体的な実装を行い、コードが 成熟し、真の重複(変更理由が同じ「知識の重複」)が明確になった段階で 抽象化や共通化を進める 「段階的な抽象化」 が多くのプログラマーから推奨されています(『達人プログラマー』でも、コードの削除や抽象化は「リファクタリング」の一部として、段階的に行うことが推奨されています)。
このアプローチは、基準B(変更理由の独立性)の不確実性を下げ、技術的負債を最小限に抑える上で有効です。
簡潔に言えば「似ているが、将来変わる可能性が別々であるロジック」は、迷ったらDRYせず、いったん重複させておく方が良い結果を生むことが多いです。
Discussion