リーダブルコード実践 第二弾 ~Vol.4~

今回はロジックを見直してさらに読みやすくします。

//商品クラス
var CartItem = function(cart_no, goods_id, unit_price, goods_num, tax_rate) {
    this.cart_no    = cart_no;
    this.goods_id   = goods_id;
    this.unit_price = unit_price;
    this.goods_num  = goods_num;
    this.tax_rate   = tax_rate;

    this.Price = function() {
        return this.unit_price * this.goods_num;
    }

    this.Tax= function() {
        return this.Price() * tax_rate;
    }

    this.PriceWithTax= function() {
        return this.Price() + this.Tax();
    }
}

//カートクラス
var Cart = function() {
    this.latest_cart_no = 0;
    this.cart_items     = [];

    this.Add = function(goods_id, unit_price, goods_num) {
        if (goods_id === "") {
            CommonFunc.ShowError("商品を指定してください。");
            return;
        }
        if (goods_num < 1) {
            CommonFunc.ShowError("数量は1以上を入力してください。");
            return;
        }

        this.cart_items[this.cart_items.length] = new CartItem(
            this.NewCartNo(),
            goods_id,
            unit_price,
            goods_num,
            CommonFunc.TaxRate(Date.now(), goods_id)
        );
    }

    this.ChangeGoodsNum = function(cart_no, goods_num) {
        var idx = this.IndexOf(cart_no);

        if (idx < 0) {
            CommonFunc.ShowError("商品が存在しません。");
            return;
        }
        if (goods_num < 1) {
            CommonFunc.ShowError("数量は1以上を入力してください。");
            return;
        }

        this.cart_items[idx].goods_num = goods_num;
    }

    this.Remove = function(cart_no) {
        var idx = this.IndexOf(cart_no);

        if (idx < 0) {
            CommonFunc.ShowError("商品が存在しません。");
            return;
        }

        this.cart_items.splice(idx, 1);
    }

    this.TotalPriceWithTax = function() {
        var total_price_with_tax = 0;

        for (var idx = 0; idx < this.cart_items.length; idx++)
            total_price_with_tax += this.cart_items[idx].PriceWithTax();

        return CommonFunc.ToMoney(total_price_with_tax);
    }

    this.NewCartNo = function() {
        return ++this.latest_cart_no;
    }

    this.IndexOf = function(cart_no) {
        for (var idx = 0; idx < this.cart_items.length; idx++) {
            if (this.cart_items[idx].cart_no === cart_no)
                return idx;
        }
        return -1;
    }
}

//共通関数クラス
CommonFunc = {
    TaxRate: function(target_date, goods_id) {
        if (target_date >= "2019/10/01") {
            //軽減税率対象商品なら8%
            if (this.IsReducedTaxRateGoods(goods_id))
                return 0.08;
            else
                return 0.1;
        }
        else if (target_date >= "2014/04/01") {
            return 0.08;
        }
        else if (target_date >= "1997/04/01") {
            return 0.05;
        }
        else if (target_date >= "1989/04/01") {
            return 0.03;
        }
        else {
            return 0;
        }
    },

    IsReducedTaxRateGoods: function(goods_id) {
        return goods_id.substr(0, 3) === "RTR";
    },

    ToMoney: function(price) {
        return "¥" + String(price).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,");
    },

    ShowError: function(msg) {
        console.log("Error: " + msg);
    }
}

※変更点は省略します。

データを保持せずとも簡単に計算できるものをメソッド化したので、保持しているデータを更新するコードがなくなり、読みやすくなりました。

初めに書いたコードから比べると、コード量自体はそこまで差はありませんが、一つ一つのメソッドのコード量は減っています。また、やりたいことに直接関係のない計算処理などをメソッド化したので、コードが簡単になり、読みやすさ・拡張性が向上しました(特にCart.AddやCart.ChangeGoodsNumは劇的に読みやすくなりました)。

これで「より良いコードを書くために」シリーズは完結します。今度は何を学習しようかな。。。

この記事が気に入ったらサポートをしてみませんか?