Patterns of Enterprise Application Architecture 読書メモ

Dec 9, 2019 ( Feb 11, 2022 更新 )

これは何

Patterns of Enterprise Application Architecture の個人的な読書メモです。 私の主観が入ったメモなので、内容が気になる方は購入して自分で読むのがよいと思います。

個人的なメモですので、随時更新もしますし、書きたい部分からメモしていっているので書籍の章立てとは異なる順で書いている場合があります。

Catalog of Patterns of Enterprise Application Architecture という、この書籍のパターン一覧のページがあるので、そちらも見てください。私の解釈が主観入りすぎている場合もあるかと思います。

コード例について

書籍にはコード例もあるのですが、このページ上で引用はしていません。 実際の実装例を見たほうがよりわかりやすいと思います。繰り返しになりますが、書籍を購入して読んでみてください。

PART 1: The Narratives

Chapter 2. Organizing Domain Logic

  • Domain Logic を構成するにあたっては3つのパターンがある
    • Transaction Script
    • Domain Model
    • Table Module

PART 2: The Patterns

書籍の中で取り扱われているパターンを列挙する。

Chapter 9: Domain Logic Patterns

Transaction Script

  • ある処理を1つの手続きとして扱う
  • 1つの処理は1つのデータベーストランザクションの処理としてまとめられる
  • メリットはわかりやすいこと
  • デメリットは、これらのトランザクション内に重複が発生していくこと

// TODO: 図

Revenue recognition problem
  • 製品によって契約と代金の計上のタイミングが異なる場合を考えてみる
  • word processors, databases, and spread sheets の場合

// TODO: 図

  • Transaction Script パターンでは、製品の種類によって共通の処理 (Transaction Script) に与えるパラメータを変える

Domain Model

  • リッチなドメインモデルは database の設計と異なりがち。 database との紐付けが難しくなる

    • Data Mapper が必要となる
  • シンプルなドメインモデルは Active Record として扱える

  • 複雑で常に変更されるようなロジックの場合は Domain Model を使う。しかし、シンプルな not-null チェックと合算の計算などであれば Transaction Script でよいだろう

  • Domain Model を使うのであれば、 database との接続には Data Mapper を使うのが第1の選択肢になる。 Domain Model を database から独立したものとし、 Domain Model と database のスキーマの差異に対する最良の手段となる

  • Domain Model を使う場合には Service Layer を使うことも考える。より独立した API を提供するのによい

Revenue recognition problem
  • Product は new する際に Strategy を持つ
  • Product.calculateRecognitions を呼び出し、 Strategy を実行

// TODO: 図

Table Module

  • 1つのテーブルに対して1つのクラスを設計する
  • Domain Model が1つの操作に対して1オブジェクトを生成するのに対して、 Table Module は複数の操作に対して1つのオブジェクトで完結する設計となる

// TODO: 図

Revenue recognition problem

※ 例が Table Module の説明にあるような Constructor のつくりではないような?各テーブルごとに異なる Dataset を引数とした Constructor の呼び出しになるのでは…。この例だと、すべての Table Module に Contract のテーブルを Dataset として渡しているように見える??

Service Layer

  • 多くの設計者(著者を含む)は、「ビジネスロジック」を「ドメインロジック」と「アプリケーションロジック」に分けるという
    • ドメインロジック
      • ある問題の領域に関すること。Revenue Recognition on Contract; 契約における歳入の計上のしくみなど
    • アプリケーションロジック
      • アプリケーションの責務。契約管理者への通知、アプリケーション間の連携
      • アプリケーションロジックはしばしば「ワークフローロジック」とも言われるが、人によって「ワークフロー」の認識が異なる…
  • Domain Models は Transaction Scripts より好ましい。ドメインロジックの重複を避けたり、クラシカルなデザインパターンを使って複雑さに対処できる
  • ただし、アプリケーションロジックをドメインオブジェクトに含めるのは、求められない結果を生む
    • ドメインオブジェクトにアプリケーションロジックを含めたり、アプリケーション固有の依存関係を持ってしまうと、そのドメインオブジェクトをアプリケーションをまたがって再利用することはまれになる
    • ドメインロジックとアプリケーションロジックを共通のクラスに含めると、アプリケーションロジックの再実装が難しくなる。例えば、あるワークフローツールを作って、後でそれが必要なくなったときなど
  • Service Layer は、これらのドメインロジックとアプリケーションロジックを別のレイヤに分けて、異なるアプリケーション間で再利用しやすくする

