コンテンツにスキップ

(記述中)設計:(DDD + CQRS)

DDD(Domain Driven Design)とはドメインモデルを中心としたソフトウェア設計手法のことである。
いくつか派生があるが、概ね下記のような特徴がある。

  • アジャイルの思想に則った開発手法の一つ
  • モデル、サービス、アプリケーション、プレゼンテーションのような層を持つ構造であること
    • 派生により常にこの4層構造での名称ではないことに注意
  • 外側から内側に向けた一方通行の依存関係になっている
    • プレゼン -> アプリ -> サービス -> モデル
  • DIP:Dependency Inversion Principle
    • 原典のレイヤードアーキテクチャではDIPを使うことを提示していない

本実装のバックエンドでは制約のバランスが良いオニオンアーキテクチャを採用する。
また、更新系についてDDDはよく機能するが、参照系に対して実装に悩む場面が多い。
そこで、CQRS(コマンドクエリ責務分離)を用いて参照系の実装の仕組みと分離することとした。

オニオンアーキテクチャ

DDDの派生の中でオニオンアーキテクチャを利用するものとする。
よく円形の図が用いられており、その見た目からオニオンアーキテクチャと呼ばれている模様。

  • Presentation
    • エンドポイント提供
    • Http Requestで渡された値とUseCaseに渡す値のマッピング
  • UseCase
    • ユースケースの実現
    • Presentationで利用するDataTransferObjectの定義
    • Value Object, Entityの生成、仕様、永続化の依頼
  • Domain
    • RepositoryのInterface
    • Value Object, Entity, Domain Serviceの定義
  • Infrastructure
    • RepositoryのImplement
    • ORMの定義

Onion Architectureに一通り実例が載っているので参考になる。

参考:派生例:クリーンアーキテクチャ

DDDの中で特に完全性に重きを置くアーキテクチャ。学習コストが高い。 引用:Clean Architectureなにもわからないけど実例を晒して人類に貢献したい

参考:派生がややこしい

登場している名詞はDDD派生ごとにゆらぎがあることに注意すること。 引用:詳細 -クリーンアーキテクチャ-

参考:MVPとの対比例(クリーンアーキテクチャ)

laravelでクリーンアーキテクチャする例。mvpとの対比言及あり。DDDによってModelレイヤの解像度が上がっている。 引用:ddd-backend-with-laravel

CQRS(command query responsibility segregation)

CQRSは情報の参照に使用するモデルと更新に使用するモデルに異なるものを使用するアーキテクチャを指す。

参考:DDDで設計するならCQRSの利用を検討すべき CQRS実践入門 [ドメイン駆動設計] DDDでのDTOの使い所 DDDを実践するための手引き(概論・導入編)

graph LR
    Actor
    Create
    Read
    Update
    Delete

    Actor --> Create
    Actor --> Read
    Actor --> Update
    Actor --> Delete

CURDにおいて、Readについては複雑さの方向性が異なり、DDDの文脈で取り扱うのが困難な場合がある。

そこで、データに対する操作をCommand(命令)とQuery(問い合わせ)に分けて考える。

  • Commandではトランザクショナルな書き込みや複雑な権限の整合性を担保
  • Queryでは条件や出力方式の複雑さに対応
    • 検索条件
    • ページネーション
    • ソートなど前提条件
graph LR
    Actor
    subgraph "Command"
        Create
        Update
        Delete
    end

    subgraph "Query"
        Read
    end

    Actor --> Create
    Actor --> Read
    Actor --> Update
    Actor --> Delete
性質 整合性 書き込み 網羅性 自由な検索 結合
Command o o o x x
Query x x x o o

このような設計思想はCQRS(command query responsibility segregation)と呼ばれている。

RDB内でクエリ処理を完結させるほか、RDBと検索エンジンの間で非同期にデータ同期を行い、利用シーンに応じて使い分けるような使い方もある。

graph LR
    Actor

    subgraph "User Interface"
        subgraph "Command"
            Create
            Update
            Delete
        end

        subgraph "Query"
            Read
        end
    end

    subgraph "Infrastructure"
        RDB
        SearchEngine
    end

    subgraph "Service"
        SyncProceccer
    end

    Query --> RDB
    Query --> SearchEngine

    Command --> RDB
    Command -->|1. event| SyncProceccer
    SyncProceccer -->|2. fetch records| RDB
    SyncProceccer -->|3. upsert index| SearchEngine

    Actor --> Create
    Actor --> Read
    Actor --> Update
    Actor --> Delete

また、Queryにおいてはバックエンドindexへの入出力は素直に露出させて設計する場合がある。

DDD と CQRS の併用

以上を踏まえて、DDD+CQRSの全体構造を示す。
CommandとQueryを完全に分ける意図で下記は明示的に分割した。

  • DTO
    • Command DTO
    • Query DTO
  • Domain Model
    • Write Model
    • Read Model