ひとことで言うと#
同じことを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原則の全体像#
こんな悩みに効く#
- 同じようなコードがあちこちにあり、1箇所直すと他も直さないといけない
- コピペしたコードの片方だけ修正して、バグが生まれてしまった
- 仕様変更のたびに影響範囲が把握できない
基本の使い方#
同じ知識やロジックが複数箇所に存在していないか確認する。
- コードの重複だけでなく、設定ファイルやドキュメントの重複も対象
- コピペしたコードは最もわかりやすい重複のサイン
- 「似ているが微妙に違う」コードも重複の可能性がある
ポイント: DRYは「コードの見た目」ではなく「知識の重複」を排除する原則。同じ見た目でも意味が違えば重複ではない。
重複しているロジックを関数・クラス・モジュールに切り出す。
- 共通のロジックを1つの関数にまとめる
- 定数や設定値は1箇所で定義して参照する
- テンプレートやジェネリクスで汎用化できないか検討する
ポイント: 抽出するときは「何が共通で、何が異なるか」を明確にする。異なる部分はパラメータにする。
抽出した共通部分を、信頼できる唯一の情報源(Single Source of Truth)にする。
- DB定義からコードを自動生成する
- APIスキーマからクライアントコードを生成する
- 環境変数や設定は1つのファイルで管理する
ポイント: 手動の同期は必ず破綻する。自動生成や参照の仕組みを作ること。
具体例#
Before(DRY違反): 登録画面、プロフィール編集画面、管理画面の3箇所で「メールアドレスの形式チェック」と「パスワードの強度チェック」を別々に実装。それぞれ微妙にルールが違ってバグの温床に。
After(DRY適用): UserValidatorクラスにvalidateEmail()とvalidatePassword()を集約。3画面すべてがこのクラスを呼び出す。
効果: パスワードポリシーを「8文字以上→12文字以上」に変更する場合、修正箇所はUserValidatorの1行だけ。以前は3箇所を修正し、1箇所の修正漏れでバグが発生していた。変更コストが1/3に削減。
Before: REST APIの仕様をSwagger(OpenAPI)で記述し、フロントエンドのTypeScript型定義を手動で作成。APIが変更されるたびに型定義の更新が漏れ、月に平均3件の型不一致バグが発生。
DRY適用: openapi-typescriptを導入。OpenAPIスキーマからTypeScript型定義を自動生成。CIパイプラインでスキーマ変更時に自動で型定義を再生成。
After: API仕様と型定義の乖離が構造的にゼロに。型不一致バグが月3件→0件。新しいAPIエンドポイント追加時も、スキーマを書くだけでフロントの型が自動で生成される。
Before: 同じDB接続情報が.env、docker-compose.yml、KubernetesのConfigMap、CIのsecretsの4箇所に記載。本番DBのパスワードを変更した際に1箇所の更新漏れがあり、2時間のサービス停止が発生。
DRY適用: HashiCorp VaultをシークレットのSSOTとして導入。すべてのアプリケーションとCIがVaultから直接取得。設定ファイルにはvault://secret/db/passwordのような参照のみ記載。
After: DB接続情報の変更はVaultの1箇所のみ。設定ミスによるサービス停止が年3件→0件に。新しい環境の追加時もVaultの権限設定だけで完了。
やりがちな失敗パターン#
- 見た目の重複だけで共通化する — たまたま同じコードでも、変更理由が異なるなら別物。「なぜ同じか」を考えてから共通化すること
- 過度な抽象化で可読性を下げる — 2箇所の重複を消すために複雑な抽象クラスを作り、誰も読めなくなる。**3回以上繰り返されたら共通化(Rule of Three)**が目安
- コードだけDRYにしてドキュメントは放置 — コードとドキュメントで同じ情報が二重管理されている。ドキュメントもコードから自動生成する仕組みを検討する
- マイクロサービス間で共通ライブラリを乱用する — サービス間の結合度が上がり、独立デプロイが困難になる。サービス間のDRYより、サービスの独立性を優先する
まとめ#
DRY原則は 「同じ知識を2箇所に書かない」 というシンプルな教え。ただし、見た目の重複と知識の重複は違う。意味のある共通化だけを行い、過度な抽象化は避けること。まずは 「コピペしそうになったら立ち止まる」 という習慣から始めよう。