コードで学ぶファクトリー〜DDD実践のためのきほん〜

はじめに

今回はポイント管理システムをテーマに

DDD×クリーンアーキテクチャでサンプルコードを作ったので、

それを使いながら、

ファクトリーの使いどころとその効果についてまとめました。


ファクトリーのサンプルコード

今回テーマにしているポイントシステムでは、

店舗からレシート情報とカード、ポイント利用などを連携され、

付与ポイントの加算、ポイント利用の減算などの

ポイント管理ができるシステムを想定しています。

ポイント管理システムのイメージ図


まずはファクトリーのサンプルコードを見てみましょう。

支払生成ファクトリー
@Service
class PaymentFactory(
    private val paymentMemberRepository: IPaymentMemberRepository,
    private val useCouponRepository: IUseCouponRepository
) {
    fun create(
        receiptNumber: ReceiptNumber,
        paymentDateTime: PaymentDateTime,
        memberCode: MemberCode,
        usePoints: Point?,
        companyCode: MemberCompanyCode,
        shopCode: ShopCode,
        couponCode: CouponCode?,
        paymentPurchases: List<PaymentPurchase>,
        paymentMethods: List<PaymentMethod>
    ): Payment {
        val paymentMemberBeforeUsePoints = paymentMemberRepository.findBy(memberCode)
        val paymentMember = if (usePoints != null) { paymentMemberBeforeUsePoints.usePoints(usePoints) } else { paymentMemberBeforeUsePoints }

        val useCoupon = couponCode?.let { useCouponRepository.findBy(it) }
        val paymentPurchaseWithCoupon = useCoupon?.let { paymentPurchases.map { it.useCoupon(useCoupon) } } ?: paymentPurchases
        return Payment(receiptNumber, paymentDateTime, paymentMember, companyCode, shopCode, useCoupon?.couponCode, paymentMethods, paymentPurchaseWithCoupon)
    }
}


支払エンティティ(支払集約ルート)を生成する際、

支払時にポイント利用があれば、

事前に支払ユーザの残ポイントを利用する。


クーポン利用があれば、

クーポンを設定して支払購入品エンティティを生成する。


など、

ファクトリーにドメインオブジェクト生成に関する

複雑な手順をまとめています。


ファクトリーの使い所と効果

僕の場合は以下のような場合に

ファクトリー導入を検討するようにしています。

  • 複数のユースケースで登場するドメインオブジェクト生成
  • ドメインオブジェクト生成に関する手順が複雑な業務ロジック
  • ドメインオブジェクト生成に他集約の参照が必要


複数のユースケースでドメインオブジェクト生成の複雑なロジックを書いていた場合、

生成ロジックの仕様変更があると全てを変更して回る必要があるので、

変更に弱くなってしまいます。

そうならないためにファクトリを導入するようにします。


また、

複数のドメインオブジェクトを特定の手順で生成した後で

目的のドメインオブジェクトが生成できる。

他集約のドメインオブジェクトとの相関関係のチェックを通した後で

目的のドメインオブジェクトが生成できる。


などの制約がある場合も

ファクトリを導入して一連の生成に関する処理をカプセル化してやります。

(その場合は集約の設計からやり直しが必要な気もしますが)

これによって、

使う側がシンプルに目的のドメインオブジェクトを生成でき、

間違った生成手順でのドメインオブジェクト生成を防げます。


今回のテーマについては以上です。

DDD実践のためのきほんシリーズのまとめ記事を作りました。

是非こちらもご覧ください。

初めてDDDを実践する方に向けて〜DDD実践のためのきほん〜


参考文献

第6章 ドメイン層の実装

ドメイン駆動設計 モデリング/実装ガイド


Chapter9 複雑な生成処理を行う「ファクトリ」

ドメイン駆動設計入門 ボトムアップでわかる! ドメイン駆動設計の基本

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください