LoginSignup
19
14

More than 5 years have passed since last update.

Rails でドメイン駆動開発 (DDD) をするときの集約の作り方

Posted at

Rails で DDD をしている時の集約の実装方法を考えます。

ActiveRecord と集約を別として考える

メリット

  • 集約が PORO (Plain Old Ruby Object、素の Ruby) で実装できる
  • 集約にDB へのアクセスロジックが混在せず、ビジネスロジックの実装に集中できる

デメリット

  • ActiveRecord のインスタンスが別に作成されるのでメモリの使用効率が悪い
  • 集約へ再構成を行う実装コストがかかる (ライブラリがあるかも)

方法

ActiveRecord のインスタンスは DAO として捉えます。
DAO はテーブルに対して操作をおこなうインタフェースとして考えればよく、リポジトリから使用することが想定されます。

例えば、作成や更新を行う リポジトリ#save を実装する場合には以下のようになります。

class UserRepository
  def save(user)
    user_dao = User.find_or_initialize_by(identity: user.identity)

    user_dao.assign_attributes(
      name: user.name,
      email: user.email
    )

    user_dao.save!
  end
end

次に、リポジトリ#user_of_identity というメソッドを実装して、識別子から集約のオブジェクトを検索/再構成するパターンです。

class UserRepository
  def user_of_identity(identity)
    user_dao = User.find_by(identity: identity)

    return nil unless user_dao

    user = Users::User.allocate # 集約を再構成する

    user.instance_variable_set(:@name, user_dao.name)
    user.instance_variable_set(:@email, user_dao.email)

    user
  end
end

ポイントは再構成を行う時に、Class#allocate を使用していることです。

このメソッドはクラスのインスタンスを作成しますが、#initialize を呼び出しません。
再構成時に #initialize の呼び出しを回避することで、オブジェクトの作成時にのみドメインイベント発行させたりすることが出来ます。
また、前述の理由のため、集約の各属性への値の代入も、集約を振る舞いを使用せずに #instance_variable_set を使用して行います。

実際には、再構成の処理をリポジトリのプライベートメソッドや、Rails のモデルにロジックをまとめる方法が有効的です。

番外編: ActiveRecord と集約を同じにする

メリット

  • リポジトリにて、集約への再構成を行うコストが少なくなる
  • メモリの使用効率が良い
  • composed_of で値オブジェクトをマッピング出来る

デメリット

  • ビジネスロジックと DB へのアクセスロジックが混在する
    • DB アクセスのロジックを別モジュールにしてファイルを分けることは出来そう
  • ドメインモデル層に ActiveRecord のインタフェースが公開されている状態になる

まとめ

基本的には、DB へのアクセスロジックは集約には漏らさないようにしたいので ActiveRecord と集約を別にするパターンで良いのかなと思いました。高い非機能要件が求められて効率的にメモリを使用しなければならない場合には、ActiveRecord と集約を同じにするパターンを検討してみてはいかがでしょうか。
ただし、高速化を求める方法はキャッシュの活用や、クエリのチューニングなどでも大きな効果があるはずなので、本当の最終手段のような気がしました。

19
14
0

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
19
14