面白駆動人生

やっほー

【読書メモ】実践ドメイン駆動設計 ~第4章~ 「アーキテクチャ」

1. What is Architecture

2. アーキテクチャの種類

Layers

特徴

クライアント -> サーバ -> DB のように、層に分けるパターン。名前空間の分割、各レイヤの依存関係、責務の明確化。

問題点

ドメイン層がインフラ層に依存するため、ドメインの実装が、インフラ層の実装に依存してしまう。

解決策

DIP(Dependency Inversion Principle)を用いる。
インフラ層の実装をドメイン層の抽象に依存させ、ドメイン層を独立させる。

Hexagonal or Ports and Adapters

特徴

システムを内部と外部の領域に分け、外部からの入力をアダプタが変換し、内部のAPIの形式に合わせる。
テスト用のアダプターが容易に作れる点が利点。 クライアント、永続化の種類が未定のうちから、暫定的なアダプターを作ればドメインの実装を進められる。

Service-Oriented

SOAの8つの原則

原則 説明
Standardized Service Contracts サービスは契約(インターフェース)によって説明される
Loose Coupling of Service 疎結合であり、外部への依存は最低限にする
Service Abstraction インターフェース(契約)のみ公開し、内部の詳細は見せない
Service Re-Usability 実装は一つで、他サービスから再利用可能である
Service Autonomy サービスが独立して存在し、一貫性と信頼性を保っている
Service Statelessness サービスを利用する側が状態を管理する
Service Discoverability サービスをメタデータで記述し、発見可能にする
Service Composability サービスはより大きなサービスの一部に組み込み可能である

Representational State Transfer (REST)

RESTの定義

RESTとは、Fieldingが博士論文として提唱してアーキテクチャスタイル。
https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm

RESTに従っていることをRESTfulと呼ぶ。

  • point1 リソースはURI(Uniform Resource Identifer)により、一意に識別される。
  • point2 一つのHTTPリクエストに、サーバ側での処理に必用な情報を全て含める。サーバは個別のリクエストに依存しない。
  • point3 全てのオブジェクトが同じインターフェースを持ち、決められたメソッドで操作される。(特に重要なメソッドとして、GET, PUT, POST, DELETE)
  • point4 レスポンスに他のリソースの情報を埋め込める。Hypermedia as the Engine of Application State(HATEOAS)

RESTとDDD

RESTとDDDをどう組み合わせるか? ドメインモデルをRESTful HTTPで直接公開するのは悪手。ドメインモデルに手を加えるたびに、システムのインターフェースにも手を加える必用が出てくる。

システムのインターフェースレイヤを、境界づけられたコンテキストとして分離する方法が一般的に使われる。

Command-Query Responsibility Segregation (CQRS)

解決したい課題

  • 読み取りと書き込みのデータの形は一死するとは限らない。
  • 同じデータセットに、並列で操作が実行されると競合が発生する可能性がある。
  • データストアとデータアクセス層への負荷、クエリの複雑さによって、パフォーマンスに悪影響が出る可能性がある。
  • 読み取りと書き込みが同じデータに行われるため、アクセス許可の管理が複雑になる。

参考: CQRSパターン - Azure Architecture Center

What is CQRS?

「更新」を行う「コマンド」と、データを「参照」する「クエリ」に、異なるモデルを使うアーキテクチャ

アクションを実行する「コマンド」と、データを呼び出し元に戻す「クエリ」をメソッドとして分離するという、 CQS(Command Query Separation)の考えを、アーキテクチャに持ち込んだもの。

f:id:yktm31:20210606192406p:plain

CQRSのメリット - スケーリング - 読み取り、書き込みそれぞれを個別にスケーリングできる。

  • パフォーマンス

    • 読み取り側はクエリ用に最適化できる。
  • セキュリティ

    • 適切なエンティティのみが、書き込みできる状態を維持しやすい。
  • 関心の分離

    • シンプルな読み取りの実装と、ビジネスロジックが含まれる書き込みの実装を分離でき、保守性・柔軟性を向上できる。

参考: CQRSパターン 解決策 - Azure Architecture Center

CQRSのデメリット - 複雑さ - イベントソーシングが含まれる場合、特に設計が複雑になりやすい。

  • メッセージング

    • コマンド発行・イベント更新にメッセージングが使われることがある。
    • その際、メッセージのエラー・重複処理が必要になる。
  • 一貫性

    • 読み取りデータが古くなる可能性がある。
    • 結果整合性を採用することがある。
      • サーバ側から更新のメッセージをUIに送り、リアルタイム更新する(WebSocket等)
      • UIに、最終更新日時を表示する。
      • UI上で擬似的に表示を更新する。

参考: CQRSパターン 実装に関する問題と注意事項 - Azure Architecture Center

Event-Driven Architecture (EDA)

  • イベントを受け取り、受け取ったイベントに応じて反応するアーキテクチャ
  • システム間の結合を切り離せる。

パイプ & フィルター方式

cat phone_numbers.txt | grep 303 | wc -l

上記のLinuxコマンドのパイプ・フィルターのように、イベントを送信->イベント受信->処理実行->イベント送信という流れを、システム間のやりとりとして表現する方式。

業務プロセスにおけるアクティビティの発生をモデリングしたものになる。

サーガ(長期プロセス)方式

パイプ&フィルターを拡張したもの。複数の処理を分散して処理したい場合に利用。

長期プロセスの設計方法

  • 実行者コンポーネントに、各タスクをトレースさせる。

  • パートナーアクティビティ という方法。Pat Hellandが推奨。

  • イベントを運メッセージに、プロセスの状態を保持させ、プロセスはステートレスとなるように設計する。メッセージを受け取るハンドラが、受け取ったイベントに情報を付与して、次のメッセージとして送出する。

イベントソーシング方式

  • 履歴管理に利用可能。
  • Gitのように、過去の状態を復元するような概念に類似
  • 発生したすべてのイベントを、イベントストアに格納。

データファブリック / グリッドベース分散コンピューティング

  • Pivotal社のGemFireや、Oracle社のCoherenceといった製品で使われる概念。

参考

「実践ドメイン駆動設計」から学ぶDDDの実装入門 (WINGSプロジェクト 青木淳夫 著)

以上