Patterns of Enterprise Application Architecture (PoEAA) は 2002 年、今からちょうど 20 年前に出版された本の名前です。このアドベントカレンダーでは、この本に書かれて世に広まったパターン名を紹介していきます。執筆された内容は、それ以前の知見のまとめということもあって、現在の業務アプリケーション開発から見ると、かなり解説が古くなっています。言葉だけ知りたいと思っている人だけでなく、原典を読もうと思っている人も、まずはこのシリーズでざっと意味をつかんでください。難解で挫折してしまわないための助けになると思います。
はじめに紹介する Transaction Script と Domaon Model は、ドメインロジックパターンに分類されます。
業務の処理をプログラムで表すとき、ひとつの処理全体を、具体的な一本の台本のように記述したものが、一般的に Transaction Script と呼ばれるタイプの記述スタイルです。長くて複雑なロジックになってくると、サブルーチンに分解するなどの工夫の余地はありますが、問題を抽象化して扱うような記述はしません。
データベースを扱うときは、主に、SQL と結果をやりとりする単一の接続オブジェクトを使います。テストはスクリプト全体を通しで実行してみて、意図した変更が正しく起きているかを、全て 確認しなければなりません。
いっぽう、Domain Model は、処理ではなくオブジェクトの関係モデルに先に着目します。オブジェクトの責務をデザインし、各部分部分が閉じたシンプルな問題にのみ注力できるかたちを考えます。当時はまだ使われていませんでしたが、現在では xUnit による純粋なロジックテストで、先に閉じた部分の正しさを確認するのが普通です。
オブジェクト同士の連携は、互いを抽象化して認識するかたちを取るのが一般的です。連携先が具体的に何をするのかを気にせず、抽象として正しいはず (インターフェース仕様のとおりに動いてくれるだろう、など) と期待して、自身以外の全体を信用する考え方をします。全体の複雑さを考える必要のない、うまく切り分けたシンプルな部品だからこそ、正しさがわかりやすい点、および、そうした部品の組み合わせグラフで柔軟に全体像を描くのは、いわゆるオブジェクト指向プログラミングらしいスタイルです。
一概にどちらが優れていると言い切ることはできません。Transaction Script のメリットは単純さです。複合的な問題とは全く無縁な、入力された値でデータベースのデータを一箇所書き換えるだけのような、単純な CRUD でよい場合などには、Domain Model は大袈裟になってきます。単機能のマイクロサービスなども同様です。逆に、複合的な問題に関する複数の機能があるアプリケーションでは、直接 SQL を意識するような低レベルコードが増えると、ロジックを誤解してしまうおそれがあるので、Transaction Script は不向きになってきます。
注意しなければならない点は、細かく責務が分かれたオブジェクトを使っているからといっても、それだけでは Domain Model とは呼べないかもしれない点です。オブジェクトを多く使っていても、実質的に Transaction Script になることがありえます。
Ruby on Rails や Laravel の ActiveRecord (Eloquent) は有名ですが、これらは手続き中のどこからでもアクセス可能な、サービスロケーターのラッパーです。また、比較的ダイレクトに、即時 SQL 発行を行います。ひとつの手続きから無節操に全ての ActiveRecord クラスを参照すると、それは実質、一本のデータベースコネクションで何でもやるスクリプトと同じ意味になってきます。
ひとつのビジネスロジックの入力と出力だけを見ながら Transaction Script のように考えて作ると、ファットコントローラーと呼ばれるアンチパターンにつながります。オブジェクトに責務を分けるときは、関心の分離を意識して、それぞれが閉じて責務を満たすかを先に考えましょう。