第8章:DRYの落とし穴(やりすぎ注意!)🐙⚠️
(=「共通化したのに、逆に読めない😭」を防ぐ章だよ〜!)
8-0. この章のゴール🎯💖
この章を終えると…
- 「共通化すべき重複」と「残すべき重複」を見分けられる👀✨
- “やりすぎDRY”のサインを、コード見てすぐ気づける🚨
- 共通化する前にチェックする「判断チェックリスト📋」を自分で回せる🧠✨
8-1. まず大事な誤解をほどくね🧻💡
DRYって「同じコードを1行たりとも書くな!」じゃなくて、**“同じ知識(ルール)を複数に置かない”**が本体だよ〜📚✨ (ウィキペディア)
だから、コードが似てても “ルールが別” なら、無理に1つにしない方が安全なことがあるの🥺🫶 逆に、見た目が違っても “同じルール” なら、1か所に寄せた方が安全だったりするよ!
8-2. DRYのやりすぎで起きる「あるある地獄」😵💫🕳️
ここからが本題!「共通化しすぎ」で起きる事故、超よくあるやつ👇
あるある①: “たまたま似てるだけ” を統一して崩壊💥

- 例:送料計算と割引計算が「%っぽい」からって同じ関数にまとめる
- 結果:条件分岐が増えまくって、読めない・直せない😇
あるある②:万能utilsが巨大化して迷子🗺️🐙

