LoginSignup
8
5

More than 5 years have passed since last update.

Rails でドメイン駆動開発 (DDD) をするときのディレクトリ構成案

Posted at

Rails でドメイン駆動開発 (DDD) をしたいという時に、考えたディレクトリ構成案です。
開発をしながら改善をして、なるべく Rails と仲良く共存できる形になったのでメモとして残します。

アーキテクチャ

その他前提

  • 複数のコンテキストは含めない
  • なるべく Rails の機能を無効化しない (目標)

ディレクトリ構成案

app/ # いつもの app ディレクトリ
┣ controllers/ # アダプターとしてみなす
┣ models/ # アダプターとしてみなす
┣ mailers/ # アダプターとしてみなす
┣ views/ # アダプターとしてみなす
┣ view_models/ # アダプターとしてみなす
┃
┣ services/ # アプリケーション
┃ ┗ users/ # `ユーザ` モジュール
┃   ┣ commands/
┃   ┃ ┗ register.rb # 登録コマンド
┃   ┃
┃   ┗ application_service.rb # アプリケーションサービス
┃
┣ domain_models/ # ドメインモデル
┃ ┣ common/ # `共通` モジュール
┃ ┃ ┣ entity.rb # エンティティ共通クラス
┃ ┃ ┣ value_object.rb # 値オブジェクト共通クラス
┃ ┃ ┗ domain_event.rb # ドメインイベント共通クラス
┃ ┃
┃ ┗ users/ # `ユーザ` モジュール
┃   ┣ user.rb # `ユーザ` 集約
┃   ┣ email.rb # `メールアドレス` 値オブジェクト
┃   ┗ repository.rb # リポジトリ (この中で Rails の機能を使用する。主に ActiveRecord。)
┃
┗ infrastructures/ # インフラ
  ┣ persistences/
  ┃ ┗ user_repository.rb
  ┃
  ┗ services/
    ┗ user_email_send_service.rb

app/controllers

いつものコントローラーです。
私が開発をするときはコントローラーで ViewModel を使用して、アプリケーション層のサービスを呼びます。

app/models

いつものモデルです。ActiveRecord のクラスと集約を同一にはしていません。
モデルには業務ロジック以外のロジックを実装します。(スコープ、エンティティへのシリアライズ、etc)

ActiveRecord集約を同一にすることも出来ます。(composed_of について)
ただし、インフラ層のインタフェースや知識がドメインモデル層に漏れてしまうのでトレードオフについて考えて、チームで決断するのが良いと思います。

app/view_models

ユーザからの入力値 (params) を受け取り、ユースケースを実行する ViewModel で、一種のアダプターとして捉えています。
入力値のバリデーションが必要な場合にはここで行います。(ActiveModel を使用しています。)
また、ビュー層は ViewModel をもとに描画をすることで、ビュー層とドメインモデル層が直接やり取りをしないようにしています。

app/services

アプリケーション層のサービスです。

app/services/#{モジュール名}/commands

アプリケーション層のサービスへ渡すコマンドオブジェクトです。
Ruby のネームスペースを活かしてこのディレクトリ配下に配置します。

app/domain_models

ドメインモデルです。
ドメインモデル内ではバリデーションは行いません。(ViewModel 内で行います。)
代わりにドメインモデル層ではアサーションを用意して、常に正しく存在し続けられるようにしています。

app/domain_models/common

ドメインモデル内の共通モジュールです。
エンティティや、値オブジェクトの親クラスを定義して、
各ドメインモデルで継承して使用します。

app/infrastructures

インフラ層の実装クラスをまとめます。

app/infrastructures/persistences

永続化に関する実装クラスです。
この中で ActiveRecord や、Rails.cache などのインフラの力を使います。

app/infrastructures/services

アプリケーション層のサービス、ドメインサービスの実装クラスです。
HTTP を使った外部への通信や、メール送信などを実装します。
メール送信をする際には、ここから ActionMailer を使用しています。

まとめ

もっといい案があれば教えて下さいませ。

8
5
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
5