「ドメイン駆動設計を始めよう」 の個人的まとめ
はじめに
こちらは Kyash Advent Calender 2024 の6日目の記事です。
Kyashでサーバーサイドの開発をしているgop50kです。
この記事では最近読んだ書籍 オライリー 「ドメイン駆動設計を始めよう」のまとめとして個人的に興味が湧いた箇所を抜粋しながら書いていこうと思います。
そもそもなぜドメイン駆動設計を採用するのか
ソフトウェアの開発はとても難しいです。
既存または新たな技術の把握、採用する技術方式が要件を満たすことができるのかPoCを回します。複雑な仕様を実現させるために書かれるビジネスロジックはスマートであるべきで、煩雑であってはいけません。
それらを統合して進める上で、上手くいっていない場合は納期の遅れや予算の超過、メンテナンスしづらい技術的負債を生んでしまいます。
ドメイン駆動設計はそれらを軽減させ、プロジェクトを成功に導くことに一役を買います。実装者と業務のエキスパートの間の意思疎通の伝達効率を上げて、間違った仕様で実装されることを防ぎ、適切な粒度でモデル分けやコンポーネント同士の繋ぎ込みを行うので、将来的にメンテナンスしやすい良いプロダクトを作ることができます。また、整ったコードを読む事で開発者も事業活動を一段と理解しやすくなります。本書で一貫して書かれていることは、開発者も業務理解を進めることで結果的に良いプロダクトを良い方法で作れるということです。
各章から興味深い箇所を抜粋しながら紹介していきます。
- 設計の基本方針
- 実装方法の選択
設計の基本方針
基本的に業務領域を下記のように分けます。これによって各領域の特徴の理解に繋がり、適切なリソース分配やモデル分け、設計方針を考えることの助けとなります。ちなみに、ここでいう業務領域とは事業活動の領域全体を細分化したものです。例えば、AmazonならEコマース、AWS、Amazon Logistics(物流・配送)などがそれぞれ業務領域として挙げられます。
-
中核
その会社にしか無い強みの部分で、コアコンピタンスの部分となります。例えばGoogleだと、提供している検索エンジンの順位付けアルゴリズムなど。他社が容易に真似できない分野のことで、この中核こそが事業の価値となり、お金を産む部分だと言えます。とても大事な部分です。大事な部分ですのでコード量は多く、変化も激しい分野になります。したがって、開発の基本方針としては内製で作っていくべきで、適切なコンポーネントで分けられていくことが必要なので、その分野のエキスパートを開発に割り当てるべきでしょう。 -
一般
どの会社でも行われている分野です。例えば認証認可の仕組みなど。ソフトウェア開発において必須となる部分ですが、一定の水準まで達していれば特に競争優位性を産みません。言い換えるとネットに答えが落ちている部分となります。信頼性の高い枯れた既存のパッケージなどを採用するのも費用対効果としては良いです。 -
補完
こちらも競争優位の源泉にはなり得ない分野です。基本的なCRUD機能など、業務ロジックが少なめの部分。このことから開発を外部に依頼することもできます。 -
同じ言葉(ユビキタス言語)
業務領域の考え方ではありませんが、事業活動を理解して実装を進めるための役に立つ手法として「同じ言葉」を使う、というものがあります。プログラムは仕様書を翻訳しただけであるという考え方のもと、プログラムの中でも業務エキスパート(プロダクト責任者、CS、デザイナーなど専門分野で信頼できる人)が使用している言葉と同じものを使います。それを続けることによって、チームの中で言葉の意味が育っていき、意思疎通の効率も上がっていきます。そのためには開発者もチームメンバーと同じ目線で、同じ言葉を使い会話をしていくことが重要です。
実装方法の選択
業務ロジックを表現するための実装方法には値オブジェクト、 レイヤードアーキテクチャなどがあります。その中でもイベントソーシングの考え方について書きます。
まずは下記の”販売管理システムの、見込み客の状態に関するデータ”を見てください。
[
{
"lead-id": 12,
"event-id": 0,
"event-type": "新規登録",
"last-name": "田中",
"first-name": "太郎",
"phone-number": "555-2951",
"timestamp": "2020-05-20T09:52:55.95Z"
},
{
"lead-id": 12,
"event-id": 1,
"event-type": "架電",
"timestamp": "2020-05-20T12:32:08.24Z"
},
{
"lead-id": 12,
"event-id": 2,
"event-type": "商談予定設定",
"followup-on": "2020-05-27T12:00:00.00Z",
"timestamp": "2020-05-20T12:32:08.24Z"
},
{
"lead-id": 11,
"event-id": 3,
"event-type": "連絡先変更",
"last-name": "山田",
"first-name": "花子",
"phone-number": "555-8101",
"timestamp": "2020-05-20T12:32:08.24Z"
},
{
"lead-id": 12,
"event-id": 4,
"event-type": "架電",
"timestamp": "2020-05-27T12:02:12.51Z"
},
{
"lead-id": 12,
"event-id": 5,
"event-type": "注文受領",
"payment-deadline": "2020-05-30T12:02:12.51Z",
"timestamp": "2020-05-27T12:02:12.51Z"
},
{
"lead-id": 12,
"event-id": 6,
"event-type": "支払い完了",
"status": "成約",
"timestamp": "2020-05-27T12:38:44.12Z"
}
]
上記はイベントソーシングを採用したテーブルのレコードの状態です。
なんとなく、顧客が今どんな状況なのでテーブルを眺めるだけでなんとなく分かってきます。lead-id 12の田中さんが新規登録して、電話をかけ、商談をして、成約したのかな?というところまで読み取れると思います。
このようにイベントソーシングは、ある対象ごとのデータを時系列とともに表現します。ここではある見込み客の管理番号や氏名、電話番号などが纏まっていて、どの時間にどの商談プロセスが行われたか追跡可能な状態になっています。また、資料を漁らなくても商談プロセスがどのような流れになるかもデータの流れから推測できます。ちなみに、event-type では業務エキスパートが使っている用語と同じ言葉を使用しています。こうすることで分析者もデータの内容を把握できます。
もう少し深掘りして、イベントソーシングのメリットは下記です。
-
タイムトラベル
永続化しているので、その状態に戻すことができます。例えば障害が起きた場合の状況を詳しく調べたり、ロールバックができます。 -
深い洞察
同じ言葉を使っていたり、適切なモデル分けがなされたイベントソーシングを使ったテーブルは優れた情報源となり得ます。分析業務の材料になる可能性があります。
監査ログ
この考えは特に金融系のシステムで役に立ちます。時間とともに残した詳細なログは、どのような処理が行われたのか追跡に使用できます。そもそも、監査ログを法的に残さなければいけない場合もあります。
対して、デメリットも存在します。
- 学習コスト
イベントソーシングに触れていない開発者からすると、最新の状態のみを永続化させる従来のやり方と違い、一連のデータの流れを表現するこの手法は少し慣れるまで時間がかかるかもしれません。 - 拡張性
データ構造の変更が容易ではありません。事前に適切な粒度での業務イベントのモデル分けが必要です。
さいごに
今回この記事では、ほんの少しだけドメイン駆動設計についての手法を書きました。現場で採用されている手法や設計方針の多くがこの本に書かれていて、まるで答え合わせをしているようでした。チーム開発を行われている多くの方が共感しながら読む事ができる書籍だと思います。0->1 で開発する際なんかは何も無い所から上手く設計をしつつ並列して実装をしていく必要があると思うので、良い地図になりますね。設計で迷ったらまた戻ってきて参考にしていきます。
Discussion