kurukuru-papaのブログ

主に、ソフトウェア開発に関連したメモを書き溜めたいと思います。

実践したい!エリック・エヴァンスのドメイン駆動設計

エリック・エヴァンスのドメイン駆動設計 (IT Architects’Archive ソフトウェア開発の実践)

エリック・エヴァンスのドメイン駆動設計 (IT Architects’Archive ソフトウェア開発の実践)


社内の有志と一緒に「エリック・エヴァンスのドメイン駆動設計」を読んだので、簡単なまとめと、私がドメイン駆動設計を実践する際の考慮点にも触れてみたいと思います。色々勝手な事を書いています。間違い、勘違いなど多々あるかもしれません。

ドメイン駆動設計とは

業務担当者(ドメインエキスパート)の知識を図式化(ドメインモデル)し、業務担当者と開発メンバーの全員が意思疎通を図りながら設計を行うための手法です。ポイントは以下になると思います。

  • 全員が理解できるようにするため、図は分かりやすい言葉(ユビキタス言語)で表記する。
  • 業務担当者とは図を用いて会話することで、仕様の誤り・漏れをなくす。
  • 業務という視点で、図を表現する。
  • 上流工程から下流工程まで、同じ図を継続的に磨き上げて使用する。これにより、下流工程で変更が入っても、上流工程の考え方が引き継がれる。

他の手法と比較してみます。

UML
  • 色々な図を用いて、お客様と開発メンバーが意識合わせをする。
  • 分析と実装では、別々にクラス設計を行う。これは、分析時のクラス設計が、実装上の制約に引きずられることを、嫌っていたからだったと思います。逆に捉えると、実装上の制約に引きずられることが無いのであれば、分析と実装のクラスは同じにしたいという考え方があったような気もします。なんだか、UML手法の延長線上に、ドメイン駆動設計があるように見えてきました。
PowerPoint設計(勝手に名前つけました)

画面イメージをPowerPointに貼付け、操作内容などをコメント書きして、要件定義や画面設計を行う手法のことを指します。

  • 複数の画面で共通した仕様を、整合性を保ちつつ、要件定義や画面設計を行うことが難しいようです。ある画面の変更が、別の画面で不整合をもたらすこともしばしばあります。ドメイン駆動設計では、業務知識や仕様・制限などを一箇所に表現しますので、PowerPoint設計での不整合を防げます。

アーキテクチャの全体像

ドメイン駆動設計では、システムを下図のように、4層にわけて構成します。この内の3つ、ユーザインタフェース、アプリケーション、インフラストラクチャは、既存のいくつかのフレームワークでも見かける構成ですね。この3層で、システムの技術的要素やユーザインタフェースを実現するため、ドメイン層では、業務に専念できますね。


図.ドメイン駆動設計におけるレイヤー構成と各レイヤーの役割

書籍では明確に書かれてはいませんでしたが、各層におけるクラス構成は、下図のようになると考えました。ユーザインタフェース、アプリケーション、インフラストラクチャの3層では、使用するフレームワークやソフトウェアの種類(WebアプリやAndroidアプリなど)によっても構成が変わるかもしれません。ドメイン層は、実装に依存しない部分なので、フレームワークやソフトウェアの種類に依存しないはずですね。


図.ドメイン駆動設計における各レイヤーでのクラス構成

ドメイン層について、私は次のように理解しました。

  • モデルを「コンテキスト」と呼ばれるグループで分割し、モデルの一貫性を管理可能な大きさに保つ。
  • 各コンテキストのなかで、モデルを構成するクラスは、エンティティ、値オブジェクト、サービス、集約、ファクトリ、リポジトリの6つの種類から成る。
  • コンテキスト内のクラスが多い場合、各クラスの責務を整理し、3〜5個の層に分類することを検討する。層を作ることで理解しやすくなる。これらの層のことを「責務のレイヤ」と呼ぶ。
  • クラスは概念的に同一のものを「モジュール」というグループで分けることも可能。

設計・実装について

設計技法は数十のトピックにわかれていて、各々を取捨選択して実践投入することになりそうです。ただ、残念ながら、本に書いてある設計技法を十分には理解できませんでした。詳細を上手くまとめることはできません。

書籍では触れられていませんでしたが、ドメイン駆動設計における設計書は、どんな書きっぷりになるのでしょう?ちょっと考えてみました。

画面定義書
  • 画面イメージを作成するのは今まで通りだと思います。
  • 操作やイベントを網羅的に書くのも今まで通りだと思います。操作やイベントの処理内容は、どのドメインモデルを呼び出すかのみ記述し、処理の実現方法は不要になるだろうと考えています。
  • 操作やイベントからドメインモデルを呼び出すことを考えていると、ドメインモデルに機能漏れが見つかることもあると思います。ドメインモデルを、業務担当者と更新することになりそうです。これによりモデルが洗練される。
テーブル定義書
  • 今まで通り
外部システムとのI/F仕様書
  • 今まで通り

この本には、設計や実装をおこなっていくなかで、より良いドメインモデルを生み出すブレイクスルーが発生ことについて、繰り返し書かれています。より良いドメインモデルが発見された時、プロジェクトは、既に作成した実装に手戻りを発生させてまで、より良いドメインモデルを取り入れるべきでしょうか?本の中では、実例を一つ挙げて、より良いドメインモデルを取り入れていました。実際のプロジェクトでは、手戻りにどう対処するのか難しい所です。

テスト

ドメインモデルは、JavaでいうとPOJOで書けそうで、単体テストJUnitで自動化するのが比較的楽にできそうですね。

実践するときの考慮点

私がドメイン駆動設計をプロジェクトで実践するにはどうすれば良いでしょうか?(受託開発や一括受託開発などと呼ばれる開発を想定しています。)

突然、ドメインモデルを用いてお客様と意識合わせする、などということは困難だと思います。まずは、従来通りの手法を行いつつ、特に重要な設計部分に限って、ドメインモデルを抜粋した図を用いて、仕様の抜け・漏れをなくすように出来たら良いなと思います。

開発メンバーにも、いきなり、ドメイン駆動設計をします、といってもついてきてもらえない気がします。従来型の設計の中で、次のことを考慮したいと思います。

  • アーキテクチャ検討当初から、ドメインモデルの場所を作ってあげて、少しずつドメインモデルに慣れる。
  • 重要な機能(コアドメイン)に絞って、ドメインモデルを作成する。
  • 悩みすぎて時間を無駄にしない。
  • ドメインモデルを複数の機能から共通して使うことで、作るものが減って楽になるはず。

WBSを計画するときには次のタスクを考慮しておきたいですね。

  • ドメインモデルの位置づけを考慮したアーキテクチャの検討と説明会。
  • 上記検討内容に基づいて、設計書と実装のサンプル。
  • より良いドメインモデルへのブレイクスルーを考慮し、ブレイクスルーを反映するタスクを設ける。このタスクは、お客様からの仕様変更や、遅れて確定した仕様の取り込み作業と合わせて作業を行うと、お客様にも開発側にも作業しやすい気がする。
  • ドメインモデルを作れる(作ることを楽しめる)担当者を選ぶ。

以上、エリック・エヴァンスさん、訳者の方々、どうもありがとうございます。とても興味深く、楽しく読ませて頂きました。