DRY 原則
Don't Repeat Yourself の略で、知識の重複を排除し、単一の正を維持する設計原則
設計設計原則
DRY 原則とは
DRY (Don't Repeat Yourself) は、Andy Hunt と Dave Thomas が『達人プログラマー』(1999 年) で提唱した原則で、「すべての知識はシステム内で唯一の、曖昧さのない、正式な表現を持つべき」とする。単なるコードの重複排除ではなく、知識の重複を排除する原則。
コードの重複 vs 知識の重複
// ❌ コードが同じだが、知識は異なる (DRY 違反ではない)
function validateAge(age: number) { return age >= 0 && age <= 150; }
function validateQuantity(qty: number) { return qty >= 0 && qty <= 150; }
// 年齢と数量は別の知識。たまたま同じ条件でも共通化すべきでない
// ❌ コードは異なるが、知識が重複 (DRY 違反)
const TAX_RATE = 0.1; // config.ts
const tax = price * 0.1; // order.ts ← 0.1 がハードコード
DRY の適用例
// ❌ 知識の重複: バリデーションルールが 2 箇所に
// フロントエンド
if (name.length < 1 || name.length > 50) { ... }
// バックエンド
if (name.length < 1 || name.length > 50) { ... }
// ✅ 共通の定義を共有
// shared/validation.ts
export const NAME_RULES = { minLength: 1, maxLength: 50 } as const;
DRY の過剰適用 (WET)
// ❌ 過剰な DRY: 無理に共通化して複雑に
function processEntity(type: 'user' | 'order' | 'product', data: any) {
if (type === 'user') { /* ... */ }
else if (type === 'order') { /* ... */ }
else if (type === 'product') { /* ... */ }
}
// 3 つの異なるロジックを 1 つの関数に押し込んでいる
// ✅ 適切な分離
function processUser(data: UserData) { /* ... */ }
function processOrder(data: OrderData) { /* ... */ }
DRY vs WET vs AHA
DRY は知識の重複を排除する原則だが、WET (Write Everything Twice) は 2 回までの重複を許容し、AHA (Avoid Hasty Abstractions) は早すぎる抽象化を避ける。3 つの原則はバランスの問題で、DRY を過度に追求すると不自然な抽象化が生まれる。
DRY の適用範囲
| 対象 | 例 |
|---|---|
| ビジネスルール | 税率、バリデーション |
| 設定値 | 環境変数、定数 |
| スキーマ定義 | TypeScript の型から JSON Schema を生成 |
| IaC | CloudFormation の Mappings, Conditions |
CloudFormation での DRY
Mappings:
EnvConfig:
dev:
LogLevel: DEBUG
prod:
LogLevel: WARN
# 1 箇所で定義、複数箇所で参照
Environment:
Variables:
LOG_LEVEL: !FindInMap [EnvConfig, !Ref Environment, LogLevel]
DRY 原則を扱う関連書籍も多い。