ドメイン駆動設計をかじってみる

はじめまして!平奥と申します。

TECHSCORE BLOGに記事を投稿させていただくことになりました。
みなさま、よろしくお願いします!

今回は私が設計について学んでみようと思い、「エリック・エヴァンスのドメイン駆動設計」を読んだ内容を記事にしました。
感想としては率直に申しますとすごく抽象的で、読みづらいですが、有益な内容がたくさん書かれています。

こういう設計関連の学習をするときに、私が心がけているのが「完璧な設計はない。」ということです。
実は、ある設計思想に基づいて設計しているときに、その思想に完璧を求めるあまり解決できなくて
途方にくれた時がありました。

しかしもっと柔軟に設計を行い、その設計思想のコアなルールは守るというスタンスでよいのではと考えています。
他の設計思想と共存させ、そのプロジェクトにおいて最適な設計を行うことが大事だと考えています。

このことはエリック・エヴァンスも本書にて語っています。

少し脱線しましたが。。

本書は4部構成になっておりますが、今回はドメイン駆動設計をかじってみるということで、ドメイン駆動設計を理解するうえで基本となる第1部、第2部の内容に関して書いていきたいと思います。

ドメインとは何か??

ソフトウェアが価値を生み出す業務領域で、本書では「知識、影響、または活動領域」と説明されています。ドメインは複雑で開発者が容易に理解できるものではありません。そのため知識の噛み砕きとしてドメインエキスパート(業務内容を熟知している人たち)と議論を進め、ブレインストーミングを行い、モデルを作り上げ、改良し、知識豊富なモデルを作り上げる作業がイテレーティブに行われることが必要だと書かれています。

ちなみにドメインエキスパートについて本書では、以下のように説明されています。

「ドメインエキスパートは、ソフトウェア開発における技術的な専門用語のことは部分的にしか理解せず、代わりに自分の得意分野の専門用語を使用する。」

これは開発者とドメインエキスパートが同じ内容を表す用語があるにもかかわらず、それぞれで違う用語を使っていることを表しています。これはモデルを作り上げるうえで好ましくないことであり、この解決方法が次に説明する「ユビキタス言語」であります。

ユビキタス言語

ドメインエキスパートが自分たちの得意分野の専門用語を使用するように、開発者も独自の言語を持っており、開発者による抽象化は自分たちの設計は支えてはいてもドメインエキスパートには理解されません。

すなわちそれは、それぞれ独自の言語を持っており、お互いに理解しにくい言語を使ってお互いを理解しようとしているということです。このような言語に亀裂があると、プロジェクトは深刻な問題に直面します。

確かに複雑な問題を解決するためのソフトウェアを開発するのですから、お互いが共通の認識である言語を使用してコミュニケーションをとった方が効率がよく、問題を回避できるということは言うまでもありません。

このお互いが共通の認識である言語が「ユビキタス言語」です。

本書では「ドメインモデルを取り巻いて構築され、チームのあらゆる活動をソフトウェアと結びつけるために、チームメンバ全員によって使用される言語」と説明されています。

「ユビキタス言語」を使うことをチーム内に約束させ、コミュニケーション、ドキュメント、コードにおいてその言語を使用すること。
モデルを言語の骨格として使用すること。これによってドメインモデルとコードが結びつくようになります。

そもそもモデルって何??モデルとコードを結び付けて何のメリットがあるの??
それについてもう少し掘り下げて以降に説明していきます。

モデル駆動設計

モデルとは簡単に言うと現実世界を抽象化したものであり、設計の方法論の多くはモデルを使用して設計を行います。またモデルとコードを、別々のものとして取り扱う分析モデルを使用することを主張しています。これはドメインと実装の問題が混ざってしまうと、わかりにくくなるからと考えられているからです。

しかしこの分析モデルで設計し、実装を行っていくと開発者が設計を行うために新たな抽象(モデル)を考え出さざるを得なくなると、分析モデルはただの置物と化します。

なぜ開発者が新たなモデルを考え出さないといけないのか??
それは明白であり、モデルと実装を切り離しているからです。

私もよく実装をしているときに、モデルって何の意味があるのかなと思っていたことがあります。
本書を読んだときその理由が理解できました。

「設計がモデルと結びついてないならば、そのモデルに価値はなく、そのソフトウェアが正確であるとは疑わしい。」
「分析と設計の間に致命的な亀裂が生じるため、それぞれの作業で得られる洞察は互いに生かされることがないのだ。」

本書にはそう書かれています。納得です。

そこでこの問題を解決するのが「モデル駆動設計」です。
「モデル駆動設計」は分析モデルと設計という二分法を捨て去り、両方の目的に使える単一のモデルを探し出します。モデル駆動設計のアプローチは、分析としても設計としてもうまく機能するモデルを要求します。

これにはソフトウェアを設計するには、紐付けを明らかになるようにモデルを忠実に反映させること。モデルについては、より自然にソフトウェアに実装されるように修正すること。これには「ユビキタス言語」を使用しドメインと実装で両方の目的で使える単一のモデルを要求することです。

それでは「モデル駆動設計」を構成する要素について掘り下げていきます。

モデル駆動設計を構成する要素

モデル駆動設計を構成する要素について、軽く触れていきたいと思います。

レイヤ化アーキテクチャ

