日本オラクル
プロダクトSC本部 テクノロジーSC部
佐藤 裕之


皆さんこんにちは、この度連載を担当させていただく、佐藤裕之です。普段の業務は、アプリケーションサーバ関連のSE?をしています。細かく説明すると自分でも職種が分からない様な、何でも屋ともいいます。あと、今の自分の中での旬が大型自動二輪(硬い言い方?)、日々振り回されながら乗車中です。

第1回:データアクセスことはじめ(前編)



 はじめに

システムを構築する上で必須となるデータベースアクセスの機能、皆さんはどのように実装しているでしょうか?JDBCで記述/EJB Entity Bean(BMP/CMP)を利用/データアクセスフレームワークを利用、等様々な実装方法を選択されているかと思います。
この連載では、様々な観点からデータアクセスに関わる事項を取り上げ、皆ささんがデータベースアクセスについて、少し考えてみる場になればと思っています。まず今回のデータアクセスことはじめ(前編/後編)では、これから様々なデータベースアクセスに関する事項を扱っていく上でのベースとなる知識を取り上げます。


 システムの論理的な階層

現在、Javaプログラミング言語を用いてエンタープライズシステムを開発する場合、要件変更への設計・実装の変更の容易性、JDBC、EJB Entity Beanなどのデータアクセス要素技術とのマッピングの容易性、等々の理由により、システム全体を論理的な階層に分け考えるのが一般的です。そのシステムの論理的な階層は、階層内に包含される機能別に分類されます。各論理的階層の名称/分け方(階層数)は、人により様々な名称/分け方(階層数)で呼ばれています。今回は、各階層の役割をある程度明確に出来るように、すこし細かめに分けた以下の論理的な階層で説明していきます。

【図】システムの論理的な階層

上記システムの論理的な階層は、Java環境特有のものではなくMicrosoft .NET等、他のプラットフォームでも似たような階層に分類されます。もっと言えばJavaの中でも人により分類方法が異なります。今回の階層で分類した場合、其々の階層の役割と、Javaにおける実装のための技術は以下のようになります。

【表】論理的階層の役割と実装技術
階層の名称 階層の役割 Javaを用いたシステムでの実装技術
ユーザインタフェース層 ユーザに対する画面の描写、ユーザからの入力の受付の制御 等 HTML/Java Script/JSP/AWT/Swing/JSP
アプリケーション層 ユーザ入力値の検証、画面遷移の制御 等 Servlet/Struts/JSF
サービス層 ドメイン層のロジックをアプリケーション層から利用しやすいように抽象化、ビジネスロジックのワークフロー制御、トランザクション・セキュリティ制御 等 JavaBeans(Java Class)/Stateless SessionBean
ドメイン層 対象となる業務のドメインロジック(ビジネスロジック) 等 JavaBeans(Java Class)/EntityBean(BMP/CMP)
パーシステンス層 ドメイン層のオブジェクトをデータストアに対して永続化するためのロジック。典型的には、リレーショナルデータベースに対してアクセスするSQLのコードを含む JavaBeans(Java Class)/EntityBean(BMP/CMP)

図の通りこれら階層は、サービス層によりユーザインタフェース側かビジネスロジック側かに分けることが出来ます。
また、これら階層は必ず実装しなければいけないものではありません。例えば、サービス層はクライアント側からのインタフェースとしての機能を提供するものですが、ドメイン層の実装によっては、ドメイン層自身にサービス層の機能を含め、サービス層が存在しない場合もあります。
今回のコラムでは、この中からデータベースアクセスに関わりのある、ビジネスロジック側の「ドメイン層」「パーシステンス層」を中心に扱っていきます。また、「データストア」に関しては、リレーショナルデータベースやオブジェクト指向データベースやメッセージ指向ミドルウェア(MOM: Message Oriented Middleware)等が考えられますが、最も選択される比率が高いと思われるリレーショナルデータベースを中心に扱っていきます。


 ドメイン層

それでは、まず始めにドメイン層からです。純粋にデータアクセスの役割は、論理的な階層の中でパーシステンス層が担当するのですが、このドメインロジック(ビジネスロジック)が含まれるドメイン層の実装方法でかなりパーシステンス層の実装方法の考え方が変わってきます。データアクセスを理解する上である程度、頭の中の整理が出来ていたほうが良いと思いますので少し見ておきましょう。
ドメイン層とは、「対象となる業務のドメインロジックが含まれた」層ですが、このドメイン層の実装を理解する上で有用なMartin Fowler氏が執筆された「Patterns of Enterprise Application Architecture(以下PoEAA)」の中で紹介されているアーキテクチャパターンをベースにご紹介していきます。PoEAA内ではドメイン層のアーキテクチャパターンとして、Transaction Script、Domain Model、Table Moduleの3種類を紹介しています。其々を順番にみていきます。

  Transaction Script

