最近、読みかけで止まっていた、Patterns of Enterprise Application Architecture (いわゆる PoEAA) を再度読みはじめました。
システムというものをゼロから設計するためには、これまで積み重ねられてきた知見を知っておかないと立ち行かないなぁと思うことが多くなったのが一番の理由です。 この手の本は、自分の理解を文章にアウトプットしておかないとただ「読んだ」という状態にしかならないので、こういうエントリにして自分の言葉でできるだけまとめておきたいと思います。
Service Layer
今日のテーマはサービス層で、Java 使ってるとよく見にするパターンです。ContractsService.java
なんてクラスがあると、あぁ Service Layer だろうなって感じになりますね。
Service Layer が解決する課題
Service Layer というのは「サービス」と呼ばれる層を設けることで、ビジネスロジックを系統立てるデザインパターンです。
ここでの「ビジネスロジック」は大きく 2 つに分けられるという前提を持っています。
- ドメインロジック
- アプリケーションロジック
ドメインロジックというのは、個々の問題領域に適用できるロジックで、wikipedia:Strategy パターンを適用するようなロジックと考えると分かりやすいでしょう。 一方で、アプリケーションロジックというのは、まさに今、対象としているエンタープライズアプリケーション特有のロジックで、例えば「この処理をしたらメールで責任者に通知する」とか、「この処理をしたら証跡ログを残しておく」とかになるでしょう。本の中では "workflow logic" とも呼ばれる、という記述がありましたが、そっちの表現の方がイメージが伝わるかもしれません。
Service Layer が取り組む課題の焦点は、この アプリケーションロジック をどう扱うかに当たっています。このアプリケーションロジックをドメインロジックと一体化させようとすると、ドメインロジックの対象とする問題(problem domain) 以外の要素をドメインロジックに持ち込むことになり、ドメインロジックの再利用性が著しく下がってしまいます。 Service Layer は、このドメインロジックとアプリケーションロジックとを明確に分離して「階層化(Layering)」による恩恵を受けることができるようにし、純粋なドメインロジックの再利用性を高めようというパターンになります。
実装
本の中では、基本的な実装パターンとして、
- wikipedia: Facade パターンでの実装
- Operation Script としての実装
が挙げられていましたが、本の焦点も著者のお勧めも後者でであるので、ここでは後者についてのみ記述しておきます。
Operation Script
Operation Script におけるサービス層は、
- アプリケーションロジックは直接実装 (書き下すわけではなく、Gateway とかに移譲する)
- ドメインロジックはドメインオブジェクトに移譲
という構成の Thick なクラスとして実装されます。"Script" という表現は個人的には微妙だなと思うのですが、まぁ P of EAA: Transaction Script でも同じような文脈で Script という単語が使われているので、そういう使い方なんでしょう。
初期のアプリケーションで要求されるビジネスロジックは単純な CRUD 等に留まることが多く、ドメインロジックのみで構成されることも多いのですが、メール通知や証跡ログ等、段々と「アプリケーションロジック」に属するロジックが増えていきます。 アプリケーションロジックは外部システムへの副作用をもたらすものも多く、トランザクション境界の中で処理されなければならないケースが大半です。こういうとき、サービス層を構成するサービスクラスはトランザクション境界としても定義することができ、アプリケーションロジックの追加がシステムに混乱をもたらしにくい構成になっていると感じました。