SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

IDDD本から理解するドメイン駆動設計

実践DDD本 第11章「ファクトリ」~複雑な生成をユビキタス言語でシンプルに~

IDDD本から理解するドメイン駆動設計 第11回

(1)コンストラクタで十分な場合

 生成処理がシンプルな場合には、コンストラクタを利用してクライアント側からオブジェクトを生成します。一般的な生成の仕組みですので、理解しやすいと思います。

(2)集約ルートに実装するファクトリ

 逆に、生成が複雑な場合は、ファクトリを使用します。例えば、多態性(ポリモーフィズム)を用いて実クラスを決定する場合や、他の集約を組み立てる場合です。なお、ファクトリでしか生成させない場合、クラスのコンストラクタには外部から生成させないスコープの修飾子をつけます。コンストラクタと異なり、ファクトリでは複雑な生成を行うことができ、ユビキタス言語にて表現することができるメリットがあります。ドメインモデラーが話す言葉に注目し、生成するオブジェクトに適した集約にファクトリを用意します。

集約上のファクトリのコード例

 SaaSOvationのコードを見てみましょう。ここでは集約であるForumクラスのStartDiscussionForというファクトリを呼び出し、戻り値としてDiscussionオブジェクトを戻しています。これは「投稿者はフォーラム上でディスカッションを開始する」というユビキタス言語を表現していることが分かります。

[リスト]集約「Forum」で「ディスカッションを開始する」ファクトリ(C#)
namespace SaaSOvation.Collaboration.Domain.Model.Forums
{
  public class Forum : EventSourcedRootEntity
  {
    // ディスカッションを開始する(ファクトリ)
    public Discussion StartDiscussionFor(ForumIdentityService forumIdService, 
        Author author, string subject, string exclusiveOwner = null)
    {
      AssertOpen();
      return new Discussion(
          this.tenantId,
          this.forumId,
          forumIdService.GetNextDiscussionId(),
          author,
          subject,
          exclusiveOwner);
    }

    // 不変条件の確認(フォーラムがオープンしているか)
    void AssertOpen()
    {
      if (this.closed)
        throw new InvalidOperationException("Forum is closed.");
    }
  }
}

 このコードでは、まず、整合性が正しくないモデルを生成しないように「不変条件」をチェックするAssertOpenというメソッドを呼び出しています。その後、ディスカッションを開始するために、Discussionクラスのコンストラクタを呼び出しています。コンストラクタを呼び出す時に、ファクトリの引数だけではなく、集約「フォーラム」の情報(this.tenantIdとthis.forumId)を使っていることが分かります。このように集約にファクトリを用意することで、引数の数を減らすことができます。

不変条件を満たすファクトリ

 上記のコードでは不変条件をチェックする処理が、ファクトリの最初で呼び出されていました。エヴァンス氏はファクトリの役割として次のことを述べています。

 集約全体をひとまとまりとして生成し、その不変条件を強調すること

 DDDのファクトリにおいては「一貫した状態のオブジェクトだけを返す」という制約があります。利用者は、複雑な生成ロジックを意識することなく、簡単に正しいオブジェクトを取得できます。その際に、生成される集約の状態が一貫して正しいこと、つまり、不変条件が正しく守られていることが重要な役割となります。このように、ファクトリは生成するオブジェクトに対して、アトミック性(原子のように、それ以上細かい単位や要素に分割されないこと。すべて完了するか1つも実行されないこと)を保ち、中途半端に生成されないことを約束します。

 ここまで、集約に実装するファクトリについて紹介しました。

次のページ
(3)サービスに実装するファクトリ

この記事は参考になりましたか?

IDDD本から理解するドメイン駆動設計連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト 青木 淳夫(アオキ アツオ)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。 2026年時点での登録メンバは約50名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるLaravel実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/10903 2018/06/26 14:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー