Open18

ドメイン駆動設計をはじめよう 読書ログ

yusukeyusuke

前提

原語 従来 本書
domain ドメイン 事業活動
subdomain サブドメイン 業務領域
domain logic ドメインロジック 業務ロジック
domain event ドメインイベント 業務イベント
Ubiquitous Language ユビキタス言語 同じ言葉
Bounded Context 境界づけられたコンテキスト 区切られた文脈
Context Map コンテキストマップ 文脈の地図
Shared Kernel 共有カーネル モデルの共有
Anticorruption Layer 腐敗防止層 モデル変換装置
Separate Way 別々の道 互いに独立
yusukeyusuke

はじめに

  • ソフトウェア開発が失敗する主な理由の共通点はコミュニケーション = 「意図の伝達」
yusukeyusuke

1章

事業活動を分析する

  • 事業活動を業務領域に分解し、3つのカテゴリーに分類する(中核・補完・一般)
  • 業務領域とは事業活動の一部
    • カフェならコーヒーの淹れ方だけでなく、よい立地への出店・採用・卸・集客イベントなど事業を成功させるための業務領域という位置づけ
  • 中核の業務領域
    • 競合他社との違いを生み出す業務活動
    • この領域が単純だと参入障壁が低くなり競合優位性が保ちにくくなる
    • 終わりはなく常に改善を重ねる部分
  • 一般の業務領域
    • 競争優位は生み出さない
    • どの会社も同じ
    • 認証認可など自作ではなく、既存の信頼性のあるサービスを利用するもののイメージ
    • ここに時間をかけるよりかは信頼できるサービスを利用してしまった方が費用対効果は高い
  • 補完的な業務領域
    • 競争優位は生み出さない
    • CRUD機能などのイメージ
    • あまり変化がしない部分

感想

  • 業務領域を分解し特定することで何となくではなく、どこに注力するかを明確にできる
  • そもそも事業活動の中核の部分は競合優位を生み出すために複雑化しやすい
yusukeyusuke

2章

業務知識を発見する

  • 本番環境にリリースされるのは開発者の理解(あるいは誤解)であり、業務エキスパートの知識ではない
  • 効果的な意図の伝達が知識の共有とプロジェクトの成功に不可欠
  • ドメイン駆動設計は同じ言葉を使って業務エキスパートからソフトウェア技術者に業務知識を伝える手法
  • 同じ言葉には技術的な用語は出てこない・含めない
  • モデルは現実世界そのものではなく、特定の課題に対して解決する目的に沿った内容・情報の表現
    • 例: 地図・地下鉄の路線図など

感想

  • 「同じ言葉」は育てていく感じであり、そのためには業務エキスパートとの日常の会話が重要である
  • 同じ言葉を育てることやモデリングしていくことで業務エキスパートの理解と開発者の意図が一致した状態で本番環境に反映される
yusukeyusuke

3章

事業活動の複雑さに立ち向かう

  • 同じ事業活動でも業務エキスパートによって解釈が異なる場面もある
    • 例: 見込み客(営業と販売促進の部門によって言葉は同じでも意味が違う)
  • 文脈の識別子を付与するやり方は好ましくはない(営業の見込み客・販売促進の見込み客など)
    • 理由1: 1つの言葉を異なる意味で使い分けることは認知負荷が高くなる
    • 理由2: 2つのモデルが混在したコードは同じ言葉の考え方と一致しない(人間は話の文脈から意味を判断できる)
    • このようなことをうまく扱う手法が区切られた文脈
  • 同じ言葉を複数の小さな同じ言葉に分割し、文脈にを区切る
    • これによってそれぞれの文脈の内部では、言葉の意味(ここでは見込み客)は1つになる
    • 販売促進の文脈における見込み客と営業の文脈における見込み客というように文脈を区切り、その中で見込み客という言葉の意味は1つになるイメージ
  • モデルには必ず境界があり、その境界こそが区切られた文脈である
    • 再喝: モデルは現実世界のコピーではなく、複雑である現実を理解するための簡略化
    • モデルで解決しようとしている課題・目的が重要
  • 同じ言葉は区切られた文脈の境界の内部に限定される(組織全体で同じ言葉を使うということではない)
  • 業務領域は「発見」であり、区切られた文脈は「設計」
    • 区切られた文脈はソフトウェア技術者による意思決定
    • 1つの業務領域に1つのモデルという固定概念は捨てる

感想

  • 同じ言葉は区切られた文脈の教会の内部に限定されるということを改めて知った
  • 事業活動として解決したい課題があり、その理解を簡略化するものがモデルであり、そのモデルを文脈で区切る
  • モデルとは現実世界のあらゆる側面をそのまま再現するものではなく、目的(解決したい課題)を中心に抽象化された表現のことというようにモデルへの理解が深まった
yusukeyusuke

4章

区切られた文脈どうしの連携

  • 完全に独立したコンポーネントだけでは事業活動の課題を解決するようなシステムの構築はできないので連携が必要になる -> この接合部分を契約と表現する
  • 契約自体が必要になるのは区切られた文脈どうしではモデル・言葉が違うから
  • 契約とは利害の異なる複数の当事者間の取り決めのこと
  • 契約の手法としては3つ(緊密な協力・利用者と供給者・互いに独立)
  • 緊密な協力: 1つのチームが複数の区切られた文脈を開発する場合・2つのチームに共通の目標があり、お互いに相手チームの成功が自分のチームの成功につながる場面も同じ
    • 良きパートナー: 協力関係は双方向
    • モデルの共有: 例外的手法、1つのチームが複数の区切られた文脈を開発する場合は良い選択肢となる可能性がある(モデルを区切られた文脈で共有するということはその分だけ密結合になるので共有範囲はできるだけ小さくする)
  • 利用者と供給者の関係
    • 自分たちのチームの成功にとって相手チームの成功は必須ではない(力関係が生まれる)
    • 従属: サービスを利用する側がサービスを提供する側のモデルに合わせる
    • モデル変換装置: サービスを利用する側がサービスを提供する側のモデルを自分のモデルに合うように変換をする
  • 共有サービス
    • サービスを利用する側(下流)が決定権を持っている場合の連携方法
    • サービス提供者が公開するインターフェイスは内部で使う同じ言葉に合わせる必要はなく、連携用途に特化した言葉を定義して利用する側が使いやすいプロトコルを提供する(公開された言葉
  • そもそも連携をしないという選択肢もある(互いに独立
  • 文脈の地図(Context Map)はシステム全体をどういう文脈に分け、それらをどのように連携させるかを描いた図
    • 理想的にはプロジェクト開始時に文脈の地図を作成し、区切られた文脈に変化があった場合は都度追従するのが理想
    • 文脈の地図を書くのは大変

感想

  • 契約の方法として密接な連携か上流か下流のどちらかが力関係を生む形か(その中で変換層をもうけて自チーム側にとって不利な状況を作らないかを考える)の連携方法が書かれており、それぞれの連携方法でのメリットデメリットがわかりやすかった
yusukeyusuke

5章

単純な業務ロジックを実装する

  • 業務領域がかなり単純な場合に適したトランザクションスクリプトアクティブレコード
  • トランザクションスクリプト
    • データの一貫性を保証する必要がある
    • 成功か失敗のどちらかで終了する
    • このトランザクション管理の必要性が名前の由来
    • 補完的な業務領域に向いている -> 業務ロジックが単純
    • 区切られた文脈をつなぐときのモデル変換装置の一部として役立つ
    • 中核の業務領域に使ってはいけない -> 複雑な業務ロジックには対応できない
    • ETL的な操作に向いている
  • アクティブレコード
    • データ構造が複雑な場合に専用のオブジェクトを使う(CRUD操作のメソッドを実装)
    • 結果としてORMなどのデータベース操作フレームワークと密に結合する
    • 本質的にはアクティブレコードもトランザクションスクリプトであり、使う時も以下のように同じ
      • 補完的な業務領域
      • 一般的な業務領域ようの外部サービスとの連携
      • 区切られた文脈どうしを連携するときのモデル変換
    • 貧血ドメインモデルと呼ばれるアンチパターンだが、一つの手段ではある

感想

  • トランザクションの簡単な管理方法について復習できた
  • どういう時に使うと適しているのかという判断基準がわかりやすかった、今回でいうと業務ロジックが単純であればその時は向いているというように一つの手段として理解することができた
yusukeyusuke

6章

複雑な業務ロジックに立ち向かう

  • 複雑な業務ロジックの実装方法 -> ドメインモデル
  • ドメインモデルとはロジックとデータの両方を一体化させた事業活動を表現するオブジェクトモデル
    • ドメイン駆動設計の戦術的手法(集約・値オブジェクト・業務イベント・業務サービス)はこのオブジェクトモデルを組み立てるための部品
    • ドメインモデルを構成するオブジェクトは区切られた文脈の同じ言葉と対応しやすくなる = 業務エキスパートのメンタルモデルを表現する
  • 値オブジェクト
    • 不変(イミュータブル)なオブジェクト
    • 値オブジェクトを使うことでコードが同じ言葉を話す(プリミティブなデータ型だけを使うのではなく)
    • 業務ロジックの記述が散らばるのを防ぐ
    • エンティティは値オブジェクトとは対照的で識別子(ID)が必要
  • 集約
    • 集約はエンティティなので、一意に識別できるフィールドが必要
    • 目的はデータの一貫性であり、集約の状態を変更するには集約が公開しているメソッドを実行する
    • 公開メソッド・コマンドをパラメーターオブジェクトとして表現する2種類の実装方法がある
    • 集約に関連するすべての業務ロジックを集約にまとめる
    • 集約の境界を設計する指針: データの一貫性、なるべく小さく、結果整合性で良いものは集約の境界の外側に置く
    • 集約のルート: 外部に公開するインターフェイスやくのエンティティは1つにする
  • 業務イベント
    • 実際に起きた重要な出来事を表現するメッセージ
      • チケットを割り当てた
      • チケットをエスカレートした
      • メッセージを受け取った
      • 必ず過去形になる
  • 業務サービス
    • 集約や値オブジェクトでは表現しにくい・複数の集約にまたがる業務ロジックが見つかった場合に業務サービスを使用する
    • ステートレスなオブジェクト(なんらかの計算などをおこなう)

感想

  • 「エンタープライズアプリケーションアーキテクチャパターン」にて業務ロジックの実装方法が紹介がされ、後にドメインモデルの作り方について「エリック・エヴァンスのドメイン駆動設計」で書かれているという流れになっているのを初めて知った
  • 集約について改めて復習になった
yusukeyusuke

7章

時間軸でモデルを作る

  • イベント履歴式ドメインモデルではイベントソーシングを使って集約の状態を管理する
    • つまり、集約の状態を永続化するのではなく、集約の状態が変化したことを業務イベントで表現し、業務イベントの履歴を the source of truth として永続化する
  • イベントソーシング
    • 時間軸の視点を取り入れたデータモデル
    • 集約の現在の状態を記録する代わりに、集約のライフサイクルで発生する全ての変化を一連のイベントとして永続化する
    • 業務イベントの履歴をつかう
    • イベントソーシングを実現するにはオブジェクトのすべての状態変更をイベントとして表現し、永続化することが必要
  • イベントストア
    • 一連のイベントを永続化するデータベースのこと
    • 追記専用で変更削除はできない
    • 最低限必要な機能は取得と追記
  • イベント履歴式ドメインモデル
    • メリット: タイムトラベル・深い洞察・監査ログ・進化した楽観的排他制御
    • デメリット: 学習曲線・モデルの発展性・技術方式の複雑さ
    • イベント履歴から状態を再構築するので性能面がきになるがそもそも一つの集約のイベントが100を超えるようなシステムの場合、集約の切り方がおかしいはず

感想

  • 見込み客テーブルの表現として、商談の現在の状態がわかるように設計しているが、事業活動の本質的な部分を考えると「それがどのような経緯があって現在の状態にいったっているのか」などを最適化したいというのは自然で、何回商談して今の状態になったのか・この後もやり取りを続ける価値があるのかなど現在に至る経緯がわからない状態のテーブル設計をしてしまうと確かに困るなと感じた
    • 事業活動において中核の業務領域における複雑な状態遷移時に使うのがイベントソーシングということを学べた(状態の変化の過程を知れることなどが中核の業務領域において重要な場合に有用)
yusukeyusuke

8章

技術方式

  • レイヤードアーキテクチャ
    • 古典的な3つのレイヤー構成
      • プレゼンテーション層 -> 業務ロジック層 -> データアクセス層
    • プレゼンテーション層
      • エンドユーザーとの対話のためのユーザーインターフェースを実行する
      • 元々はGUIインターフェースだったが、最近では役割が広がっている
      • GUI・CLI・他システム連携のAPI・メッセージ通信基盤が配信するイベント購読・送出イベントを配信するためのメッセージトピックなど
      • これらはすべてシステムが外部環境からのリクエストを受け取り処理結果を伝えるためのもの
    • 業務ロジック層
      • プログラムの業務ロジックを実装し、カプセル化する役割を担う
      • システムの心臓部
      • アクティブレコードやドメインモデルなど実装する場所
    • データアクセス層
      • 永続化の仕組みと接続する機能を提供
      • プレゼンテーション層と同様に最近は1つのシステムでも複数のデータベースを利用することが一般的になってきた
    • レイヤー間の通信
      • トップダウン(プレゼンテーション層 -> 業務ロジック層 -> データアクセス層)
      • 実装場の関心事が切り離され、レイヤー間で共有する知識が少なくなる
    • レイヤードアーキテクチャの派生型
      • 追加のレイヤー(サービス層)によって拡張されることがある
      • サービス層はプレゼンテーション層と業務ロジック層との仲介役として機能する
      • 論理的な境界であり、物理的に独立したサービスではない
      • 業務ロジックのファサードとして機能する(公開するメソッドのインターフェースを定義する)
      • 利点
        • 同じサービス層を複数の公開インターフェース(GUIやAPIなど)に使用でき、アプリケーションロジックの重複がなくなる
        • プレゼンテーション層と業務ロジック層をさらに分離できる
        • 業務機能のテストがしやすくなる
    • 業務ロジックをトランザクションスクリプトアクティブレコードで実装するには向いている
    • ドメインモデルの実装をするのは困難
      • ドメインモデルで業務を表現するオブジェクト(集約と値オブジェクト)はインフラから独立し、基盤に関する知識を持つべきではない
  • ポートとアダプター
    • レイヤードアーキテクチャの欠点を解消し、複雑な業務ロジックの実装に適している
    • 本質的にはプレゼンテーション層とデータアクセス層はどちらも外部コンポーネント、つまりデータベース・外部サービス、ユーザーインターフェースフレームワークとの連携を表現するため業務ロジックを反映していない -> なのでインフラストラクチャ層に統合する
    • インフラストラクチャ層 -> アプリケーション層 -> 業務ロジック層
    • 業務ロジックは下位のレイヤーに依存していない
    • ポートとアダプターは業務ロジックを技術的な関心事から切り離せるためドメインモデルを用いた業務ロジックの実装に最適
  • コマンド・クエリ責任分離
    • ポートとアダプターとはデータの管理方法が異なる
    • CQRSは複数の永続化モデルで表現することを可能にする
    • CQRSはイベントソーシングと密接に関連する
      • イベント履歴式モデルの持つ製薬、つまりイベントを取り込んで状態を投影するのは1つの集約のインスタンスだけと言う制約に対処することだった
      • とはいえ、業務ロジックの実装方法がイベント履歴式ドメインモデルではなくもでCQRSは使用できる
    • コマンド実行モデル
      • 業務を表現するオブジェクトに対して、一貫性のある状態を読み取り、更新時には楽観的な排他制御を行う必要がある
    • 読み取りモデル(投影)
      • 投影結果のキャッシュ
      • 情報の発生元のテーブルが更新されるたびにキャッシュされたビューに変更を反映する必要がある
      • 投影の方法: 同期投影・非同期投影
yusukeyusuke

9章

通信

  • 同期式
    • 共有サービスを提供する区切られた文脈(上流)からすると、文脈固有のモデルと連携に最適化した公開された言葉の変換はAPIゲートウェイが担当する
    • 独立したAPIゲートウェイを使うことで、複数バージョンのAPIを提供しやすくなる
  • 非同期式
    • メッセージプロキシを用意する
    • 中間コンポーネントとなるプロキシがモデル変換を行い変換したメッセージを購読者に転送をする
    • モデルの変換が不可欠で、そのまま公開された言葉として外部に出すのはありがちな間違った設計
  • 状態ありのモデル変換
    • 複数のデータを1つにまとめたい
      • AWS Kinesis、AWS Glueなどが利用できる(ストリーム式の変換で複数のデータを1つのデータにまとめる)
    • さまざまな発生元からのデータを統合して単一のモデルに変換したい場合
      • BFF
      • ユーザーインターフェースが複数のサービスからデータを集めて組み立てなければいけない状況
  • 集約どうしの連携
    • 集約が他のコンポーネントと連携するやり方として業務イベントの発行がある
    • 集約の内部から業務イベントを発行するのは良くない
      • データベースに新しい状態をコミットする前に業務イベントを外部に発信している点
      • データベースへのコミットが失敗した場合
    • 送信箱(Outbox)を使う
      • 更新された集約の状態と業務イベントの両方を1つのトランザクションとしてデータベースにコミットする
      • 中継サービスは新規にコミットされた業務イベントを読み取る
      • 中継サービスは読み取った業務イベントをメッセージ通信基盤に発行する
      • メッセージ送信が成功した場合、中継サービスはデータベースの業務イベントに送信済の印をつける、あるいは送信済となったイベントを完全に削除する
      • RDBの場合は2つのテーブル(集約の状態・送信箱テーブル)をアトミックにコミットできる機能を活用しメッセージを記録する専用テーブルを使う
      • 複数ドキュメントへのトランザクション管理ができないNoSQL系のデータベースの場合、集約レコードの中に発行すべき業務イベントを埋め込むことが必要
  • サーガ
    • 複数の集約にまたがる業務プロセスを実装しなければいけない場合
    • サーガとは開始から終了まで長く続く業務プロセスのこと
      • 必ずしも時間の絶対的な長さではなく、秒単位で終わるサーガもあれば年単位で続くサーガもある
      • 重要なのはトランザクションの視点
    • 多数のトランザクションで構成される業務プロセスがサーガ
    • 一連の処理がどこかで失敗した場合、サーガはシステムの一貫性を確保するために失敗に対する補償アクションを実行する
    • サーガは全てのコンポーネントの状態は結果的に整合する
      • データが強く整合していると想定できるのは集約の境界の内側だけ
      • 集約の境界の外側にあるデータは結果的に整合する
  • プロセスマネージャー
    • もしサーガの実装でif-else文を使った処理の分岐が必要ならそれはおそらくプロセスマネージャー
    • サーガと違い特定のソースイベントと関連づけることはできない
    • そうではなく、複数の処理ステップで構成する開始から終了までが1つにつながった業務プロセス
    • そのためプロセスマネージャーは明示的に起動してプロセスを開始する必要がある

感想

  • サーガについて、そもそも集約が強い整合性を保ちたい設計となっており、その集約が複数ある場合の連携方法としてサーガを使うので、サーガ自体は結果整合性として設計するのが自然と言うことが理解できた
    • つまり、サーガが結果整合性であることに問題があるとなるとそれは集約の設計の問題になると言う理解をした
yusukeyusuke

10章

設計の経験則

  • 区切られた文脈の最適な大きさ
    • 大きさは最も役に立たないものの1つ
    • 大きさを決めてからモデルを作らない、むしろ逆でモデルを作ってから区切られた文脈の大きさを決定する
    • 変更が大変になるため
    • 中核の業務領域は変化しやすく、不確実性が高いのが特徴
    • 広い範囲で文脈を区切る・複数の業務領域を取り囲んだ境界で文脈を区切ることは境界の設計やモデルの対象範囲が間違っていたとしても比較的安全
  • 業務ロジックの実装方法
    1. お金や金融取引に関わる処理の追跡・監査記録・深い行動分析が必要であればイベント履歴式ドメインモデル
    2. 業務領域の業務ルールが複雑であればドメインモデル
    3. 業務領域のデータ構造が複雑であればアクティブレコード
    4. トランザクションスクリプト
  • テストの方針
    • トランザクションスクリプト -> 逆ピラミット形のテスト(エンドツーエンドのテストを重視)
    • アクティブレコード -> ダイヤモンド形のテスト(統合テストを重視)
    • ドメインモデル -> ピラミット形のテスト(単体テストを重視)
    • イベント履歴式ドメインモデル -> ピラミット形のテスト(単体テストを重視)
  • 実装方法の判定
    • できるだけ単純なツールを選択
    • 複雑な手段(ドメインモデル・イベント履歴式ドメインモデル・CQRS)などは本当に必要な時に最終手段として使う

感想

  • 区切られた文脈の大きさについて、まずは広く区切り、業務知識が増えるのに合わせて小さな文脈に区切っていくようなイメージになった
  • 各判断基準が書かれておりイメージしやすかった
yusukeyusuke

11章

設計を進化させる

  • 会社の利益に貢献しないのにロジックが複雑になるとしたらそれは不必要な業務の複雑さ
  • 反対に業務ロジックが複雑になることで収益が増えているとしたら業務領域が中核の業務領域に変化する兆候
  • 業務ロジックの実装方法を変更する例
    • トランザクションスクリプトからアクティブレコードへ
      • ほぼどちらも同じだが違いはデータ構造の扱い方
      • データベースを直接操作するかわりに、アクティブレコードを使ってモデル構造を抽象化する
    • アクティブレコードからドメインモデルへ
      • データ不整合やロジックの重複が増えていることに気がついたら業務ロジックの実装をドメインモデルにリファクタリングする
      • まずは値オブジェクトを見つける
      • 最小のトランザクション境界を見つける
    • ドメインモデルからイベント履歴式ドメインモデルへ
      • 最も厄介になるのはすでに存在している集約の履歴をどうするか(履歴が失われ、最新の状態だけを表現する集約をイベント履歴式モデルに転換する方法)
      • 過去の業務イベントを可能な範囲で修復する、あるいは移行したことを表現する特別なイベントを用意するのいずれかの対応になる
  • 価値を生み出すソフトウェア設計には業務知識が不可欠というのがドメイン駆動設計の中核にある信念
  • 中核の業務領域を理解することは大きな挑戦であり、中核の業務領域のロジックは入り組んでいるだけでなく、たびたび変化し、モデル作りがずっと続く
  • システムの成長はソフトウェアが健全である証
  • 人生において唯一不変なことは変化である

感想

  • 業務領域(中核・一般・補完)というのは常に変わりゆくもの
    • 他社との競争で生き残っていくために根本的な部分が変わったり、変えていく必要が出てきたりするため
    • 業務領域に対する実装方法の設計を考え直す機会が出てくるので再整理
yusukeyusuke

12章

イベントストーミング

  • 業務プロセスのモデルを迅速に作ることを目的に関係者が集まり、ブレインストーミングスタイルで進めるローテクな手法(業務知識・同じ言葉を共有するための戦術的なツール)
    • 付箋を使って、業務イベントを時系列に並べながら対象としている業務プロセスを探求する
    • アクター・コマンド・外部システムなどを追加しならがらモデルを拡張する
    • 業務プロセスの仕組みを説明できるところまで要素が揃ったら終了
  • イベントストーミングのプロセス
    1. 発散的に探索する
    2. 時系列に並べる
    3. 問題点を洗い出す
    4. 転換イベントを見つける
    5. コマンドを見つける
    6. ポリシーを定義する
    7. 読み取りモデルを見つける
    8. 外部システムを追加する
    9. 集約を見つける
    10. 区切られた文脈に分割する

感想

  • できるだけ短い時間で多くのことを共有することが大事だと知った
yusukeyusuke

13章

現実世界のドメイン駆動設計

  • ドメイン駆動設計が大きな効果をもたらすのはすでに稼働しているソフトフェアに取り組んだ場合
  • 最初にやるべきこと
    • 事業活動を理解する
    • システムの構造が現在どうなっているかを理解する
  • 集約や値オブジェクトの実装がドメイン駆動設計ではなく、ソフトウェアの設計判断を事業活動(ドメイン)で駆動するのがドメイン駆動設計

感想

  • ドメイン駆動設計は全てをやるのか全くやらないのかの二者択一ではないことを知った
yusukeyusuke

14章

マイクロサービス

  • サービスとは
    • 1つ以上の機能にアクセスできる仕組みで規則として定められたインターフェースを用いて提供されるもの
  • マイクロサービスとは
    • 極めて小さな公開インターフェース(小さな玄関ドアを持つサービス)
    • 公開インターフェースを小さくすることでサービスの機能が明快になり、他のコンポーネントとのつながり方も理解しやすくなる
    • サービスの機能が減ることでそれぞれのサービスの変更理由が限定的になり、開発・管理そしてスケーリングの独立性が高くなる
    • データベースを公開しない
      • SQLは柔軟なので、組み合わせの数は無限に近しいため、データベースをカプセル化して隠蔽し、データへのアクセス方法を連携に特化したコンパクトな公開インターフェースに限定する
    • サービスの公開インターフェイスを1つのメソッド単位にするという話ではない
    • メソッド単位で分割したサービスは浅いモジュール
      • 浅いモジュールは局所的な複雑さをカプセル化しないコンポーネントを増やしシステム全体の複雑さを増加させる(マイクロサービスを目指したプロジェクトが失敗する原因)
    • 深いモジュールはシステムの全体的な複雑さを減少させる
    • システムのどこまでマイクロなサービスに分解するかの閾値はマイクロサービスで実現するユースケースから決めることが可能
  • ドメイン駆動設計とマイクロサービスの境界
    • ドメイン駆動設計の手法
      • 区切られた文脈はモデルの境界
      • 業務領域は業務活動の境界
      • 集約と値オブジェクトはトランザクションの境界
    • 区切られた文脈
      • マイクロサービスも区切られた文脈も物理的な境界
        • 単一のチームによって所有される
        • 1つのマイクロサービスで複数のモデルは実装できない
      • マイクロサービスと区切られた文脈の関係は非対称
        • マイクロサービスは区切られた文脈
        • 区切られた文脈はマイクロサービスではない
    • 集約
      • 集約をサービスの単位とすることで、細かい粒度のサービスとなりシステムの全体を複雑化させる可能性がある
      • 集約という単位に分割すると浅くなりがち(同じ業務領域の他のオブジェクトとの関係が強いほど)
      • マイクロサービスの単位は他のコンポーネントとの相互作用の文脈で捉える必要がある
    • 業務領域
      • 区切られた文脈や集約よりもバランスが取れているのはサービスの境界を業務領域に合わせる方法
      • 業務領域は自然に深いモジュールとなる
  • マイクロサービスとドメイン駆動設計とは密接な関係にあり、ドメイン駆動設計の考え方とやり方を使えば効果的なマイクロサービスの境界を設計できる

感想

  • マイクロサービスは「深さ」が大事で、浅いモジュール単位で公開インターフェースを作ると逆にシステム全体の複雑さが増加し分散した大きな泥団子になり失敗する原因となるということを知った
  • マイクロサービスは区切られた文脈ではあるが、区切られた文脈はチームの規模や構造などによって分けた方が変わるため、一概にマイクロサービスということではないになることもあるためということを知った
    • 例えば区切られた文脈は一枚岩の巨大なシステム(≒大きな泥団子)の境界になることもある
yusukeyusuke

15章

イベント駆動型アーキテクチャ

  • 分散システムを疎結合に保ち、拡張性と耐障害性を向上するための有力な技術方式でドメイン駆動設計と関係する
  • イベント駆動型アーキテクチャを安易に取り入れるとモジューラモノリス(モジュール化された巨大な一枚岩)を分散した大きな泥団子に変えてしまう可能性がある
  • イベント駆動型アーキテクチャとは
    • システムのコンポーネント間でイベントメッセージを非同期でやり取りする技術方式
    • 同期ではなく、イベントを発行(publish)し、他のコンポーネントはシステムで起きた変化をイベントとして購読(subscribe)し、そのイベントに応じた動作をする
    • 9章ででてきたサーガは典型的なイベント駆動型アーキテクチャ
    • イベント駆動型アーキテクチャはサービス間の通信方法で、イベントソーシングはサービス内部の実装方法でシステムの他のコンポーネントと連携することを意図した方法ではない
  • イベント
    • すでに起こった変化を表現したメッセージ、なので過去形で表現する
  • コマンド
    • これから実行すべき操作を表現したメッセージ
  • イベントのペイロード(イベントの内容)はイベントを3つのカテゴリに分類する
    • イベント通知
      • 事業活動で起きた変化に関するメッセージ(例えば給与明細発行済・キャンペーン公開済など)
      • イベントの購読者にイベントの発生を伝えることが目的
      • イベントに反応するために必要な全ての情報をイベント通知に含めない、必要最小限にとどめる
    • イベントによる状態転送
    • 業務イベント
yusukeyusuke

16章

データメッシュ

  • オンライントランザクション処理(OLTP: Online Transaction Processing)
  • オンライン分析処理(OLAP: Online Analytical Processing)
  • ドメイン駆動設計とデータメッシュは相互に保管する関係
  • 事実(Facts)テーブル
    • 業務イベントと似ているが、動詞の過去形で表現することは必須ではない
    • 業務イベントと同じでレコードを変更・削除することはない
  • 特性テーブル
    • 事実の性質や状態(形容詞)を記述する
    • 事実テーブルの外部キー(FK)の参照先となる
  • データウェアハウス(DWH: Data Warehouse)
    • 全社のさまざまな業務系システムからデータを抽出し、単一の分析系モデルに変換し、その結果を単一の分析用データベースに書き出す、このデータベースがデータウェアハウス
    • 中核にある目標は事業全体を単一モデルで表現すること
    • そのため分析系システム(OLAP)と業務系システム(OLTP)が密結合になる
  • データレイク
    • 業務系システム(OLTP)のデータを取り込む
    • データを直ちに分析系モデルに変換するのではなく、生の状態(業務系モデル)のままで保管する
    • データレイクに保管されたデータを解釈しETLスクリプトを書いて分析モデルを生成しデータウェアハウスへ送り込む
    • 元のモデルのまま保管することで目的ごとに複数の分析系モデルを利用できる
    • 分析系モデルの生成を後回しにすることでシステム全体が複雑になる
  • データウェアハウスとデータレイクの課題
    • 業務系システムの実装の詳細に不必要に依存してしまう
    • ドメイン駆動設計ではドメインモデルは頻繁に変更されるので、業務系モデルの変更が分析系システムに予想外の問題を引き起こす
  • データメッシュ
    • 分析系データのドメイン駆動設計のようなもの
    • 基本的な考え方
      • データを業務の視点で分割する
      • データをプロダクトと考える
      • 自律性を高める
      • エコシステムを構築する