まず1つのアーキテクチャパターンはTransaction Scriptパターンです。一言でいうと「ドメインロジックを機能別に分け1つのプロシージャとして実装」といった感じです。
基本的にユーザインタフェース/アプリケーション層からの1つのトランザクション(リクエスト)に対応した処理を1つのプロシージャ(+ サブルーチン)としてドメインロジックを記述するパターンです。Transaction Scriptパターンからは直接データベースにアクセスするか、もしくはデータベースアクセスロジックをカプセル化したラッパークラス(パーシステンス層)を利用してデータベースにアクセスします。Transaction Script間での共通の処理は、サブルーチン化しても良いですが、トランザクション自身はTransaction Scriptパターンを実装した一つのプロシージャ内で完結する様にします。

【図】Transaction Scriptパターン概念図

では、実際の例をいきます。今回のコラムではオンラインオークションシステムのごく一部の単純なデータベーススキーマを元に、それにアクセスするドメイン層のアーキテクチャパターンをなるべく単純なコードで示してみたいと思います。
オンラインオークションシステムのデータベーススキーマは、ITEM/BID/SALEの3種類のテーブルを利用します。それぞれのテーブルの役割は以下の様になります。

【表】オンラインオークションシステムのテーブルと役割
テーブル名 役割
ITEM 出品するアイテムの情報を格納するテーブル
BID 入札の情報を格納するテーブル
SALE 落札が確定した情報を格納するテーブル

これら3種類のテーブルを生成するDDL(Data Definition Language)は、以下のものを利用します。

【コード】オンラインオークションシステムのスキーマ作成DDL
CREATE TABLE "ITEM" (
  "ITEM_ID" NUMBER NOT NULL,
  "ITEM_NAME" VARCHAR2 (16),
  "START_ITEM_UNIT_PRICE" NUMBER,
  "ITEM_AMOUNT" NUMBER,
  "DISCOUNT_TYPE" NUMBER,
  CONSTRAINT "ITEM_PK1" PRIMARY KEY ("ITEM_ID")
);

CREATE TABLE "BID" (
  "BID_ID" NUMBER NOT NULL,
  "USER_NAME" VARCHAR2 (16),
  "BID_DATE" DATE,
  "ITEM_ID" NUMBER,
  "BID_UNIT_PRICE" NUMBER,
  "BID_AMOUNT" NUMBER,
  CONSTRAINT "BID_PK1" PRIMARY KEY ("BID_ID"),
  CONSTRAINT "BID_FK" FOREIGN KEY ("ITEM_ID") REFERENCES "ITEM" ("ITEM_ID")
);

CREATE TABLE "SALE" (
  "SALE_ID" NUMBER NOT NULL,
  "ITEM_ID" NUMBER,
  "SALE_UNIT_PRICE" NUMBER,
  "SALE_AMOUNT" NUMBER,
  "SALE_DATE" DATE,
  CONSTRAINT "SALE_PK1" PRIMARY KEY ("SALE_ID"),
  CONSTRAINT "SALE_FK" FOREIGN KEY ("ITEM_ID") REFERENCES "ITEM" ("ITEM_ID")
);

このデータベーススキーマを元にTransaction Scriptパターンでドメイン層を実装してみます。Transaction Scriptパターンは、基本的にトランザクション(クライアントリクエスト)ごとにメソッドとして実装するパターンでした。下記BiddingServiceクラスのコード内では、findHighestBidPrice()メソッドとmakeSale()メソッドを実装しています。findHighestBidPrice()メソッドは、オークションアイテム内で、最高の入札額をBIDテーブルから取得し返します。makeSale()メソッドは、オークション出品者が出品時に、オークション主催者が予め定義した割引タイプ(ITEMテーブルのDISCOUNT_TYPEカラム列)を選択してあると仮定して、その割引きタイプを元に算出した落札額をSALEテーブルに挿入し、落札を確定します。

