今回やること
この記事では、重複しているように見えるコードを見つけ、共通化してよいかを判断します。
DRYは、似たコードを全部まとめることではなく、同じ知識を1箇所に置くことです。
前提条件
- JavaScriptまたはTypeScriptの関数が読める
- if文と関数呼び出しが分かる
- 共通化の目的を説明できるようになりたい
Step 1: 重複しているコードを見る
次のコードを見ます。
function calculateCartTotal(price: number) {
const tax = price * 0.1;
return price + tax;
}
function calculateInvoiceTotal(price: number) {
const tax = price * 0.1;
return price + tax;
}
どちらも税率 0.1 を使っています。これは同じ税率ルールという知識が重複しています。
Step 2: 共通化する
税率と計算処理を1箇所にまとめます。
const TAX_RATE = 0.1;
function calculateTaxIncludedPrice(price: number) {
return price + price * TAX_RATE;
}
目的は、コードを短くすることではありません。税率が変わったときに変更箇所を1つにすることです。
Step 3: 共通化しない例を見る
次のコードも似ています。
function validateUserName(name: string) {
return name.length >= 2 && name.length <= 20;
}
function validateProductName(name: string) {
return name.length >= 2 && name.length <= 20;
}
今は同じ条件ですが、ユーザー名と商品名は別々の仕様です。将来、商品名だけ80文字まで許可されるかもしれません。
Step 4: あえて分けておく
function validateUserName(name: string) {
return name.length >= 2 && name.length <= 20;
}
function validateProductName(name: string) {
return name.length >= 2 && name.length <= 20;
}
同じ形でも、変更理由が違うなら分けたままで問題ありません。
Step 5: 判断表で確認する
| 質問 | はいなら |
|---|---|
| 同じ仕様変更で同時に変わるか | 共通化を検討 |
| 名前を具体的に付けられるか | 共通化しやすい |
| 片方だけ変わりそうか | 分けておく |
| 引数や分岐が増えそうか | 共通化を待つ |
迷ったら、すぐ共通化せず、3回目の重複まで待つのも現実的です。
よくあるエラー
| 状況 | 原因 | 対応 |
|---|---|---|
| 共通関数の引数が増え続ける | 別々の責務をまとめている | 分け直す |
関数名が processData になる | 抽象化の目的が曖昧 | 具体名にできるまで待つ |
| 片方の変更で別画面が壊れる | 変更理由が違うコードを共通化した | 利用元ごとに分離する |
| 重複が怖くて何でもまとめる | DRYの誤解 | 重複知識か確認する |
まとめ
重複コードを見つけたら、まず同じ知識か、同じ変更理由かを確認します。似ているだけのコードを急いでまとめると、あとで修正しにくくなります。