この記事は クラウドワークス Advent Calendar 2021 の 21日目の記事です。
はじめに
こんにちは!
欧州サッカーと総合格闘技と酒とドメイン駆動設計が好きなエンジニアの@d4teです。crowdworks.jpというプロダクトの施策チームでリーダーをやっています。
自分はドメイン駆動設計が好きで、その中でも解決すべき課題を明確にしソフトウェアの価値を高めるドメインモデルの考え方が好きです。
この記事ではドメインモデルの素晴らしさを伝えるべく、ドメインモデルとそれを取り巻く周辺の概念について説明していこうと思います!
※ ValueObjectやRepositoryなどドメイン駆動設計の設計パターンについてはこの記事では言及しません。
そもそもソフトウェアを開発する目的って?
多くの場合は「ソフトウェアによって何らかの問題を解決するため」と言えると思います。そして問題を解決するためには問題や問題を取り巻く世界について学ぶ必要があります。
例えば会計システムを開発するためには会計業務を学ぶ必要がありますし、採用管理システムを開発する場合は採用業務を学ぶ必要があります。
そしてその学習で得られた問題解決に貢献する重要な知識をドメイン知識と呼びます。ドメイン駆動設計は最も重要であるドメイン知識を発見し、他の技術的関心事などから遠ざけることによって、ソフトウェアを変更容易で継続的に問題を解決し続けるものにするための設計思想です。
ドメインとは何か
ソフトウェアによって何らかの問題を解決するため
ソフトウェアを開発する目的を上記のように言いました。
ドメインとは問題解決のためにソフトウェア化しようとする対象の領域のことを指し、問題領域とも呼びます。
例えばECサイトであれば「問題」は下記のようなイメージです。
- 商品を購入したい
- 支払いを行いたい
- プロダクトの健全性を維持したい
そして、ドメインは問題をソフトウェアによって解決する領域として解決領域を持っています。
解決領域
ドメインに存在する問題をソフトウェアによって解決する領域(=境界づけられたコンテキスト)のことを解決領域と呼びます。
解決領域には問題を解決する手段であるユースケースと問題の解決に必要な概念であるドメインモデルが存在します。それぞれ後述します。
わかりにくいので図で表現してみる
「インターネットでモノを販売したい」というドメインとその解決領域を下記のように表現してみました。
一番抽象度の高いレイヤーに「インターネットでモノを販売したい」というドメインが存在し、さらにそれぞれ複数の関心事単位でドメインが存在しているイメージです。それぞれのドメインの問題をソフトウェアによって解決する領域が存在し、その中にはユースケースとドメインモデルが存在します。
ユースケース
ドメインに存在する問題を解決するための手段をユースケースと呼びます。
ユースケースはユーザーの要求に対して実行されるべきシステムの振る舞いを意味しています。
また、ユースケースを実行できるのはアクターと呼ばれる概念です、アクターはシステム内でユーザーがなることができる役割を意味しています。
ECサイトであれば出品者 / 店 / 管理者などがいると考えます。
例えば下記などはユースケースに該当します。
- 顧客として商品をカートに入れる
- 顧客として商品を購入する
- 管理者として誹謗中傷コメント投稿者を凍結する
ドメインモデル
ドメインに存在する問題を解決するためのモデルをドメインモデルと呼びます。
ドメインモデルはドメインに存在する物事の特定の側面を抽象化1したものです。
※ ActiveRecordなどDBアクセス効率化の文脈で語られるモデルとは別概念です。
定義だけだと理解しづらいのでサッカーのユニフォームを例に説明してみる
自分はサッカーが好きなので、サッカーのユニフォームを使ってドメインモデルを説明してみようと思います。
この画像は自分が購入したサッカーのユニフォームで、一見選手が着ているユニフォームと同じように見えますが、実は結構違います。
ユニフォームを初めて購入しようとした時に店員さんに違いを聞いてみたところ下記のように違うことがわかりました。
さらに「なぜ実際に選手が着ているものと性能が違うんですか?」と質問したところ、店員さんは
「ファンが購入するユニフォームは観戦を目的として作られており、ファンとして長い間ユニフォームを着用できるよう耐久性を重要視しています、逆にサッカーをプレーする目的では作られていないため、伸縮性や通気性などの性能はありません。」と教えてくれました。また、選手が着用しているユニフォームを「オーセンティックユニフォーム」、ファンが観戦の時に着用するユニフォームは「レプリカユニフォーム」と呼ばれているとも教えてくれました。
つまり選手が着用している「オーセンティックユニフォーム」では通気性や伸縮性という要素を必要としていますが、耐久性という要素は捨てています。
一方で自分が所有している「レプリカユニフォーム」は耐久性という要素を必要としていて、通気性や伸縮性などの要素は捨てている、と言えます。
そしてこれらをドメインに存在する問題を解決するためのモデルという定義から考えると、下記のように言えます。
- オーセンティックユニフォーム(実際に選手が着用している)
- 快適にプレーしたいというドメインの問題解決に貢献
- レプリカユニフォーム(ファンが観戦などの時に着用している)
- ファンとして長くサッカー選手を応援したいというドメインの問題解決に貢献
それぞれ異なるドメインの問題解決を関心としたドメインモデルと言えます。
このようなドメインの問題を解決するための要素の取捨選択(抽象化)するプロセスをドメインモデリングと呼び、得られたモデルをドメインモデルと呼びます。
そして問題解決に貢献する有能なモデルを得るためにはドメインエキスパートと呼ばれる、ドメインに詳しい人と共にドメインを学習し、ドメインモデリングしていくことが重要です。
ドメインモデルと境界づけられたコンテキスト
境界づけられたコンテキストは解決領域のことを指していて、ドメインモデルを同じ意味で利用できる範囲を定義するものです。
境界づけられたコンテキストによって、ドメインモデルの精度を向上させることができます。
サッカーのユニフォームを例に説明しようと思います。
境界づけられたコンテキストを意識せず、愚直にユニフォームとして考えれば下記のようなドメインモデルになります。
簡単な例なので問題はないように見えますが、これではチームメンバーとのコミュニケーションで「オーセンティックユニフォーム」のことを話しているのか「レプリカユニフォーム」について話しているのか混乱しやすくなり、かつこのように概念同士を一緒くたにするとFatになっていきます。
境界づけられたコンテキストを意識すれば本来分けるべき概念が分離され、コミュニケーション齟齬などを減らすことができ、かつ複数の意味を持ったFatなモデル等を防ぐことができます。
実際の機能開発でどのようにドメインモデルを発見するか
ここでは自分が概念整理のために行うドメインモデリングのやり方について書いてみようと思います。
実際にヨーロッパの某プロサッカーチームが運営しているチケット販売サイトの1機能を例にドメインモデリング をしてみようと思います。
※ ホームの試合はホームチームがチケットを販売するという文化になっているため、各サッカーチームが独自のチケット販売サイトを持っている2
ドメインモデリングの手順は下記になります。
- モデリング対象のユースケースの詳細を書き出す
- 要件からドメインモデルを抽出する
- ドメインモデル図を作成する
- 発見したドメインモデルをソフトウェアに落とし込む
モデリング対象のユースケースの詳細を書き出す
今回は「試合のチケットを選択する」というユースケースをモデリングしてみようと思います。
ユースケースの仕様は下記になります。
-
「チケットを選択する」の意味
- アクター: サイト内会員
- 観戦したい試合を選択する
- 試合選択後、観戦場所となる座席を選択する
- チケット購入に必要な金額が閲覧できる
-
要件
- 全ての座席には基本料金が設定されている
- 座席には観戦する場所(エリア)ごとに料金が設定されている
- 座席の料金は基本料金とエリアごとの料金の合計で決定する
- 座席と試合の料金の合計が請求される金額となる
- 会員には一般会員とVIP会員が存在している
- VIP会員は試合開催予定日の2週間前に試合を選択可能
- 一般会員は試合開催予定日の1週間前に試合を選択可能となる
※ 今回は購入(支払い)は含めません
このタイミングでユースケースの実行者であるアクターが誰なのかも明らかにしておいた方が良いです。
今回の例では会員登録を済ませた人がアクターですが、サッカーチームのチケットは旅行代理店なども代行販売していることがあり、そのために「旅行業者としてサッカーチームからチケットを選択/購入する」している可能性があります。その場合、一般会員が解決したい課題と旅行関係業者が解決したい課題が異なる可能性も高く、モデリングの精度も曖昧になりやすいためです。
要件からドメインモデルを抽出する
自分は要件に書かれた名詞がドメインモデルになる可能性が高いと考えます。
なので次はユースケースの要件に存在する名詞を抜き出してみます
- 会員
- マッチ(試合)
- サッカーでは試合のことをマッチと呼ぶことが多い気がしたのでマッチにしてみる
- 座席
- 基本料金
- チケット
- 座席エリア
- エリア料金
- 請求金額
- 試合開催予定日
ドメインモデル図を作成する
そしてクラス図のようにドメインモデルを関連づけ、モデルに関連する知識やルールも書き出していきます。
発見したドメインモデルをソフトウェアに落とし込む
このプロセスをドメインエキスパートや他のチームメンバーと議論しながら行うことで、開発に関わるメンバー全員でドメインに詳しくなり、同時に開発メンバーとの認識を合わせることが可能です、それに加えてドメイン駆動設計は発見したドメインモデルをソフトウェアとして表現するためにEntityやValueObjectなど強力な設計パターンも兼ね備えています。これによって発見したモデルを高品質でソフトウェア化することが可能となります。
まとめ
- 問題解決のためにソフトウェア化しようとする対象の領域をドメイン(問題領域)と呼ぶ
- ドメインに存在する問題をソフトウェアによって解決する領域を解決領域と呼ぶ
- ユースケースはユーザーの要求に対して実行されるべきシステムの振る舞いを意味する
- ドメインモデルはドメインに存在する物事の特定の側面を抽象化したもの
- 境界づけられたコンテキストはドメインモデルを同じ意味で利用できる範囲のこと
- ドメインモデルはユースケースの仕様などから発見できる
- ドメインモデル同士の関連 / 知識 / ルールをドメインモデル図に記入するとドメインが理解しやすくなる
- ドメインモデリングによってチーム全員でドメインに詳しくなる
おわりに
ドメインモデルとそれを取り巻くドメインやユースケースなどの概念を説明し、あわせて自分が日頃行っているドメインモデリングについても書いてみました。
この記事がソフトウェアの価値を高めるための一助になれば嬉しいです!