【コード】Transaction Scriptコード例: BiddingService.java
// BiddingService.java
// ----- 省略 -----
public class BiddingService {
    // SQL文
    private static final String FIND_HIGHEST_BID =
        "select bid_id, user_name, bid_date, item_id, bid_unit_price, bid_amount " +
        "from bid where bid_unit_price = (select max(bid_unit_price) from bid where item_id = ?)";
    private static final String MAKE_SALE =
        "select bid.bid_id, bid.item_id, bid.bid_unit_price, bid.bid_amount " +
        "item.discount_type" +
        "from bid, item where bid_unit_price = (select max(bid_unit_price) from bid where item_id = ?)";
    private static final String INSERT_SALE =
        "insert into sale (sale_id, item_id, sale_unit_price, sale_amount, sale_date) " +
        "values (?, ?, ?, ?, ?)";

    // 定数
    private static final String SALE_TABLE = "sale";
    private static final String SALE_PK = "sale_id";

    // アイテムの最高入札額をBIDテーブルから取得
    public int findHighestBidPrice(int itemId) throws AuctionException {
        Connection con = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        try {
            con = DBUtil.getConnection();
            pstmt = con.prepareStatement(FIND_HIGHEST_BID);
            pstmt.setInt(1, itemId);
            rs = pstmt.executeQuery();
            rs.next();
            int price = rs.getInt(5);
            return price;
        } catch (SQLException se) {
            throw new AuctionException(se);
        } finally {
            DBUtil.cleanUp(con, pstmt, rs);
        }
    }

    // 最高額の入札に割引き金額を適用し確定(SALEテーブルに挿入)
    public void makeSale(int itemId) throws AuctionException {
        Connection con = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        try {
            con = DBUtil.getConnection();
            pstmt = con.prepareStatement(MAKE_SALE);
            rs = pstmt.executeQuery();
            int bidId = rs.getInt(1);
            int bidUnitPrice = rs.getInt(3);
            int bidAmount = rs.getInt(4);
            int discountType = rs.getInt(5);  // 割引きタイプの取得
            int saleUnitPrice = 0; // 割引き適用後の金額

            switch (discountType) {
            case 1:
                //Type1のアルゴリズムを適用しsaleUnitPriceの算出
                //SALEを作成し、テーブルにインサート
                // 10個以上5%引き、20個以上10%引き
                if (bidAmount >= 10) {
                    saleUnitPrice = new Double(bidUnitPrice * 0.95).intValue();
                } else if (bidAmount >= 20) {
                    saleUnitPrice =  new Double(bidUnitPrice * 0.90).intValue();
                }
                break;
            case 2:
                //Type2のアルゴリズムを適用し、適用しsaleUnitPriceの算出
                // ----- 省略 -----
                break;
            case 3:
                //Type3のアルゴリズムを適用し、適用しsaleUnitPriceの算出
                // ----- 省略 -----
                break;
            default:
                //割引なしのアルゴリズム ----- 省略 -----
            }

            pstmt = con.prepareStatement(INSERT_SALE);
            pstmt.setInt(1, DBUtil.getNextId(SALE_TABLE, SALE_PK)); //主キーの生成
            pstmt.setInt(2, itemId);
            pstmt.setInt(3, saleUnitPrice);
            pstmt.setInt(4, bidAmount);
            pstmt.setDate(5, new Date(System.currentTimeMillis()));
            pstmt.execute();
        } catch (SQLException se) {
            new AuctionException(se);
        } finally {
            DBUtil.cleanUp(con, pstmt, rs);
        }
    }
}

今回のTransaction Scriptパターンの例であるBiddingService.javaは、SQLを直接Transaction Script内に記述し、ドメイン層とパーシステンス層が合わさった形式で実装してみました。もちろん、SQLをDAO(Data Access Object)等のデータアクセスをカプセル化したパーシステンス層に分離することも可能です。
Transaction Scriptは、基本に1つのメソッド内(共通の処理をサブルーチン化することも可能)で完結するため、多くの手続き処理型言語になれた開発者の方にその容易性は受け入れられるのではないかと思われます。
ただ、問題はドメインロジック多くなり複雑になってきた時です。Transaction Scriptで実装した場合、1メソッドに着眼して処理が実装されますので、必然的に他のトランザクションのことは考えなくなる(考えないことがメリットでもあるのですが)と思います。つまり、ドメインロジックが多くなればなるほど、各トランザクションでの共通したロジックであるサブルーチンが切り出しにくくなり、重複したロジックが増え、結果的に保守しにくいものになる可能があるかと思われます。


  Domain Model

2つ目のドメイン層アーキテクチャパターンは、Domain Modelです。一言で言うと「振る舞いとデータを持ったドメインオブジェクトとして実装」といえます。

Domain Modelはオブジェクト指向分析にしたがって、抽出されたドメインオブジェクトを元に実装します。当然、そのオブジェクトには振る舞い(ドメインロジック)が含まれます。例えば、「入札(Bid)」オブジェクトには、入札金額を計算し確定するための振る舞い(ドメインロジック)が含まれる等々。当然其々のオブジェクトで振る舞い(ドメインロジック)を持っているので、それらオブジェクトの持つ振る舞い(ドメインロジック)が連携し、全体の振る舞い(ドメインロジック)を構成します。また、これらDomain Model内に含まれるオブジェクトは、継承やポリモーフィズムなのオブジェクト指向言語の特性を利用することもできますし、GoF(Gang of Four)のデザインパターンなども適用しTransaction Scriptパターンよりオブジェクト指向的な実装が可能です。

【図】Domain Modelパターンの概念図

それでは、またオンラインオークションシステムを元に簡単なDomain Modelのサンプルコードを見ていきます。先ほどのTransaction Scriptでは、makeSale()メソッドがありました。このメソッドは、入札者が入札したBIDテーブルの中にある情報を元に、その入札最高額のものに、出品者が設定した落札個数による割引を考慮してSALEテーブルに挿入することにより落札を確定するものでした。仮にこのロジックが頻繁に変わりやすいものだとしましょう。例えば、実際に落札するときに出品者が割引き率を変更することができるようにしたい等、オークションサイトの特性を引き出すために様々な落札金額確定アルゴリズムが選択したいとします。このような時にStrategyパターンを利用することが出来ます。Strategyパターンは、GoFのデザインパターンの1つで「様々なアルゴリズムを呼び出し側のコードを変更せずに実行したい」時に利用するパターンです。では、Strategyパターンを適用したDomain Modelのサンプルを見ていきましょう。アイテムの情報をカプセル化したItemクラスです。

【コード】Domain Modelパターンのサンプルコード:Item.java
// Item.java
// ----- 省略 -----
public class Item implements Serializable {
    // フィールド
    private int itemId;
    private String itemName;
    // ----- 省略 -----

    // コンスラクタ
    public Item(int itemId, String itemName, int startItemUnitPrice,
        int itemAmount, int discountType) {
        this.itemId = itemId;
    // ----- 省略 -----
    }

    // アクセッサメソッド
    public int getItemId() {
        return itemId;    }
    // ----- 省略 -----

    // Strategyパターンの利用
    public Sale makeSale(Bid bid) throws AuctionException {
        return bid.makeSale();
    }
}

Itemクラスは、アイテムに関する属性をフィールド変数としてもち、其々のフィールド変数に対するアクセッサメソッドを持ちます。また、Bidクラス内のStrategyパターンを呼び出す、makeSale()メソッドがあるという単純なものです。それでは、実際のStarategyパターンを呼び出しているBidクラスを見てみましょう。

【コード】Domain Modelパターンのサンプルコード:Bid.java
// Bid.java
// ----- 省略 -----
public class Bid implements Serializable {
    // フィールド
    private int bidId;
    private String userName;
    private Date bidDate;
    private Item item;
    // ----- 省略 -----

    // コンストラクタ
    public Bid(int bidId, String userName, Date bidDate, Item item,
        int bidUnitPrice, int bidAmount) {
        this.bidId = bidId;
        this.userName = userName;
        this.bidDate = bidDate;
        this.item = item;
        // ----- 省略 -----
        // デフォルトのストラテジの設定
        this.saleStrategy = (SaleStrategy)new DefinedSaleStrategy(getItem().getDiscountType());
    }

    // アクセッサメソッド
    public int getBidId() {
        return bidId;
    }
    public void setBidId(int bidId) {
        this.bidId = bidId;
    }
    // ----- 省略 -----
    public Item getItem() {
        return item;    }
    public void setItemId(Item item) {
        this.item = item;
    }
    // ----- 省略 -----

    // Strategyパターンの変更用メソッド
    public void changeStrategy(SaleStrategy saleStrategy) {
      this.saleStrategy = saleStrategy;
    }
    // Strategyパターンの利用
    public Sale makeSale() throws AuctionException {
        return saleStrategy.makeSale(this);
    }
}

Bidクラス内では、コンストラクタでデフォルトのStrategyである、DefinedSaleStrategyクラスのインスタンスを生成し、フィールド変数に対し設定しています。つまり、Bidクラスのインスタンスを生成後何もせずにmakeSale()メソッドを呼び出した場合、デフォルトのStrategyであるDefinedSaleStrategyの落札金額確定アルゴリズムが適用されたSaleオブジェクトが返されます。また、デフォルトのStrategyであるDefinedSaleStrategyクラス以外のStrategyを利用するために、changeStrategy()メソッドを用意しています。このchangeStrategy()メソッドで新しいStrategyを追加することにより、呼び出し側のコードmakeSale()の実装を変更しなくても、落札金額確定アルゴリズムを変更することが出来ます。では次にStrategyパターンのインタフェースであるSaleStrategyインタフェースを見てみます。

【コード】Domain Modelパターンのサンプルコード:SaleStrategy.java
// SaleStrategy.java
// ----- 省略 -----
interface SaleStrategy {
    Sale makeSale(Bid Bid) throws AuctionException;
}

このSaleStrategyインタフェースにより、呼び出し側のコードを変更しなくても落札金額確定アルゴリズムを変更できるというポリモーフィズムを実現しています。また新たな落札金額確定アルゴリズムを追加したい場合、このSaleStrategyインタフェースを実装したクラスを開発し、Bid#changeStrategy()メソッドの引数として実行することにより、簡単にドメインロジックを変更・追加することが出来ます。次はこのSaleStrategyインタフェースを実装したデフォルトの落札確定アルゴリズムDefinedSaleStrategyクラスです。

【コード】Domain Modelパターンのサンプルコード:DefinedSaleStrategy.java
// DefinedSaleStrategy.java
// ----- 省略 -----
public class DefinedSaleStrategy implements SaleStrategy {
    int discountType = 0;
    // コンストラクタ
    public DefinedSaleStrategy(int discountType) {
        this.discountType = discountType;
    }
    // デフォルトの落札確定メソッド
    public Sale makeSale(Bid bid) {
        int saleUnitPrice = 0;
        int bidUnitPrice = bid.getBidUnitPrice();
        int bidAmount = bid.getBidAmount();
        switch (discountType) {
        case 1:
            //Type1のアルゴリズムを適用しSALEを作成
            // 10個以上5%引き、20個以上10%引き
            if (bidAmount >= 10) {
                saleUnitPrice = new Double(bidUnitPrice * 0.95).intValue();
            } else if (bidAmount >= 20) {
                saleUnitPrice = new Double(bidUnitPrice * 0.90).intValue();
            }
            break;
        case 2:
            //Type2のアルゴリズムを適用しSALEを作成
            //例えば5個以上5%引き、10個以上10%引き
            // ----- 省略 -----
            break;
        case 3:
            //Type3のアルゴリズムを適用しSALEを作成
            //例えば3個以上5%引き、5個以上10%引き
            break;
            // ----- 省略 -----
        default:
            //割引なしのアルゴリズムを適用しSALEを作成
        }

        Item item = bid.getItem();

        return new Sale(item, saleUnitPrice, bidAmount,
        new Date(System.currentTimeMillis()));
    }
}

DefinedSaleStrategyクラスにより実装されたデフォルトのアルゴリズムは予めオークション出品者が設定した割引きタイプであるItemのdiscountTypeフィールド(ITEMテーブルのDICOUNT_TYPEカラム)の情報に従い、条件分岐しそのアルゴリズムを適用した落札金額を算出します。ちなみに割引きタイプと割引きアルゴリズムは予めオークション主催者が決定してあるものとします。このデフォルトの割引きアルゴリズム以外に、任意の割引率を適用できるアルゴリズムを持ったクラスが次のCustomSaleStrategyクラスです。

【コード】Domain Modelパターンのサンプルコード:CustomSaleStrategy.java
// CustomSaleStrategy.java
// ----- 省略 -----
 public class CustomSaleStrategy implements SaleStrategy {
    double discountRate = 0.0;
    public CustomSaleStrategy(double discountRate){
      this.discountRate = discountRate;
    }

        // カスタムの落札確定メソッド
    public Sale makeSale(Bid bid) {
        int saleUnitPrice = 0;

        int bidUnitPrice = bid.getBidUnitPrice();
        int bidAmount = bid.getBidAmount();
        saleUnitPrice = new Double(bidUnitPrice * discountRate).intValue();
        Item item = bid.getItem();

        return new Sale(item, saleUnitPrice, bidAmount,
        new Date(System.currentTimeMillis()));
    }
}

