バグ解消法、お役立ち情報など

商品の料金計算には、バリューオブジェクトが便利!

はじめに

みなさま、バリューオブジェクト(ValueObject, 値オブジェクト)をご存知でしょうか。

バリューオブジェクトとは、クラスや構造体を用いて値を保持するという設計手法を指します。

クラスや構造体を用いて値を保持することで、開発のしやすさが劇的に向上します!

本日は、特に「商品の料金計算」を実装する際にバリューオブジェクトを使うといいよ、という話をします。

参考になれば嬉しいです!

実装例

先に実装例をお見せします。

Before: バリューオブジェクトを使わない例

バリューオブジェクトを使わない例
const UNIT_PRICE = 100; // 商品1の単価 const TAX_RATE = 10; // 税率 ... // 中略 // 商品数 $count = 10; // 税抜金額 $chargeExcludeTax = $count * self::UNIT_PRICE; // 税額 $tax = $chargeExcludeTax / self::TAX_RATE; // 税込金額 $chargeIncludeTax = $chargeExcludeTax + $tax; // それぞれの値ごとに変数がバラバラなので、管理が大変・・・ // 後の処理で、意図しない値に更新されてしまうかも・・・ // 間違って、税込金額にまた税を足してしまう例 $chargeIncludeTax = $chargeIncludeTax * 1.1;

保守が大変な辛いコードになっております。

上記のような処理を、バリューオブジェクトを使って実装してみます。

After: バリューオブジェクトを使った例

バリューオブジェクトを使った例
/** * 商品1 の 個数を受け取り 税抜金額・税額・税込金額を計算する */ class Service1ChargeValue { const UNIT_PRICE = 100; // 商品1の単価 const TAX_RATE = 10; // 税率 public $chargeExcludeTax; public $tax; public $chargeIncludeTax; public function __construct( int $count ) { // 税抜金額 $this->chargeExcludeTax = $count * self::UNIT_PRICE; // 税額 $this->tax = $this->chargeExcludeTax / self::TAX_RATE; // 税込金額 $this->chargeIncludeTax = $this->chargeExcludeTax + $this->tax; } } $service_1 = new Service1ChargeValue(10); echo '税抜金額: ' . $service_1->chargeExcludeTax . PHP_EOL; echo '税額: ' . $service_1->tax . PHP_EOL; echo '税込金額: ' . $service_1->chargeIncludeTax . PHP_EOL; // 税抜金額: 1000 // 税額: 100 // 税込金額: 1100

とてもスッキリしました!

税込金額や税額などが、ひとつのオブジェクトにまとまっているため、非常に扱いやすくなります。

また、getterメソッドを追加することで、オブジェクト全体をイミュータブル(変更ができない状態)にすることも可能です。

バリューオブジェクトを使った例(イミュータブル版)
class Service1ChargeValue { const UNIT_PRICE = 100; // 商品1の単価 const TAX_RATE = 10; // 税率 private $chargeExcludeTax; private $tax; private $chargeIncludeTax; public function __construct( int $count ) { // 税抜金額 $this->chargeExcludeTax = $count * self::UNIT_PRICE; // 税額 $this->tax = $this->chargeExcludeTax / self::TAX_RATE; // 税込金額 $this->chargeIncludeTax = $this->chargeExcludeTax + $this->tax; } public function getChargeExcludeTax(): int { return $this->chargeExcludeTax; } public function getTax(): int { return $this->tax; } public function getChargeIncludeTax(): int { return $this->chargeIncludeTax; } } $service_1 = new Service1ChargeValue(10); echo '税抜金額: ' . $service_1->getChargeExcludeTax() . PHP_EOL; echo '税額: ' . $service_1->getTax() . PHP_EOL; echo '税込金額: ' . $service_1->getChargeIncludeTax() . PHP_EOL; // 税抜金額: 1000 // 税額: 100 // 税込金額: 1100

おわりに

オブジェクトをイミュータブルにすることで、プロパティが意図しない値へと更新される心配がなくなるため、保守性がさらに高まります!

みなさまも機会があればぜひバリューオブジェクトを使ってみてください。

バグ解消法、お役立ち情報など