様々な条件があるクーポンのドメインモデリング
注文情報・顧客情報・期間限定セールなどに応じて
・注文全体への割引
・特定の商品への割引
・特定のカテゴリ(ブランド)への割引
・割引ではなく、固定金額になる。(クーポンを使うと200円など)
・送料無料
・回数制限
など
ドメインを跨いで影響する様々な仕様を持つクーポンと注文クラスについてのドメインモデリングについて
他の方がどのようにクラスを実装するか、お聞きしたいです。
状況
特に既存のシステムがあるわけではなく、注文と注文に対して使用できるクーポンがある場合にどのようにモデリングしたらいいだろうという意見交換です。
概要
・OrderクラスはCouponの配列を持ったImmutableなクラス。
・OrderDetailクラスは商品情報を持った注文詳細クラス(各注文商品の金額を持つ)
・CouponクラスはCouponInterfaceを使用することで、様々な仕様のクーポン機能が可能
現状のOrderクラス
php
1<?php2namespace App\Beer;3 4use App\Beer\Interface\CouponInterface;5 6class Order {7 8 private ?int $id;9 10 private int $totalPrice;11 12 private Customer $customer;13 14 private OrderDetails $orderDetails;15 16 private Coupons $coupons;17 18 private DeliveryFee $deliveryFee;19 20 public function __construct(21 ?int $id,22 int $totalPrice,23 Customer $customer,24 OrderDetails $orderDetails,25 Coupons $coupons,26 DeliveryFee $deliveryFee,27 ) {28 $this->id = $id;29 $this->totalPrice = $totalPrice;30 $this->customer = $customer;31 $this->orderDetails = $orderDetails;32 $this->coupons = $coupons;33 $this->deliveryFee = $deliveryFee;34 }35 36 public function addOrderDetail(OrderDetail $orderDetail) {37 $this->orderDetails->addOrderDetail($orderDetail);38 }39 40 public function getTotalPrice() {41 return $this->totalPrice;42 }43 44 public function getOrderDetails(): OrderDetails {45 return $this->orderDetails;46 }47}
現状のOrderDomainService
php
1<?php2namespace App\Beer\DomainService;3 4use App\Beer\Order;5use App\Beer\Interface\CouponInterface;6 7class OrderDomainService {8 9 public function __construct(10 11 ) {12 13 }14 15 public function addCoupon(Order $order, CouponInterface $coupon): Order {16 if (!$coupon->isApplicable($order)) {17 throw new \Exception('適用できません');18 }19 $appliedOrder = $coupon->apply($order);20 21 return $appliedOrder;22 }23}
聴きたい意見
クーポンの割引の適用処理をOrderクラスで行うべきか、OrderDomainServiceで行うべきか
Orderクラスからクーポンの適用処理を行おうとすると、金額を変更したOrderDetailや DeliveryFeeを持ったOrderクラス(自分自身)を返す必要があり、不自然な処理になっている気がします。
一方、OrderDomainServiceにOrderとCouponクラスを渡し、割引が適用されたOrderクラスを受け取るようにすると
適用処理はDomainServiceに任せているのに、Orderはどのクーポンが適用されているか把握する必要があるためCoupon配列を持っているという違和感を感じます。
現状、OrderDomainServiceで実装する方が良いと考えていますが、他の方法も含めて意見を聴きたいです。

0 コメント