DRY原則

英語名 DRY Principle
読み方 ドライ プリンシプル
難易度
所要時間 即日適用可能
提唱者 アンディ・ハントとデイヴ・トーマス(『達人プログラマー』)
目次

ひとことで言うと
#

同じことを2回書くな。知識やロジックの重複を排除し、1つの場所で管理することで、変更漏れやバグを防ぐプログラミングの基本原則。

押さえておきたい用語
#

押さえておきたい用語
SSOT(Single Source of Truth)
ある情報の唯一の信頼できる情報源のこと。DRY原則の理想形であり、すべての参照先が1つの情報源を指す状態を目指す。
Rule of Three(3回ルール)
同じコードが3回以上繰り返されたら共通化を検討するという実践的な指針のこと。2回の重複では時期尚早な抽象化のリスクがある。
WET(Write Everything Twice)
DRYの対義語として使われる皮肉な表現のこと。同じコードが2箇所以上に存在している状態を指す。
知識の重複(Knowledge Duplication)
コードの見た目ではなく、同じビジネスルールやロジックが複数箇所に存在する状態のこと。DRYは見た目の重複ではなく知識の重複を排除する原則。

DRY原則の全体像
#

DRY原則:知識の重複を排除し一元管理する
WET(重複あり)登録画面: emailチェック実装A編集画面: emailチェック実装B管理画面: emailチェック実装C1箇所直すと他も直す必要あり微妙にルールが違ってバグの温床DRY(一元管理)UserValidator.validateEmail()↑ 唯一の信頼源(SSOT)登録画面 → 参照編集画面 → 参照管理画面 → 参照注意: DRYの対象は「知識の重複」同じ見た目のコードでも、変更理由が違えば重複ではないRule of Three: 3回繰り返されたら共通化を検討過度な抽象化は可読性を下げる。バランスが大事
DRY原則の適用フロー
1
重複を発見
コード・設定・ドキュメントの重複を特定
2
共通部分を抽出
関数・クラス・モジュールに切り出す
3
一元管理
SSOTとして自動生成・参照の仕組みを構築
過度な抽象化を避ける
Rule of Threeで共通化の判断を行う

こんな悩みに効く
#

  • 同じようなコードがあちこちにあり、1箇所直すと他も直さないといけない
  • コピペしたコードの片方だけ修正して、バグが生まれてしまった
  • 仕様変更のたびに影響範囲が把握できない

基本の使い方
#

ステップ1: 重複を見つける

同じ知識やロジックが複数箇所に存在していないか確認する

  • コードの重複だけでなく、設定ファイルやドキュメントの重複も対象
  • コピペしたコードは最もわかりやすい重複のサイン
  • 「似ているが微妙に違う」コードも重複の可能性がある

ポイント: DRYは「コードの見た目」ではなく「知識の重複」を排除する原則。同じ見た目でも意味が違えば重複ではない。

ステップ2: 共通部分を抽出する

重複しているロジックを関数・クラス・モジュールに切り出す

  • 共通のロジックを1つの関数にまとめる
  • 定数や設定値は1箇所で定義して参照する
  • テンプレートやジェネリクスで汎用化できないか検討する

ポイント: 抽出するときは「何が共通で、何が異なるか」を明確にする。異なる部分はパラメータにする。

ステップ3: 一元管理する仕組みを作る

抽出した共通部分を、信頼できる唯一の情報源(Single Source of Truth)にする

  • DB定義からコードを自動生成する
  • APIスキーマからクライアントコードを生成する
  • 環境変数や設定は1つのファイルで管理する

ポイント: 手動の同期は必ず破綻する。自動生成や参照の仕組みを作ること。

具体例
#

例1:バリデーションロジックの重複を排除して変更コストを1/3にする

Before(DRY違反): 登録画面、プロフィール編集画面、管理画面の3箇所で「メールアドレスの形式チェック」と「パスワードの強度チェック」を別々に実装。それぞれ微妙にルールが違ってバグの温床に。

After(DRY適用): UserValidatorクラスにvalidateEmail()validatePassword()を集約。3画面すべてがこのクラスを呼び出す。

効果: パスワードポリシーを「8文字以上→12文字以上」に変更する場合、修正箇所はUserValidator1行だけ。以前は3箇所を修正し、1箇所の修正漏れでバグが発生していた。変更コストが1/3に削減

例2:APIスキーマからクライアントコードを自動生成してドキュメント乖離をゼロにする

Before: REST APIの仕様をSwagger(OpenAPI)で記述し、フロントエンドのTypeScript型定義を手動で作成。APIが変更されるたびに型定義の更新が漏れ、月に平均3件の型不一致バグが発生。

DRY適用: openapi-typescriptを導入。OpenAPIスキーマからTypeScript型定義を自動生成。CIパイプラインでスキーマ変更時に自動で型定義を再生成。

After: API仕様と型定義の乖離が構造的にゼロに。型不一致バグが月3件→0件。新しいAPIエンドポイント追加時も、スキーマを書くだけでフロントの型が自動で生成される。

例3:環境変数の散在をSSOTに統合して設定ミスを排除する

Before: 同じDB接続情報が.envdocker-compose.yml、KubernetesのConfigMap、CIのsecrets4箇所に記載。本番DBのパスワードを変更した際に1箇所の更新漏れがあり、2時間のサービス停止が発生。

DRY適用: HashiCorp VaultをシークレットのSSOTとして導入。すべてのアプリケーションとCIがVaultから直接取得。設定ファイルにはvault://secret/db/passwordのような参照のみ記載。

After: DB接続情報の変更はVaultの1箇所のみ。設定ミスによるサービス停止が年3件→0件に。新しい環境の追加時もVaultの権限設定だけで完了。

やりがちな失敗パターン
#

  1. 見た目の重複だけで共通化する — たまたま同じコードでも、変更理由が異なるなら別物。「なぜ同じか」を考えてから共通化すること
  2. 過度な抽象化で可読性を下げる — 2箇所の重複を消すために複雑な抽象クラスを作り、誰も読めなくなる。**3回以上繰り返されたら共通化(Rule of Three)**が目安
  3. コードだけDRYにしてドキュメントは放置 — コードとドキュメントで同じ情報が二重管理されている。ドキュメントもコードから自動生成する仕組みを検討する
  4. マイクロサービス間で共通ライブラリを乱用する — サービス間の結合度が上がり、独立デプロイが困難になる。サービス間のDRYより、サービスの独立性を優先する

まとめ
#

DRY原則は 「同じ知識を2箇所に書かない」 というシンプルな教え。ただし、見た目の重複と知識の重複は違う。意味のある共通化だけを行い、過度な抽象化は避けること。まずは 「コピペしそうになったら立ち止まる」 という習慣から始めよう。