ドメインモデル(DomainModel)パターン(PofEAA)

参考書籍一覧(Amazon アソシエイトリンク)

データと振る舞いが一体となったオブジェクトによってドメインロジックを記述するパターン。

アクティブレコードパターンもドメインモデルの一種である。

アクティブレコードの本質はドメインモデルであり、アクティブレコード内のクラスは、基盤となるデータベースレコード構造とほぼ一致している。

エンタープライズアプリケーションアーキテクチャパターン 第10章 データソースのアーキテクチャに関するパターン 10.3 アクティブレコード

DDDにおいて、モデル駆動設計を行って作られるエンティティやバリューオブジェクト、集約といったものはすべてドメインモデルである。

アクティブレコードパターンを適用しない場合、ドメインモデルとデータソースが対応しないため、なんらかの方法で橋渡しする必要がある。専用のクラスを用意するのであれば、リポジトリ(Repository)パターンを適用する方法がある。

ドメインモデルとデータソースの対応づけが煩雑な場合で、行データゲートウェイ(RowDataGateway)パターンのフレームワークを利用しているのであれば、行データゲートウェイのインスタンスをデータホルダーとしてドメインモデルに持たせてしまう方法がある。

データをドメインオブジェクトにコピーする代わりに、行データゲートウェイをドメインオブジェクト用のデータホルダーとして使用することができる。

エンタープライズアプリケーションアーキテクチャパターン 第10章 データソースのアーキテクチャに関するパターン 10.2 行データゲートウェイ

Railsにおいて、ドメインモデルパターンを適用しようとしたとき、私が最も手っ取り早いと考えている方法はActiveRecordを行データゲートウェイとして扱いドメインモデルにデータホルダーとしてインスタンスを渡してしまう方法である。以下のようにドメインモデルのファクトリ(Factory)をActiveRecordに用意して、保存時はサービスレイヤなどでActiveRecordのsaveメソッドなどを呼び出してしまえば良い。

class SomeUserDomainModel
  # rawはActiveRecordのUserクラスのインスタンス
  attr_accessor :raw
  def initialize(raw_user)
    @raw = raw_user
  end

  # userに対する変更処理...
  def some_command_method
    # ...
  end
end

class User < ApplicationRecord
  # ドメインモデルごとにメソッドを用意する
  def to_some_user_domain_model
    SomeUserDomainModel.new(self)
  end
end

class SomeService
  def command(user_id)
    domain_model = User.find(user_id).to_some_user_domain_model
    domain_model.some_command_method
    domain_model.raw.save!
  end
end