TaNA LABO
エンジニアリング

April 24, 2020

AWS
GAFA
DX
マイクロサービス

マイクロサービスでのビジネスロジック Aggregateでドメインモデル設計

post 36

モノリスのサービス分割では、DDDの考え方が役立つと言われている(多分)

そのため以下の書籍でも、DDDのAggregateパターンを利用したドメインモデルの設計が説明されているが、正直なところ説明内容が難しくて(自分には)あまり理解出来ず … DDDの知見が無い状態で本書を読んでも、結構な数の人が困惑するのでは?と思う(多分自分が理解力不足なだけ)


私のようにDDDへの理解が無い方には、以下の書籍を読むことをオススメしたい。DDDにおける「概念を実装に落とし込むパターン」や、集約(Aggregate)に関する内容が説明されているので、一読するとマイクロサービスパターンの内容理解も深まると思われる。


また集約を理解しようとすると、DDDの基本である値オブジェクトやエンティティ、ドメインサービスの理解も必須なので、やはり本書の一読を強く推奨したいかも。

アグリゲートパターン

ドメイン駆動設計入門では、集約をざっくりこんな感じで説明。

集約は関連するオブジェクト同士を線で囲う境界があり、例として以下のようなクラス定義!!

集約を操作するための直接のインターフェースとなるオブジェクトは 集約ルート(Aggregate Root)と呼ばれるオブジェクト(User)に限定、集約内部のオブジェクト(UserIdとUserName)に対する変更は、集約ルートが責任をもって行うこと で集約内部の不変条件が保たれる(UserNameを直接操作するのはUserのみとなる = デルメルの法則)

class User
{
  public User(UserId id, UserName name)
  {
      # 処理
  }
}

デルメルの法則では、メソッドを呼び出せるオブジェクトを4つに限定(オブジェクト自身 / 引数として渡されたオブジェクト / インスタンス変数 / 直接インスタンス化したオブジェクト)しており、この原則を守ることでメンテナンス性の向上とコードの柔軟性を実現。

アグリゲートのルール

本書ではFTGOアプリケーションというものをサンプルに説明。

アグリゲートで各領域の境界を明確にしていない場合にどんな問題が考えられるか? 密結合していると、あるビジネスオブジェクトの一部を直接更新することで、ビジネスルールを破る可能性がある。

まず本書では各領域(Order / Consumer / Restaurant)でアグリゲートルートを明確化させ、更にアグリゲートでは以下の3つのルールが課されると説明されている。

■ アグリゲートルートだけを参照する.

■ アグリゲート間の参照では主キーを使わなければならない.

■ 1つのトランザクションで1つのアグリゲートを作成または更新.

一点目では、値オブジェクトを操作出来るのはアグリゲートルートだけで、必ずルート経由で操作を行うもので、例えばサービスはリポジトリでデータベースからアグリゲートをロードし、アグリゲートルートの参照を獲得する流れとなる。

二点目では、他アグリゲートを利用する際、オブジェクト参照ではなく、アイデンティティ(主キー)利用するもので、最後は文字通り(第4章で解説されているサーガの話)

アグリゲートの粒度

両書とも基本的には、アグリゲートはなるべく小さく作ることを推奨されており、FTGOの例ではOrderとConsumerを別々に分割していたけど、勿論Consumerに集約する考えも勿論あり得る。

集約すればアトミックに更新できるメリットがある反面、スケーラビリティが下がる欠点(アプリケーションで同時処理出来るリクエスト数が増える等)もあり、これは明確な答えは無さげだ(システム毎にエンジニアが考えるしかない)

ビジネスロジックの基本はアグリゲート中心となり、それ以外のビジネスロジックは、ドメインサービスとサーガに集約(本書の場合では、アグリゲートのOrder、サービスクラスのOrderService、最後にOrderRepositoryと1つ以上のサーガから構成される)


©Copyright2020 TaNA LABO. All Rights Reserved.