Rindrics Mumbles

第 1 章: ドメイン駆動設計入門

“1. Introducing Domain-Driven Design” from “Domain Modeling Made Functional: Tackle Software Complexity with Domain-Driven Design and F#)” 📚

開発者の仕事:

  • not only コードを書くこと
  • but also ソフトウェアを通して問題を解決すること

📝 ソフトウェア開発では “garbage in, garbage out” とよく言うが、ここでは想定しているレイヤが高度なのが印象的だった:

  • ふつうはソフトウェア自体への入力と出力について表すフレーズ
  • ここでは input が「要件」、output を「価値」としており、かなり高レイヤ

要件が不明瞭だったり、設計が悪ければコーディングをどれだけ頑張ろうとよい価値は得られない。

“garbage in” を減らすのに必要なもの:

  • 明解なコミュニケーション
  • 共有ドメイン知識に基づく設計アプローチ

つまりドメイン駆動設計が必要。

共有モデルの重要性

まず開発者が問題を正しく理解することが重要

とりうるアプローチを 3 つ紹介:

  1. 仕様書・要件定義書を整備する 💣
  2. ドメインエキスパートを開発プロセスに入れる ⚠️
  3. ドメイン駆動設計 ✅

1. 仕様書・要件定義書を整備する 💣

これはだめなやり方。

理由:

  • ドメインエキスパートと開発チームの距離が遠くなってしまう
  • “伝言ゲーム” のようなことが実際に起こり、これはプロジェクトにおいては致命的

2. ドメインエキスパートを開発プロセスに組み込む ⚠️

一見良さそうに思えるがベストではない。

誤りをすぐに修正できるようにするために、ドメインエキスパートを開発プロセスのフィードバックループに組み入れる。 いわゆるアジャイルなやり方。

デメリット:

  • 開発者の働きがドメインエキスパートのメンタルモデルの単なる翻訳者でしかなくなってしまう
  • 必ず抜け落ちてしまう情報がある
  • 将来、ドメインエキスパートからの入力なしにコードをメンテする開発者は容易に方針を誤ってしまう

3. ドメイン駆動設計 ✅

下記の 3 者が共通のメンタルモデルを共有した状態:

  • ドメインエキスパート
  • 開発者
  • ステークホルダー

ソフトウェアのコードはメンタルモデルを直接反映したものになるので、DDD では"翻訳"という作業は存在し得ない。

DDD のメリット:

  • 市場投入スピード
  • 得られるビジネス価値の大きさ
  • 無駄の排除
  • スムーズな維持修正

(コラムでは、開発者自身がドメインエキスパートになる重要性が示されている)

共有メンタルモデルを作るためのガイドライン:

  • データ構造ではなく、ビジネスイベントとワークフローに着目せよ
  • ドメインを小さいサブドメインに分割せよ
  • それぞれのサブドメインについてモデルを作れ
  • 会話やコードで使われる共通言語を作れ

ビジネスイベントからドメインを理解する

共有メンタルモデルの構築はどこから始めたらいい?

イベントから始めよ。データ構造ではなく。

理由:

  • ビジネスがデータをただ持っているだけで終わることは有り得ないため
  • ビジネスは何らかの方法でデータを変換するため

ビジネスプロセスとは、データやドキュメントの変換処理の集まり。

なのでこれらの変換がどう行われ、どう関連しているかを理解することが重要。

使われずにただ置かれているだけのデータは何の価値も生まない。 これらのデータから価値を引き出すためのプロセスはどうやって始まるか?

  • 外部トリガー
  • スケジュールに基づいたトリガ
  • 観測に基づくトリガー

これらをドメインイベントという。 ドメインイベントは事実である変化しないため必ず過去形で表現される。


(中略)

下記の 2 節で、イベントストーミングの説明と実例が書いてある:

  • Using Event Storming to Discover the Domain
  • Discovering the Domain: An Order-Taking System

イベントストーミング自体を理解するには提唱者の解説を読むほうがいい。

イベントストーミングで重要な点:

  • 「“我々” vs “彼ら” 思考」から脱却できること
  • 意見が合わなかったら、それは問題ではなくチャンス

イベントを境界にまで拡張する

要件の取りこぼしを防ぐために下記に注意を払う:

  • 最初のイベントと思っていたイベントをトリガーする他のイベントがないか
  • 最後のイベントと思っていたイベントにトリガーされる後続のイベントはないか

全てを一気に変える必要はない。最も価値を生む一部分から取りかかれ。

コマンドを記述する

イベントストーミングによってイベントが見えるようになった。 「何がこれらのイベントを生むのか」と思うだろう。

例:

  • 顧客は我々に注文書を受け取ってほしい
  • 上司があなたに何かをしてほしい

DDD ではこれらをコマンドという。 コマンドは常に命令形で表現される。 紛らわしいが、OO のコマンドパターンとは違う。

コマンドが成功するとワークフローがトリガーされ、ドメインイベントが作られる。

例:

  • 「X を起こせ」というコマンドによってワークフローが X を起こし、「X が起こった」というドメインイベントが発行される
  • 「注文書を会社 A に送れ」というコマンドによってワークフローが注文書を送ると、「注文書が送信された」というドメインインベントが発行される
  • コマンド「注文を確定せよ」 → ドメインイベント「注文が確定された」
  • コマンド「発送を顧客 B に送れ」 → 「発送が送られた」

📝 「発送が送られた」は日本語としておかしいが、DDD ではモデルを記述する用語(ユビキタス言語)が重要なのでこのままにしておく。原著が英語なので限界がある。自然な日本語にしようとして「発送」の代わりに「商品」とするのは絶対に NG。いずれにせよ、ドメインエキスパートが使う言葉に合わせることが重要。

これから、コマンド、ワークフロー、イベントの組み合わせでビジネスプロセスを記述していく。 これはまさに関数プログラミングの動きと同じ。

全てのイベントがコマンドに紐付いている必要はない。 スケジュールによるトリガーや監視に基づくトリガーなどがあるため。


comments powered by Disqus