【14日目】『リーダブルコード』を意識してJavascriptをリファクタリングしてみた
技術ブログ14日目。
本日は、Javascriptの読みやすさを追求します。
〇課題
ECサイトの配送手数料計算プログラム
配送先(国内・海外)や配送プラン(通常・急ぎ)に応じて手数料を計算する処理です。
条件分岐が複雑に絡み合っており、新しい地域やプランを追加しようとすると既存のコードを壊しかねない「拡張しにくい」状態です。
〇修正前コード(動くけれど読みにくいコード)
// 課題コード
function getFee(area, plan, weight) {
let fee = 0;
if (area === "domestic") {
if (plan === "standard") {
fee = 500;
} else if (plan === "express") {
fee = 800;
}
} else if (area === "international") {
if (plan === "standard") {
fee = 2000;
} else if (plan === "express") {
fee = 3000;
}
}
// 重量が5kgを超える場合は一律500円追加
if (weight > 5) {
fee += 500;
}
return fee;
}
// 実行例
console.log(getFee("domestic", "standard", 2)); // 500
〇リファクタリングの指針
名著『リーダブルコード』の以下の原則を意識しました。
「条件分岐」を「データ」に置き換え:
if-else の羅列を、Lookup Table(検索表)による管理に移行。
マジック文字列の定数化:
"domestic" などの文字列を直接書かず、意味のある定数に集約。
巨大な式の分割:
基本料金の決定と、追加料金の計算を明確に分離。
例外処理の先行検討(ガード節):
未対応のエリアやプランが渡された際、即座にエラーを返して後続のロジックを保護。
〇修正後コード
// 1. マジック文字列を定数化
const AREA = {
DOMESTIC: "domestic",
INTERNATIONAL: "international",
};
const PLAN = {
STANDARD: "standard",
EXPRESS: "express",
};
// 2. 料金体系を「データ」として定義
const FEE_TABLE = {
[AREA.DOMESTIC]: {
[PLAN.STANDARD]: 500,
[PLAN.EXPRESS]: 800,
},
[AREA.INTERNATIONAL]: {
[PLAN.STANDARD]: 2000,
[PLAN.EXPRESS]: 3000,
},
};
const WEIGHT_LIMIT = 5;
const OVER_WEIGHT_SURCHARGE = 500;
/**
* 配送手数料を計算する
*/
function getShippingFee(area, plan, weight) {
// 3. ガード節:未対応のエリアやプランを早期に除外
const areaFees = FEE_TABLE[area];
if (!areaFees) {
throw new Error(`未対応の配送エリアです: ${area}`);
}
const baseFee = areaFees[plan];
if (baseFee === undefined) {
throw new Error(`未対応の配送プランです: ${plan}`);
}
// 4. 計算ロジックを分離
const weightSurcharge = weight > WEIGHT_LIMIT ? OVER_WEIGHT_SURCHARGE : 0;
return baseFee + weightSurcharge;
}
// 実行例
console.log(getShippingFee(AREA.DOMESTIC, PLAN.STANDARD, 6)); // 1000 (500 + 500)
〇主な修正ポイント
ロジックからデータへの変換(Lookup Table)
入れ子になった if 文を FEE_TABLE オブジェクトに置き換えました。「どの組み合わせでいくらか」が一目でわかる表形式になったため、エリアが増えてもロジック(if)をいじらず、データを 1 行足すだけで対応可能です。
マジック文字列の排除
定数化することで、エディタの補完が効くようになり、タイポによるバグを未然に防げるようになりました。
ガード節による入力値の検証
関数の冒頭で「想定外の値」を弾くことで、メインの計算処理をシンプルに保ち、プログラムの堅牢性を高めています。
計算式の分割
「基本料金」と「重さの加算」を分けることで、将来的に「海外便だけ重量加算を 1000 円にしたい」といった変更があっても、修正箇所を特定しやすくなっています。
〇参照先
▼公式ドキュメント
▼書籍
リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック
以上
Discussion