Chapter 10: Data Source Architectural Patterns

Active Record

  • Active Record はデータベースの構成とかなり近い状態

    • データの保存と取得とドメインロジックを同時に持つ
    • Transaction Scripts にいくつかのドメインを持ちつつ、 Active Record を使う場合もある
  • Active Record オブジェクトは以下のような機能を持つ

    • コンストラクタ
      • SQL を実行して初期化する
    • データ操作メソッド
    • ビジネスロジック
  • このパターンを使うと RDB の構造が見えることになる

  • Row Data Gateway パターンと異なる点は、 Active Record はデータアクセス手段の提供のほかにビジネスロジックも内包しているところ

  • Active Record は、ドメインロジックがそこまで複雑でないときに有効

    • RDB のテーブルと直接関連づけられる場合
    • 一致しなくなってしまった場合はリファクタが難しくなる
  • Active Record は Transaction Script を使っていて、コードの重複がつらいときの移行対象としてよい

    • 移行する場合は Gateway としてテーブルをラップしてリファクタリングできる

Data Mapper

  • Data Mapper は、データベースからメモリ上のオブジェクトを分けるレイヤ

    • このレイヤによって、メモリ上のオブジェクトはデータベースのインターフェース(SQL等)を知る必要はなくなる
    • これは Mapper なので、 Data Mapper 自体はドメインレイヤについて知る必要はない
  • このパターンだと Database に毎回リクエストを送らなくてもよい。メモリ上のオブジェクトとの影響を小さくするために Lazy Load を使うことができる

  • Data Mapper は各ドメインごとにわけたほうが見通しはよい

  • Data Mapper は、 Database のスキーマとオブジェクトモデルとを独立して更新していきたい場合によい

  • Domain Model なしに Data Mapper を使うことはないだろう。でもどっちにしても Data Mapper なしに Domain Model を使うか?もし Domain Model がとてもシンプルで、 Database が開発者のコントロール下にあれば、 Active Record を使って Database に直接アクセスするのがよいだろう。複雑性が増してきたら、 Database の振る舞いを別のレイヤに分けるのが良い

  • 覚えておいてほしいのは、すべての機能をもつ database-mapping layer をつくる必要はないということだ。作りきるのは複雑だし、そのようなものは利用できる状態にある(ライブラリ等を指していると思われる)

Java のコード例
  • AbstractMapper
    • +loadAll(resultSet)
    • +findMany(statementSource)
  • PersonMapper
    • +findByLastName(lastName)
    • +update(Person)

(自分のメモ)

Chapter 13: Object-Relational Metadata Mapping Patterns

Repository

  • Repository は Domain Model と Data Mapper の中間に位置する。メモリ上のドメインオブジェクトの集合のようになる

  • コンセプトとしては、Repository は、データストア(RDBなど)に永続化されたデータやそれに関する操作を包んで、よりオブジェクト指向なビューを提供するもの

  • ドメインレイヤ と データマッピングレイヤを分割し、それらの間の依存関係をなくすもの

  • Repository の Clients (呼び出し元) は Criteria を作成する。例としては criteria.equals(Person.LAST_NAME, "Fowler")

  • Repository は repository.matching(criteria) のようなインターフェースを提供し、 Criteria に定義された条件に合致するドメインオブジェクトを返す

  • Repository は Metadata Mapping と Query Object を組み合わせて、 Criteria から SQL を自動で生成するようなもの

  • たくさんのドメインオブジェクトの型があり、クエリも多様化しているのであれば、 Repository はクエリに関わるコードの量を減らすことができる

Return to top