[Contribution to Japan PLoP]
RDBアプリケーションのためのデザインパターン
RDB とオブジェクト指向
パターン記述のきっかけ
パターンの紹介
このパターンに期待すること
リレーショナルデータベースとオブジェクト指向アプローチには、「表を中心とする集合演算」と「オブジェクトの相互作用」という、セマンティクスギャップ(意味的ギャップ)があり、両者のマッピングは水と油などと言われることもあります。確かにオブジェクト指向データベースを適用できれば非常に簡単に永続化をすることができますが、既存システムとの共存やSQLベースの検索ツールへのニーズなどから、RDBを適用するケースはまだまだ多いようです。
データベースの概念スキーマ設計や、論理レベルの実体関連図は、オブジェクト指向アプローチでの分析段階のモデリング(概念モデリングやドメイン分析などと呼ばれる作業)は、非常によく似ています。しかし実装段階になると、RDBは一筋縄ではいきません。特にSQLの文字列を生成するロジックなどは、プログラミング上は、非常に煩わしい冗長な手続きになってしまいます。
一方、オブジェクト指向アプローチは、適切に役割分担されたオブジェクトが相互作用するようにシステムを表現することで、”複雑な問題を単純な解決策に分解しようとする考え方”であるとみることができます。つまり、オブジェクト指向アプリケーションにRDBを適用するのではなく、RDBアプリケーションにオブジェクト指向設計を適用すると考えると、両者のマッピングはあながち不自然であるとも言えません。
このパターンは、パターンを考えようとして作ったものではなく、実際に経験した2つのプロジェクトで構築したアーキテクチャを「パターン」という形式を使ってまとめたものです。基本的な部分は、最初のプロジェクトで考えたものですが、2度目のプロジェクトではそれを再検討し、一部を変更して使いました。実際に2度目のプロジェクトの時には、最初の時に考えた多くのアイデアを再利用できたため、比較的スムーズに仕事を進めることができました。
ここに挙げたパターンは、Gang of Four
の23のデザインパターンような、抽象度の高いものではありませんが、少なくとも私の中では「パターン」となっていたものです。喉元を通り過ぎると色々なことを忘れてしまう私としては、そのとき考えたアイデアを将来のために何らかの形でまとめたいと思っていました。ちょうどその頃、Japan
PLoP からパターン募集の呼びかけがあったことから、その機会を利用することにしました。
- PERSISTER
永続記憶に格納されるオブジェクトを、業務処理を担当するオブジェクトと永続処理を担当するオブジェクトに分離する。
基本的な考え方は、業務処理手続きからSQLを発行する手続きを分離させることです。ドメインオブジェクトを明確に役割分担された2つのオブジェクトに分離することで、アプリケーション構造の見通しを良くし、特定のDBMSベンダー固有のインタフェースを隠蔽して、記憶媒体の構造や種類の変更を容易にすることを狙いました。
- QUERY ITERATOR
永続記憶から特定の条件に合致する複数のオブジェクトを取り出す際に、内部構造を意識させない抽象的なインタフェースを提供する。
RDBアプリケーションで1件単位の登録・更新・検索のメカニズムだけを定義したのでは片手落ちで、条件指定によるクエリー処理は避けて通れません。ここでは、条件検索の時に特定のベンダー固有のインタフェースから独立し、かつ一度に大量のメモリリソースを圧迫しない仕組みを提案してみました。
- HEADER DETAIL
ヘッダー−明細形式のオブジェクトの永続処理をシンプルな方式で実現する。
ビジネスアプリケーションでは、注文と注文明細、売上と売上明細といったようなヘッダー・明細型の情報がしばしば登場します。これをオブジェクト指向的にシンプルに考えると、ヘッダーと各明細それぞれを1件処理として扱ってしまいがちですが、それでは明細の数が減るような更新がされた場合にうまく制御できません。また削除や更新のときに、(古い)明細を1件1件削除していたのでは、効率上も好ましくありません。ここでは明細オブジェクト群の永続化をまとめて処理するような
DetailPersister
インタフェースを導出することで、ヘッダー・明細型のオブジェクトの永続化処理をシンプルで、かつ効率の良い方式を提案しました。
- SQL UTILITY
リレーショナルデータベースを使ったシステムにおいて、SQL 文字列の生成ロジックを容易にする。
Gang of Four
の23パターンこそパターンだと考えているような方からすると、これは非常に貧弱な、とてもパターンとは言えないような代物でしょう。そもそもは隣の席にいた当時新入社員のエンジニアが、非常にたくさんの項目を持つテーブルをアクセスするための
SQL を書く羽目に陥ったときに、カンマやクォーテーションなど SQL
の文法を間違えないために工夫して作った関数をプロジェクト全体で共通に使えるようにしたのがきっかけでした。複雑な条件の WHERE 句 など、SQL
のさまざまな機能をサポートしようとすると大変なことになりますが、ごく単純な機能だけをサポートするものであっても、一緒に開発をしたメンバーからは案外重宝されたものでした。
- TRANSACTION CONTEXT
トランザクション処理に依存する情報、あるいはシステム全体で共通な情報を、オブジェクト間で暗黙的に共有する。
Japan PLoPのワークショップの時に、「PERSISTER
でトランザクション制御はどうやるのか?」という質問を受けたのですが、それに対する回答としてこのパターンを書きました。これは知っている人にとっては、非常に当たり前の定石的な手法で、今さら「パターン」として提案するには、あまりにも平凡なアイデアです。しかしこんなものでも名前をつけてパターンとして整理することに意味があるのではないかと思いました。(POSA
本でも「ブローカー」や「マイクロカーネル」といったものがパターンとして紹介されていますね。このパターンは CORBA
のトランザクションサービスなどと絡めてより深い議論をすると、それなりに立派な読み物にできるかもしれません。)
ここの紹介したものはまだまだ完成度が低く、「パターン」などと呼ぶのはおこがましいかもしれません。
RDBとオブジェクト指向のマッピングについては、これ以外にもさまざまな方式が提案されているようで、少なくともここに書かれたものが唯一の正解でないことだけは確かなようです。
このパターンがあなたのプロジェクトでそのまま正解となったり、このパターンを見て「この通りやってみよう」と思っていただければそれはとても嬉しいことです。しかし実際にはシステムによって、色々な要件や前提条件があるはずですから、このやり方ではうまく行かないケースもたくさんあることでしょう。そんな場合でも、このパターンに書いてあることを読んでいただければ、そこを出発点にすることができます。そこには私達が経験し、考えたことが書かれていますので、少なくとも「思考を節約する」ことができると思います。
そして、これよりもっと良いアイデアや改善すべき点があれば、是非教えてください。
Japan PLoP やオブジェクトの広場のメーリングリストを使って、パターンに関する議論ができればと思っています。
© 1999 OGIS-RI Co., Ltd. |
 |
Index |
|