ドメインモデル(DomainModel)パターン(PofEAA)
データと振る舞いが一体となったオブジェクトによってドメインロジックを記述するパターン。
アクティブレコードパターンもドメインモデルの一種である。
アクティブレコードの本質はドメインモデルであり、アクティブレコード内のクラスは、基盤となるデータベースレコード構造とほぼ一致している。
エンタープライズアプリケーションアーキテクチャパターン 第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