CustomSaleStrategyクラスではコンストラクタの引数として与えられた割引率により落札金額確定するアルゴリズムもったStrategyパターンの実装です。このCustomSaleStrategyクラスのインスタンスを生成し、Bid#changeStragety()メソッドの引数として実行することにより、容易に新しいアルゴリズムに変換することが出来ます。
ここまでがサンプルコードです。

今回のDomain Modelのサンプルは、GoFのデザインパターンの一つであるStrategyを実装することにより、アルゴリズムの容易な変更を実装してみました。そのほかにも例えば、オークションアイテムをカテゴリ分けするためにItemクラスを抽象クラスとして、その実装クラスBookクラス、Stationery(文具)クラス等の継承を利用したり、オブジェクト指向の特徴・利点を比較的素直に実装できるのがDomain Modelの利点です。
一方、Transaction Scriptパターンに比べるとなんだか面倒だなと思われた方もいるのではないでしょうか?設計・実装する側にある程度のスキルが求められるのも事実かと思います。


  Table Model

3つ目のドメイン層のアーキテクチャパターンはTable Moduleです。一言でいうと「DB内のテーブル/ビューに関連したドメインロジックを1クラスとして実装する」といえます。

今回のサンプルの場合、Domain ModelパターンもBIDテーブルに対応したBidクラス、ITEMテーブルに対応したItemクラスという構成になっておりTable Moduleと似ていますが、ドメインロジックが複雑になればなるほど、その違いは明確になります。Domain Modelは、基本的な全くテーブル構造とは関係なく設計実装されます。一方、Table Moduleはデータベースのテーブル・ビューに関連したドメインロジックを1テーブルと対の1クラスとしてカプセル化したものです。ちょうど手続き処理をフォーカスしたTransaction Scriptパターンとオブジェクト指向にフォーカスしたDomain Modelパターンの中間のイメージです。

【図】Table Moduleの概念図

実装は、基本的にテーブルごとに一つのクラスを作る形になります。ドメインロジックはstaticメソッドとして実装して良いですし、インスタンスメソッドとして実装することも出来ます。Table Moduleはデータベースの1テーブルの操作に対応したドメインロジックが1つのクラスにまとまるので、機能別にメソッド単位で実装したTransaction Scriptよりも構造が明確になり、共通のサブルーチン等を抜き出す事が容易になるかと思います。一方、あくまでテーブルの構成に依存するので、Domain Modelの様なオブジェクト指向の特性、継承やポリモーフィズム、Strategyパターンの様なGoFのデザインパターンの様なきめ細かなオブジェクトモデルの構造をとることは難しいと思われます。


 ドメイン層アーキテクチャパターンの選択

Transaction Scriptパターン、Domain Modelパターン、Table Moduleパターンの違いを簡単に確認しました。それでは、皆さんはどれを選択すべきなのでしょうか?どれが、正しいと言うものでもないと思うのですが、PoEAAの中で各ドメイン層のアーキテクチャパターンをドメインロジックの複雑さと拡張に要する努力(コスト)の面で表したグラフがあります。Martin氏自身も科学的に証明されているわけではなく、感覚的にこんな感じと言っているグラフです。

【図】ドメインロジックの複雑性と拡張に要するコストの関連図

このグラフを見てどのように感じるでしょうか?ドメインロジックが簡単なシステムはTransaction ScriptパターンやTable Modelパターンで記述して、複雑なシステムはDomain Modelパターンを利用しますか?今まで見てきたように、Transaction Script、Table Model、Domainモデルは其々、何を主体として考えるかの思考の回路が結構異なります。つまり、そんなに簡単にはドメイン層のアーキテクチャパターンを変更する事は難しいかと思われます。ドメインロジックの複雑性でシステムごとにドメイン層のアーキテクチャパターンを変更するよりも、どんなに単純なシステムでも最初からDomain Modelのアーキテクチャパターンを適用すべきなのではないかと思われます。


 パーシステンス層

それでは、パーシステンス層のアーキテクチャパターンもみていきましょう・・・後編へ続く


【参考文献】
「Pattern of Enterprise Application Architecture」
Martin Fowler著
ISBN 0-321-12742-0
2002/11/05

「オブジェクト指向における再利用のための デザインパターン 改訂版」
Erich Gamma/Richard Helm/Ralph Johnson/John Vlissides 著
本位田 真一/吉田 和樹 監訳
ISBN4-7973-1112-6
改訂版 1999/11/1