これは複雑なプログラムをレイヤに分割します。ドメイン駆動設計ではドメインを隔離するため、「ドメイン層」のレイヤが重要となります。このドメイン層にビジネスロジックを閉じ込め、他のレイヤにビジネスロジックが入らないようにします。

レイヤ化アーキテクチャ

  • ユーザインターフェイス
  • ユーザに情報を表示して、ユーザのコマンドを解釈する責務を負います。

  • アプリケーション層
  • ソフトウェアが行うことになっている仕事を定義します。ビジネスルールや知識を含みません。プログラムが行う作業の進捗を反映する状態を持つことはできます。

  • ドメイン層
  • ビジネスの概念と、ビジネスが置かれた状況に関する情報、およびビジネスルールを表す責務を負います。

  • インフラストラクチャ層
  • 上記レイヤを支える一般的な技術的機能を提供する層になります。

さて「レイヤ化アーキテクチャ」に触れてみたところで、次はオブジェクトそのものに目を向けてみようと思います。
ドメイン駆動設計ではオブジェクトを以下のような区別をすることによってモデルが明確になり、より現実に即して実装することができるようになります。

エンティティ

属性は異なっていても、同一のものとして扱う必要のあるものをエンティティとして扱うようにします。一般的にはID属性を持たせて同一性を確保します。

値オブジェクト

エンティティとは逆で属性にしか対象とならないものであればこの値オブジェクトとして扱います。

サービス

ドメインの重要な操作でありながら、エンティティや値オブジェクトの責務とするには不自然なものがあります。そういった操作はサービスのオブジェクトの振る舞いとして定義します。

モジュール

プログラミングの場合と同じく、モデルのモジュール分割においても高凝縮・低結合で分割する必要があります。概念をできるだけモジュール分割してわかりやすくします。

集約

複雑な関連を伴うモデルでは、オブジェクトの一貫性を保証するのは難しいです。維持すべき不変条件には、個々のオブジェクトに適用されるものだけでなく、密接に関連するオブジェクトのグループに適用される場合があります。そのためエンティティと値オブジェクトを集約の中にまとめ、各集約に対してルートとなるエンティティを1つ選び、集約の境界内部にはそのルートエンティティを通してアクセスするようにします。

ファクトリ

オブジェクトの生成は、それ自体が主要な操作になりますが、複雑な組み立て操作は、生成されるオブジェクトの責務にはなりません。ファクトリはそのような複雑なオブジェクトと集約のインスタンスを生成する責務を負います。

リポジトリ

生成されたオブジェクトは、DBに保存されたりして永続化されます。DBへの問い合わせなどの操作によって処理が複雑にならないようリポジトリオブジェクトを導入し、その処理を隠ぺいします。ファクトリはオブジェクトを生成するのに対して、リポジトリはオブジェクトの再構成を行うものと定義されます。

上記のオブジェクトについてはこの文章だけではなかなか理解できないと思いますので、実際に設計をする場合は本書を読んでいただければと思います。

これらの要素を組み合わせて設計を行っていきます。

ドメイン駆動設計を使用する

以下に記載したモデルは貨物輸送会社のための新しいソフトウェアの設計です。このシステムは3つの要求があります。1つは顧客貨物に対する主要な荷役を追跡します。2つめはあらかじめ貨物を予約します。3つめは貨物が荷役の過程で所定の場所に到達した際に、自動的に請求書を顧客に送付します。これらの機能を満たすため、上記で記載したパターンのオブジェクトを利用しきれいに分割しています。

クラス図1
引用:エリック・エヴァンスのドメイン駆動設計 P180 図7.7

エンティティ、値オブジェクト、サービスを使用し設計を行っています。しかしドメインの知識は伝わっていません。
これをドメインの概念に基づいた設計にしたのが以下の図です。
クラス図2
引用:エリック・エヴァンスのドメイン駆動設計 P181 図7.8

「ユビキタス言語」すごいです。これだとチーム全体でこの設計が理解され共有できますね。

まとめ

いかがでしたでしょうか。ドメイン駆動設計の概要について触れていただけたのなら幸いです。

この記事を読んで興味を持たれた方は是非読んでみてください。

エリック・エヴァンスのドメイン駆動設計 翔泳社
エリック・エヴァンス (著), 今関 剛 (監修), 和智 右桂 (翻訳), 牧野 祐子 (翻訳)

Comments are closed, but you can leave a trackback: Trackback URL.

Comments

  • 初心者  On 2016年6月12日 at 11:29

    まったく分かりませんでした。

    モデル駆動とドメイン駆動は別の概念ですか?

    • 平奥 真一  On 2016年6月13日 at 10:08

      コメントありがとうございます。

      なかなか簡単に理解するのは難しいですよね。繰り返し少しずつ理解していくのがよいと思います。

      ドメイン駆動設計とモデル駆動設計って似かよった概念だと思います。

      簡単に説明すると、ドメイン駆動設計は、ドメインを重要視して設計する手法で、それをソフトウェアに反映させる手法として、モデル駆動設計を採用しています。

      一方モデル駆動設計は、ドメイン駆動設計だけでなく、UIフレームワークや、ウィンドウメニューといったものにまで適応することができます。

      ドメイン駆動設計にとっては、モデル駆動設計は必須ですが、モデル駆動設計にとってはドメイン駆動設計の影響を受けない概念だということですかね。

      この部分については著者のエリック・エヴァンスも以下の記事で触れています。

      http://dddcommunity.org/uncategorized/evans_2004/

      よかったら読んでみてください!