O/Rマッピングで失敗しない分析・設計のポイントJavaのDBアクセスを極める(2)(2/3 ページ)

» 2005年03月10日 00時00分 公開
[諏訪勇紀 著, 安間裕 監修アクセンチュア・テクノロジー・ソリューションズ]

2. レイヤの役割・責任範囲の明確化およびカプセル化

 それでは、上記で発生要因として推測された項目に、どう対処すればよいかを考えてみます。発生要因をさらに簡潔に整理してみると、問題(1)の根本原因は以下の2点になります。

  • レイヤごとの役割・責任範囲が実装可能なレベルまで詳細に明確化されていない
  • 各レイヤ間に強い依存が発生している(密結合状態)

 まず、1つ目の原因である「レイヤごとの役割・責任範囲が実装可能なレベルまで詳細に明確化されていない」について、具体的に解決法を探ってみましょう。解決する方法は一言でいってしまえば、「役割・責任範囲を明確にすること」ですが、ビジネスロジック・レイヤとデータベース・レイヤに関する役割を一例として挙げてみます。表2「レイヤ別の役割・責任範囲の定義例」を参照してください。

 役割・責任範囲を決めていく詳細な手順については、第3回の記事で解説する予定なので今回は割愛しますが、このように、レイヤごとの役割・責任範囲を明確にすることで、レイヤ間で齟齬(そご)がある設計・実装に陥る可能性は低くなると考えられます。ただし、役割・責任範囲は全体(開発プロジェクト全体またはレイヤ間同士)で同意が取れなければ意味がなくなってしまいます。これは、非常に重要なポイントとなります。

役割・責任範囲
ビジネスロジック・レイヤ 業務機能を実現するための業務ロジックを設計・実装する
データベース・レイヤが実装したトランザクション用のメソッド(begin()、commit()、rollback()、end())を使用し、業務トランザクションの制御を設計・実装する
業務トランザクション内のエラーハンドリングを設計・実装する
ビジネスロジックで扱う業務データモデルに準じたエンティティ・クラスを設計・実装する
データベース・レイヤに必要なデータベース問い合わせ処理の要件(どういったデータの問い合わせ処理が必要か)を提示する
データベース・レイヤ ビジネスロジック・レイヤにより要件として提示されたデータベース問い合わせ処理(Select、Update、Delete)を設計・実装する
O/Rマッピング(データベース・データモデルと業務データモデルとのマッピング)を設計・実装する
トランザクション用メソッド(begin()、commit()、rollback()、end())を設計・実装する。
コネクションプールなどのConnection制御アーキテクチャも設計・実装する
表2 レイヤ別の役割・責任範囲の定義例レイヤ別の役割・責任範囲の定義例

 次に2つ目の原因「各レイヤ間に強い依存が発生している(密結合状態)」について、具体的に解決法を探ってみましょう。これを解決するためには、「レイヤのカプセル(隠ぺい)化」が必要になります。カプセル化とは、オブジェクト指向で出てくるカプセル化の概念とほとんど同じ意味になります。オブジェクト間の依存を極力なくし、データの隠ぺい性の保証およびクラスの拡張性の確保を目的としているオブジェクト(クラス)のカプセル化と同様に、レイヤ自体をカプセル化することにより、各レイヤ同士で依存の少ない疎結合の状態にすることが可能になります。カプセル化の方法は次項で説明します。

3. レイヤのカプセル化を実現するデータベース・アクセス・インターフェイス設計のポイント

 レイヤのカプセル化を実現する方法は、実装要件が実現可能であることを前提として、各レイヤ間でデータを受け渡しするインターフェイス(例えていえば、玄関です)を抽象化(集約)することです。インターフェイスを抽象化(集約)する理由は、必要以上のインターフェイスの存在は、メンテナンス性の低下を招くと同時に、必然的にレイヤ間の依存も強くしてしまう可能性があるからです。図4を参照してください。この例では、業務機能ごとにデータベース・レイヤが1対1の関係でインターフェイスを用意しています。これは、ビジネスロジック・レイヤ側にデータベース・レイヤのすべての処理をさらけ出しているのと同義になり、依存関係を強く持った実装になってしまう可能性が高いと考えられます。

図4 業務機能ごとにデータベース・レイヤがインターフェイスを定義している例 図4 業務機能ごとにデータベース・レイヤがインターフェイスを定義している例

 どういった設計が望ましいかを理解するために、図5を参照してください。

図5 データベース・レイヤのインターフェイスを抽象化(集約)した例 図5 データベース・レイヤのインターフェイスを抽象化(集約)した例

 この例では、データベース・レイヤのインターフェイスを抽象化することで1つに集約させ、データベース・レイヤのDAO実装クラスは、このインターフェイスを実装する形でFactoryパターン注1 により設計・実装しています。このようにインターフェイスを抽象化(集約)させデータベース・レイヤをカプセル化することで、問題(1)の解決だけでなく、以下のことが実現可能になります。

  • レイヤ依存の疎結合により、ビジネスロジック・レイヤは、テーブル構成変更などの影響を最小限に抑えることが可能になる(問題(1)が該当)
  • ビジネスロジック・レイヤからRDB(データベース・データモデル)が見えなくなり、ビジネスロジック・レイヤ上のオブジェクトは業務データモデルに専念できる
  • DAOオブジェクトを呼び出すビジネスロジック・レイヤ側の業務クラスの実装もシンプルになり、メンテナンス性においても効果が期待できる
注1 Factoryパターン
デザインパターンの1つで、オブジェクトを生成するときのインターフェイスだけを規定して、実際にどのクラスをインスタンス化するかはサブクラスが決めるようにする設計・実装パターン。

Point

  • レイヤごとの役割・責任範囲をまず開発プロジェクト全体で同意したうえで、明確にすることが設計の大前提である。
  • レイヤごとの役割・責任範囲が決定したならば、レイヤ間の依存度を抑えるためにレイヤ内処理をカプセル化する設計を行うことが重要である。
  • レイヤのカプセル化を実現するためにインターフェイス設計は、必要最小限のインターフェイスのみを公開し、極力インターフェイスを抽象化(集約)する設計を心掛けることが重要である。

次ページに続く)

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。