SHOEISHA iD

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

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

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

実践DDD本 第7章「ドメインサービス」~複数の物を扱うビジネスルール~

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


  • X ポスト
  • このエントリーをはてなブックマークに追加

ドメインサービスの失敗例

 次に、ドメインサービスを導入するときの注意点について紹介します。

ドメインサービスの多用/誤用

 ドメインサービスの危険な点は、ユビキタス言語ではないビジネスロジックを大量に記述できてしまう点です。特にDDDに慣れていない場合、トランザクションスクリプトで処理を書いてしまう可能性があります。

 この問題は、使う必要がない箇所でドメインサービスを利用してしまうため、エンティティや値オブジェクトが空っぽの「ドメインモデル貧血症(5章)」を引き起こす危険性があります。

ドメインサービスのミニレイヤ

 似たアンチパターンとして、ドメインサービスの「ミニレイヤ」を作ってしまう失敗があります。検討することなく最初からドメインサービスのレイヤを作ってしまうと、このレイヤが肥大化する傾向にあります。それを避けるため、ドメインサービスのレイヤを作る必要がないコンテキストでは導入しないようにします。

アプリケーションサービス層での実装

 別の失敗として、ドメインサービスをアプリケーションサービスで実装してしまう間違いもあります。アプリケーションサービス(14章)は、トランザクションやセキュリティといった、ドメインの外側の関心ごとの実装を行う場所です。

 例えば、先ほど紹介したソースコードの「BusinessPriorityCalculator」の計算処理は、現在のドメインに特化しており、外部に流出させたくない情報です。アプリケーションサービスは利用者側であり、ドメイン内部の不要なロジックを知る必要はありません。このような観点でドメインサービスとアプリケーションサービスの区別を意識しておくといいでしょう。

ドメインサービス導入時のポイント

 次に、ドメインサービス導入時のポイントについて紹介していきます。まず、これまで紹介してきたように、値オブジェクト/エンティティ/集約の構成でドメインモデルを表現できていれば、ドメインサービスがなくても問題ありません。

 しかし、エンティティと値オブジェクト単体では計算できないビジネスロジックがある場合にドメインサービスの利用を検討します。ドメインモデルの詳細がクライアント側に漏れ出ないようにしつつ、複数のエンティティと値オブジェクトを組み合わせて抽出したり合計したりするビジネスルールを記述します。

リファクタリングによるドメインサービスの導入

 IDDD本では先ほど紹介したBusinessPriorityTotalsメソッドを、Productクラスからドメインサービスへリファクタリングするシナリオを紹介しています。

リファクタリングして、ドメインサービスを導入する例
リファクタリングして、ドメインサービスを導入する例

 リファクタリング前の状態では、Productクラス(集約)からBacklogItemクラス(集約)を取り出すことになり、集約の内部からリポジトリを呼ぶことになります。しかし、この呼び出し方式はできる避けたほうがよいといわれているため、ドメインサービスを導入しました。

 このように、最初からドメインサービスを導入するのではなく、ドメインモデルの発展の過程でリファクタリングを行い、ドメインサービスが導入されるというシナリオがよいと思われます。

単一責任の原則(SRP原則)

 SaaSOvationのサンプルでは、Productクラスが複数の役割を担っていたため、ドメインサービスを導入するリファクタリングを行いました。このリファクタリングを行うに至った考え方として「単一責任の原則」が存在しています。

 単一責任の原則(SRP:Single Responsibility Principle)とは、ロバート・マーチン氏の書籍「アジャイルソフトウェア開発の奥義」にて解説されているオブジェクト指向の設計原則で「クラスを変更する理由は1つ以上存在してはならない」ことです。

 1つのクラスが複数の役割を受け持っている場合、複数の役割がつながってしまい、片側の変更が逆側に影響を与えてしまいます。その結果、想定外の不具合が発生してしまいます(もし2つの役割が必ず同時に変更されるのであれば、分離する必要はありません)。

 「クラスを単一の責務で設計する」という考え方はよく聞きますが、SRP原則では「仕様変更」に注目することで、より具体的にクラスを分割し、正しい名前をつけることを促しています。

 なお、オブラブの単一責任の原則の紹介ページにも「クラスに変更が起こる理由は、1つであるべき」「良い抽象には良い名前がつく」といったポイントがわかりやすく解説されていますので、目を通してみるといいでしょう。

次のページ
ドメインサービスの設計方法

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

  • X ポスト
  • このエントリーをはてなブックマークに追加
IDDD本から理解するドメイン駆動設計連載記事一覧

もっと読む

この記事の著者

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

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 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本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

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

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

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/10318 2017/09/05 16:32

おすすめ

アクセスランキング

アクセスランキング

イベント

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

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

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

メールバックナンバー

アクセスランキング

アクセスランキング