utils.tsに何でも入る- いつの間にか 神(God)オブジェクト/クラスっぽくなる😱 (ウィキペディア)
あるある③:共通化のための引数が増えすぎる🎛️😵
optionsが10個isFoo,shouldBarみたいなフラグ地獄- 呼び出し側が「結局これ何してるの?」ってなる
あるある④:型でDRYしようとして型パズル🧩🌀
- ジェネリクス + 条件型 + mapped type が合体
- 未来の自分(と仲間)が詰む😭 (TypeScriptは最新でも強いけど、強い=複雑にしやすい、でもあるの…! (npmjs.com))
8-3. “やりすぎDRY” を見抜く7つのサイン🚨👀
共通化した関数(or モジュール)が、こうなってきたら黄色信号だよ〜⚠️
- 名前がぼんやりしてきた
process()/handle()/doThing()とか🫠
- 引数が増え続ける(3〜4個を超えて増殖)
- booleanフラグが増える(
isX,useY,enableZ) - if/switchが増える(共通化した中で分岐が増殖)
- 呼び出し側が読みにくい(何が起きるか分からない)
- 修正すると別機能が壊れる(関係ないものが巻き込まれる)
- **「これ将来もっと分かれる予感」**がする(勘、大事🥺✨)
8-4. 判断のコアはこれだけ💎(3つの質問)
共通化する前に、まずこの3問だけは自分に聞いてね☺️🫶
Q1. 「同じルール?」それとも「似てるだけ?」🤔
-
例:
- “割引” と “送料” はどっちも金額をいじるけど、ルール(知識)が別なことが多い
Q2. 「変更理由」は同じ?🧭
- 変更理由が同じなら、寄せる価値が高い✨
- 変更理由が違うなら、寄せるほど事故る💥
Q3. それ、共通化したら呼び出し側が読みやすい?📖
- 共通化して 中だけキレイでも、 呼び出し側が 呪文になるなら負け😭
8-5. 迷ったら「Rule of Three」+「AHA」でOK🙆♀️✨
✅ Rule of Three(3回出たら考える)
「2回は様子見、3回目で抽象化を検討」みたいな目安だよ〜🧠 (ウィキペディア)
✅ AHA(Avoid Hasty Abstractions:早すぎる抽象化を避けよ)💡
「似てるっぽい」で急いでまとめず、“必要性が叫び出すまで”ちょい待つ考え方だよ! (Kent C. Dodds)
8-6. 例で体感しよ!「悪いDRY」「良いDRY」🧪✨
例1:「似てるから統一」→ 分岐地獄 😇
❌ “悪いDRY” 例(統一しすぎ)
type Mode = "discount" | "shipping";
function calcAmount(base: number, mode: Mode, options: {
percent?: number;
min?: number;
max?: number;
freeShippingOver?: number;
}) {
if (mode === "discount") {
const p = options.percent ?? 0;
const discounted = base - base * (p / 100);
return Math.max(options.min ?? 0, Math.min(options.max ?? discounted, discounted));
}
// shipping
if (options.freeShippingOver != null && base >= options.freeShippingOver) return 0;
return Math.max(options.min ?? 0, options.max ?? base);
}
見た目は「1つにまとまった」けど…
- modeで分岐
- optionsが増殖
- 送料と割引のルールが混ざる → 未来に変更が来たらほぼ詰む😭
✅ “良いDRY” 例(ルール単位で分ける)
function calcDiscountedPrice(base: number, percent: number) {
return base - base * (percent / 100);
}
function calcShippingFee(subtotal: number, freeOver: number, standardFee: number) {
return subtotal >= freeOver ? 0 : standardFee;
}
- ルールが別なら、関数も別でいいの😊✨
- 共通化は「同じ知識」のところだけにするのがコツ!
例2:「万能utils」→ 神になって終わる🐙
❌ ありがち
utils.tsにformatDate,calcTax,fetchJson,sleep,parseCsv… → 便利だけど、どんどん増えて探せない🫠
✅ コツ(超シンプルでOK)
-
用途でフォルダを分ける(例:
domain/,ui/,infra/みたいに) -
もしくは最小で
money/(金額ルール)date/(日付)http/(通信) みたいに“話題ごと”に分ける✨ (神オブジェクト化はアンチパターンとして有名だよ〜(ウィキペディア))
例3:型でDRYしすぎて読めない🧩😭
❌ “型の共通化” が目的化するとこうなる
- 「全部Genericでいけるよね?」
- 「条件型で自動推論させよ!」 → 数週間後、誰も直せない型パズル完成🎉(うれしくない)
✅ ルール
- “型の再利用”は、読める範囲でやる
- 迷ったら、型は少し重複してもOK(AHAの気持ち💡 (Kent C. Dodds))
8-7. VS Codeで「安全にDRYを試す」小ワザ🛟✨
共通化って、怖いのは「戻せない」ことだよね🥺 でもVS Codeには、リファクタ支援があるよ〜!
- Extract(関数/定数):選択 → 電球💡(または
Ctrl + .) - Rename Symbol:
F2で名前を安全に変更 (VS Codeのリファクタ機能として紹介されてるよ (Visual Studio Code))
※そして、Gitでコミットを小さく切ると最強🫶(戻せる安心感)
8-8. AI(Copilot/Codex等)で“やりすぎ”を検査する🤖🔍
AIは共通化アイデア出すの得意だけど、やりすぎ案も平気で出すよ😂 だから、こう聞くのがコツ!
そのまま使えるプロンプト例🪄
- 「この共通化、Wrong Abstractionになりそうな点ある?」
- 「呼び出し側の可読性が落ちてない?具体例で評価して」
- 「引数が増えた理由を“変更理由”で説明して。説明できなかったら分割案を出して」
- 「Rule of Three的に、今は抽象化すべき?まだ複製のまま?理由付きで」
Copilotにも“リファクタの相談”用のガイドがあるよ (GitHub Docs)
8-9. ここで作るもの:判断チェックリスト📋✨(保存版)
共通化の前に、これを上から順に✅してね!
✅ DRY判断チェックリスト(ミニ版)
-
⬜ これは 同じ知識(ルール)?(見た目が似てるだけじゃない?) (ウィキペディア)
-
⬜ 変更理由は同じ?(誰が・いつ・なぜ変える?)
-
⬜ 呼び出し側は読みやすい?(呪文になってない?)
-
⬜ 分岐やフラグが増えそう?(増えそうなら分ける)
-
⬜ 今はまだ2回目?(3回目まで待つのもアリ) (ウィキペディア)
-
⬜ 共通化した結果、引数や条件分岐が増えてない?
- 増えてたら「不適切な抽象化」かも…! (Sandi Metz)
-
⬜ “万能utils” に押し込めてない?(神化の入口) (ウィキペディア)
8-10. ミニ演習(15〜25分)🧁✨
お題:どっちを選ぶ?(共通化 or 残す)
次の2つ、あなたならどうする?🥺
ケースA:ほぼ同じに見える
- 商品の割引(クーポン%)
- 会員割引(会員ランク%)
👉 質問:「%で引く」って同じだけど、ルールは同じ?
- クーポンは仕様変更されがち、会員割引は固定かも…?
- 変更理由が違うなら、分けた方が楽なことあるよ💡
ケースB:見た目は違うけど同じ知識っぽい
- 画面Aと画面Bで「ステータス表示の文言」が違う書き方で散らばってる 👉 質問:“ステータス文言ルール”は同じ?
- 同じなら「辞書(Record)+型」で1か所に寄せるのがDRY✨
8-11. まとめ🎀✨
- DRYは「コードを1つに」じゃなくて「知識(ルール)を1つに」だよ (ウィキペディア)
- 迷ったら Rule of Three と AHA で落ち着いてOK🫶 (ウィキペディア)
- 共通化が “分岐・フラグ・引数増殖” を呼び始めたら、いったん戻す勇気も正解🙆♀️ (Sandi Metz)
次は第9章で、わざとちょいWETな状態から「DRY改善を1周」するまとめプロジェクトに入ると、判断力が一気に育つよ〜🎯💖