この記事はドメイン駆動設計を取り入れたソフトウェア開発を実際にどのようなやり方で進めているかの事例紹介です。
2021年10月のモデルベースで要件定義をやってみた - connpassで発表した資料の解説です。
設計の効果
良い設計は悪い設計よりも変更が楽で安全です。
ドメイン駆動設計は、そういう良い設計を目指すための設計の考え方とやり方の一つです。
ドメイン駆動設計の特徴は次の2つです。
ドメインとはソフトウェアの対象領域です。業務アプリケーションであれば、事業活動がドメインです。この記事では、ドメイン(事業活動)に焦点を合わせたクラス設計の考え方とやり方の基本的な流れを紹介します。
画面やユースケース中心のソフトウェア開発
アプリケーション開発でありがちなのは、画面やユースケースを要件として定義して、画面の入力をデータベースに記録しデータベースから取り出したデータを画面に表示するためのコードを書く、というやり方です。
その結果、どこに何が書いてあるかのわかりにくく、ちょっとした変更が思わぬ副作用を引き起こす変更がやっかいで危険なプログラムになってしまいます。
モデルベースの要件定義
このような問題を解決するために考案された要件定義の手法がRDRA(ラドラ)です。 バリューソースの神崎さんが提唱されたモデルベースで軽量で柔軟な要件定義手法です。
ソフトウェア開発の視点を増やす
- ビジネスユースケースと業務フロー
- ビジネスルール
- 業務上で意識している状態の遷移
- 業務で関心のある情報
画面やユースケースを個別に定義するだけでは見落としがちな、さまざん情報を取り入れることで、いままではっきりしなかった画面やユースケースの目的や、画面間・ユースケース間の関係が見えるようになります。
関係づけて考える![RDRA 2.0 関係で考える](https://cdn-ak.f.st-hatena.com/images/fotolife/m/masuda220/20211102/20211102071213.jpg)
関係で考える
![RDRA 2.0 関係で考える](https://cdn-ak.f.st-hatena.com/images/fotolife/m/masuda220/20211102/20211102071213.jpg)
RDRA(Relationship Driven Requirement Analysis)の特徴は、関係(relationship)で考えることです。
さまざまな視点の情報を関係づけることで、情報の意味が明確になります。また関連づけて考えることで、それぞれの視点だけでは見落としがちな情報を発見できます。
要件モデルの品質をあげる
複数の視点を関連づけることで、それぞれの視点のゆがみや、視点間の不整合が見つかり、ゆがみや不整合を修正することで、要件モデルの品質が向上します。
事業活動と関係づける
さまざまな視点のモデルを総合的に関連づけるために役に立つのが事業活動の俯瞰モデルです(図の左上)。 事業活動は、さまざまな業務活動をばらばらに進めているわけではなく、お互いに関連しながら活動しています。表面的にはわかりにくいかもしれませんが、企業は収益を上げ続けるための組織的な行動をするための仕組みです。すべての活動はなんらかの形でつながっています。
事業活動まで視野を広げることで、要件定義のさまざな視点の情報を適切に関連づけ、全体を一貫したモデルとして体系だてることができます。
ドメイン駆動設計
事業活動にまで視野を広げることはドメイン駆動設計というソフトウェア開発のやり方の必要条件です。
しかし、事業活動まで意識してソフトウェア開発をすることのたいせつさは、ドメイン駆動設計に限らず、さまざなソフトウエア開発の考え方で強調されています。
ではドメイン駆動設計ならではの特徴とはなんでしょうか?
エヴァンスの『ドメイン駆動設計』に書かれている内容の中でも、ドメイン駆動設計ならではの特徴がはっきりと表れているのは次の3つの章です。
- 第3章 モデル駆動設計(モデルと実装を結びつける)
- 第10章 しなやかな設計(ソフトウェアの変更を楽で安全にする)
- 第15章 蒸留(コアドメインに集中する)
この三つの章は『ドメイン駆動設計』の中では、読みにくい箇所かもしれません。エヴァンスが何を伝えたいのか私も最初はチンプンカンプンでした。しかしアプリケーション開発の現場で、変更を楽で安全にするための良い設計を模索し、この本を何度も読み返す中で、この三つの章がドメイン駆動設計の考え方とやり方の要点であることがだんだんとわかってきました。 この三つの章が理解できると、他の章を読む時に、この三つの章の準備や応用として位置付けて解釈ができるようになります。
事業活動に焦点を合わせる
技術者にとっては最初は事業活動のモデルといってもぼんやりとした、おそらくはまちがったイメージしか持つことができません。しかし、ソフトウェアの開発を通じて、一貫して事業活動を意識しつづけることで、しだいに事業活動のモデルがしっかりしたイメージになってきます。
事業活動のモデルをしっかりと認識できるようになった開発チームの生み出すソフトウェアは、事業活動に適切な価値を提供することができるようになります。
事業活動の仕組みと決め事の言語化(可視化)
しかし、事業活動の知識が増えただけでは、良い設計はできません。良い設計をするために重要なのは、事業活動の仕組みと決め事(ビジネスルール)を言語化し可視化する活動です。
アプリケーションが複雑になる大きな要因は、事業活動の仕組みと決め事が複雑だからです。事業活動の仕組みと決め事を整理して扱いやすくすることは、アプリケーションの複雑さを整理し扱いやすくすることに直結します。
ビジネスルールをソフトウェアで表現する
オブジェクト指向プログラミングの技法といっても難しい話ではありません。
- 業務的に関連するロジックとデータを一つのクラスのまとめる(カプセル化)
- クラス名やパッケージ名に業務の用語をそのまま使う
- クラス間の関係、パッケージ間の関係を業務の構造と一致させる
の三つを地道に丁寧に実践するだけです。
この活動は難しいわけではありませんが、時間がかかります。ロジックとデータのうまいまとめ方や良いクラス名や良いパッケージ名が最初から見つかるわけではありません。
継続的なリファクタリング(設計改善)
ある時点の理解をもとに試しに作ってみて、作ってみた内容を関係者で評価しながら、ぎごちなさや分かりにくい箇所をよりよい設計に改善を試みる。こういうリファクタリングの活動が延々と続くのがドメイン駆動設計というソフトウェア開発のやり方です。
そして良い設計を目指したリファクタリング(設計改善)を地道に丁寧に続けるから、変更が楽で安全なソフトウェアに育てていくことができるのです。
収益構造と事業方針に焦点をあわせる
中核の課題に焦点を合わせる
ドメイン駆動設計の費用対効果をあげるために、設計改善の対象を絞り込み、その対象とする範囲の設計改善に集中することが重要です。
もちろん、どこに集中すればよいかを特定すること自体がたいへんな活動になります。しかし、どこでもいいからせっせとリファクタリング、というアプローチと、どこに集中すべきかを模索しつづける、というアプローチとでは、生み出す成果に大きな違いが生まれます。
収益構造と事業方針を理解して設計する
どこに集中すべきかの模索の重要な手がかりが、その事業の収益構造と事業方針です。
収益構造は売上 ー 費用です。売上をどうやって生み出していて、どこに費用が生まれているか、という仕組みを理解することで、どこに集中すべきかを判断しやすくなります。 そして、事業活動には必ず独自の事業方針があります。ビジョンやミッションという抽象度の高い方針の理解も有用ですが、ソフトウェア開発に直接的に役に立つのは、もっと具体的な決め事として現れる事業方針です。
具体的な決め事に焦点を合わせる
たとえば、価格設定のルールや割引適用のルールです。 あるいは、いつ何をどのくらい発注するかの決め事や、キャンセル・返品・返金に関する決め事です。 これらの決め事は基本は単純ですが、実際の業務では、顧客のカテゴリー、商品の種類、取引先との関係、季節や時間による条件分けなど、さまざまな要素が複雑に絡み合ってきます。
これらの決め事は、安定した収益を確保し、事業を存続させ発展させるための決め事です。こういう決め事に焦点を合わせることで、設計を重点的に改善すべきクラスやパッケージを特定する手がかりが得られます。
全体への波及
重点対象としたクラスやパッケージの設計改善を続けると、結果的にはそれ以外のクラスやパッケージの設計も改善されます。さまざまな事業活動やそのための仕組みと決め事はなんらかの関係でつながっています。収益構造や事業方針に直結するクラスやパッケージを集中的に改善することで、そのクラスやパッケージに隣接したクラスやパッケージの改善が進みます。そういう隣接したクラスやパッケージの改善がさざ波のようにアプリケーション全体につながっていくのです。
事業方針とコードを直接的に関係づける
収益構造や事業方針はソフトウェアの設計や実装から遠く離れた関心事ではありません。日常の設計活動に直接的に関係します。
たとえば、このクラスとパッケージを分割すべきかいっしょにすべきか、という開発現場の日常的な迷いの答えも、事業方針を考えれば、明確な指針が見つかります。 汎用的なAPIにすべきか、ビジネスルールの違いを反映した個別のAPIに分割すべきかの答えは、事業活動の仕組みと決め事、今後、どのように事業を発展させていきたいかの方針から判断すべき設計課題なのです。
こういう設計を日々くりかえすことが、私が実践しているドメイン駆動設計というソフトウェア開発のやり方です。
ドメイン駆動設計の主活動と補完活動
主軸の設計活動と補完する設計活動は相互に関連します。
主軸となるドメインモデルのクラス設計をするときには、画面やユースケースの視点から設計の妥当性を検証します。画面やユースケースを実現するためのクラス設計は、ドメインモデルのクラス設計の視点から検証します。
こういう双方向の設計のフィードバックがより良い設計を生み出します。