【6日目】『リーダブルコード』を意識してJavascriptをリファクタリングしてみた
技術ブログ6日目。
本日は、Javascriptの読みやすさを追求します。
〇課題
注文合計金額計算プログラム
一応、期待通りに計算は行われます。
しかし、何をしているかが読み解きづらく、修正時にバグを出しやすい状態です。
〇修正前コード(動くけれど読みにくいコード)
// 課題コード
function process(p, q, status) {
let r = 0;
if (p > 0) {
if (q > 0) {
// 合計を計算
let total = p * q;
// 10個以上は10%引き
if (q >= 10) {
total = total * 0.9;
}
// 会員種別による割引
if (status === 1) {
total = total - 500;
} else if (status === 2) {
total = total - 100;
}
// 消費税(10%)
r = total * 1.1;
}
} else {
r = 0;
}
return r;
}
// 実行例
console.log(process(1000, 10, 1)); // 会員かつ10個以上購入の場合
〇リファクタリングの指針
名著『リーダブルコード』の以下の原則を意識しました。
名前の改善:p, q, r などの抽象的な名前を、意味を持つ名前に変更。
条件記述の単純化:深いネストを解消し、「ガード節(早期リターン)」を導入。
説明変数の導入:計算式に名前を付け、コード自体が説明書になるように修正。
〇修正後コード
/**
* 注文の合計金額(税込)を計算する
* @param {number} unitPrice - 単価
* @param {number} quantity - 数量
* @param {number} memberStatus - 会員ランク (1: プレミアム, 2: 一般)
*/
function calculateTotalPrice(unitPrice, quantity, memberStatus) {
// 定数の定義(マジックナンバーの排除)
const TAX_RATE = 1.1;
const BULK_DISCOUNT_THRESHOLD = 10;
const BULK_DISCOUNT_RATE = 0.9;
const MEMBER_DISCOUNTS = {
PREMIUM: 500,
REGULAR: 100,
};
// 1. ガード節による早期リターン
// 不適切な条件を先に排除し、メインロジックのネストを浅くする
if (unitPrice <= 0 || quantity <= 0) {
return 0;
}
// 2. 説明変数による計算過程の明確化
const basePrice = unitPrice * quantity;
const isBulkPurchase = quantity >= BULK_DISCOUNT_THRESHOLD;
const priceAfterBulkDiscount = isBulkPurchase
? basePrice * BULK_DISCOUNT_RATE
: basePrice;
const memberDiscountAmount = (memberStatus === 1) ? MEMBER_DISCOUNTS.PREMIUM
: (memberStatus === 2) ? MEMBER_DISCOUNTS.REGULAR
: 0;
// 3. 再代入を避け、constで値を確定させる
const totalPriceBeforeTax = Math.max(0, priceAfterBulkDiscount - memberDiscountAmount);
return Math.max(0, totalPriceBeforeTax * TAX_RATE);
}
console.log(calculateTotalPrice(1000, 10, 1));
〇主な修正ポイント
1.ガード節の導入
ifの中にifがある深いネストを解消しました。
2.名前に情報を詰め込む
p, q, r を unitPrice, quantity, totalPrice へ変更。 また、status === 1 を MEMBER_DISCOUNTS.PREMIUM と比較するようにし、コメントがなくても「何と比較しているか」が一目で分かるように修正しました。
3.「説明変数」と「不変性」
「後で値が変わる空箱(let)」を、各段階の計算結果に名前を付けてconstで固定しました。
「今の変数の値はどうなっているか?」とコードを遡って追跡する手間をなくすことを目指しました。
4.マジックナンバーの排除
0.9 や 500 といった生の数値を定数化しました。
これにより、将来的な消費税率や割引額の変更にも、1箇所の修正で対応できます。
〇参照先
▼公式ドキュメント
Math.max()
JavaScript オブジェクトの基本
条件(三項)演算子
▼書籍
リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック
以上
Discussion