DelphiやC++Builderは、ビジュアルな操作ですばやく目的のアプリケーションを開発でき、プロトタイピングやスパイラル式の開発を行うRAD手法をビジュアルにサポートします。コンポーネントと呼ばれる再利用性の高いプログラム部品を組み合わせることで、高度なデータベースアプリケーションもすばやく開発できます。しかし、作成したアプリケーションは、将来的にメンテナンスしつづけなければならず、「作り捨て」というわけにはいきません。特に、データベースサーバーやOSのバージョンアップ、ハードウェアの入れ替えなどに伴うマイグレーションでは、アーキテクチャや使用するテクノロジーの変更など、単純な移行作業だけでは済まない、さまざまな問題が発生する可能性が内在します。
本書では、将来的なマイグレーションを見越したデータベースアプリケーション構築の指針を紹介するとともに、現実にマイグレーションの必要に直面している方のために、その基本的な考え方を示します。
※この文書は、第1回ボーランドデベロッパーキャンプのテクニカルセッション「データベースアプリケーション構築技法」の講演内容をベースに執筆しました。
データベースアクセステクノロジーの理解
Delphi/C++Builderでは、VCL(Visual Component Library)と呼ばれるプログラム部品が提供されており、これによって、GUIアプリケーション、データベースアプリケーション、多層アプリケーション、Webアプリケーションなどを開発できます。VCLは、オブジェクト指向技術に基づいて作られており、すべてのコンポーネントは、コンポーネントの基本的な振る舞いを定義したTComponentクラスを派生させたクラスです。オブジェクト指向技術を用いることで、コンポーネントの再利用性、拡張性を高め、ツールが提供するコンポーネントでも、自作のカスタムコンポーネントでも、区別なく利用できるようになっています。
データベースアクセス技術も、このVCLの一部として提供されており、コンポーネントの組み合わせによって、極めてわずかのコーディング量で、データベースアプリケーションを開発できます。
データベースコンポーネントは、大きく分けて、データベースへの接続/トランザクション、データの取得(データセット)、データの供給(データソース)、データの表示/編集(データコントロール)という4つの役割を担うそれぞれの部品が用意されている。これらをプロパティによってつなぎ合わせる(例えば、データ表示用のコンポーネントのDataSourceプロパティに、データ供給用のコンポーネントを指定する)ことで、データベースアクセスの一連の機能が働きます。

図1 データベースコンポーネントの役割
現在利用できるデータベース接続形態には、さまざまなものがありますが、これらに対してそれぞれコンポーネントセットが提供されています。現在利用可能なコンポーネントセットには、以下のようなものがあります。
・BDE(Borland Database Engine)
・dbExpress
・ADO
・InterBase Express
・Oracle Data Access Components
これらは、接続アーキテクチャが異なるため、コンポーネントの形態や機能が異なります。しかし、いずれのコンポーネントセットも、データソースによって共通のインターフェースを提供できるため、ユーザーインターフェース層は共通化できます。
表:接続形態ごとのコンポーネント

データモジュールによるカプセル化
データベースアプリケーションのメンテナンス性を考えるとき、ユーザーインターフェース層とデータアクセス層の分離性は極めて重要なファクターになります。VCLでは、データモジュールと呼ばれる、データベースアクセスコンポーネント用のコンテナを用意しています。データモジュールは、非ユーザーインターフェース要素(つまり表示されないコンポーネント)を配置し、管理することができます。
データモジュールを使わない場合の弊害として、次のようなケースを考えてみてください。
従業員データを表示するために、フォームにデータコントロールを配置します。データアクセスのための各コンポーネントも、同じフォームに配置します(これらのコンポーネントは実行時は目に見えないので、使う側からすればどこにあろうが関係ありません)。データの取得や更新はこれらのコンポーネントを経由して行いますが、別のフォームでも従業員データを表示する必要がありました。ここでも新しいフォームにデータアクセスコンポーネントを配置して、簡単に済ませます。

図2 フォームに直接貼り付けたデータセットは同期を考慮しない
このような方法で開発したアプリケーションには、データの同期という概念が欠落しています。あるフォームでの更新は、そのフォームに配置されたデータセットに対する更新であり、別のフォームのデータセットとは同期を取っていません。もし、両者の同期を取りたいのであれば、何らかのコードを書き加えなければなりません。
データがどのように供給されているかについての理解なしに作られたアプリケーションに対する場当たり的な対応コードは、メンテナンス性を著しく損ねる結果になります。データモジュールを使用して、データアクセスを一元化しなければならない理由はここにあります。
また、データアクセスの一元化は、アクセス方法の変更やそのデータの利用形態(Windowsクライアント、Webアプリケーション、Webサービスなど)の変更、追加などに対しても、柔軟性を与えることになります。データベースアプリケーションのマイグレーション、機能拡張を容易にするには、まずデータモジュールを利用することが、重要な第一歩です。

図3 データモジュールの利用
データモジュールを利用する場合の注意点としては、データアクセスコンポーネントに対する操作をデータモジュール自身でカプセル化することです。例えば、データモジュールに配置したTSQLConnectionを、他のフォームから直接操作してデータベースに接続するようなコードを記述すると、データアクセスの分離性は損なわれてしまいます。こうならないためには、データモジュール側で、こうした操作を行うアクセッサーメソッドを定義し、外部からは、これらのメソッドを通してでしか、データアクセスコンポーネントを操作しないようにします。データアクセスについては、例外などのエラー処理を含め、データモジュール内にデータ操作コードを完結した形で実装します。
パフォーマンス劣化の潜在要因
VCLのデータベースアクセスコンポーネントは、デスクトップデータベースからSQLデータベースまで幅広いデータソースに対応しています。当然、そのデータ取得のための対価は、接続形態やデータベースアーキテクチャ、データベースの場所(ローカルかリモートか?)などによって異なります。
ユーザーインターフェースレベルで見ると、これらの違いは隠蔽されているため、なかなか気付きにくいのですが、背後にある技術的前提を忘れていると、接続形態の変更や扱うデータ量の変化などの要因によって、問題が一気に顕在化してくることがあります。
BDEは、元来デスクトップデータベースを前提に作られたアーキテクチャであり、SQLデータベースに対する接続方法としては、現在、他の接続方法を推奨しています。すでにBDEに対するメンテナンス/サポートは終了していますから、新規にアプリケーションを開発する場合には、別の方法を選択することになると思いますが、既に開発済みのアプリケーション、あるいは、BDEで用いていたデスクトップデータベース的な手法をそのままSQLデータベースアプリケーションに適用している場合には注意が必要です。
SQLデータベースを用いる場合の基本的な方針は、サーバー側で適切な処理を行い、クライアント側には最小限の結果セットを持ってくるような設計にするということです。いくつか例を挙げましょう。
Tableタイプのコンポーネントを使わない
Tableコンポーネントは、実質的に ”SELECT * FROM TABLE” にすぎません。データ量が増加したときに、不要なデータをクライアント側に持ってくる結果になります。SQLデータベースでは、必ずQueryタイプのコンポーネントを使って、WHERE節によってデータベースのクエリー機能を使ってデータを取得するようにします。
Filterプロパティを安易に使わない
Filterプロパティは、データベースサーバーから取得した結果セットに対して、フィルター操作をかけます。もし、フィルターをかけた結果のデータしか使わないのであれば、サーバー側でフィルタリングしておくべきです。つまり、WHERE節を指定するということです。
RecordCountプロパティを使わない
RecordCountプロパティも、結果セットに対してレコード数をカウントします。データベースのレコード数を得るためにすべてのデータをサーバーから取得するのはナンセンスです。”SELECT COUNT(*)” で十分です。もし、結果セットをforループなどでフェッチする場合には、RecordCountを参照してカウンター変数をチェックするのではなく、Eofプロパティで次のレコードがあるかどうかを確認できます。
SQLを何度も発行して結果が得られるような処理は実装を考えよう
何回もSQLを発行してやっと結果が得られるような処理については、ストアドプロシージャやビューを使って実装できないか考えましょう。最終的な結果が得られる前に、何度もクライアント/サーバー間でデータが行き来するのは効率的ではありません。
マイグレーションの指針
データベースアプリケーションのマイグレーションにあたっては、接続形態の変更、利用するコンポーネントの変更などによって、大なり小なりの修正が必要になります。その際に、上記のようなポイントをしっかり理解し、分離性の高いアプリケーション構造をとっていれば、その作業は明確にゴールの見えるものになります。しかし、ユーザーインターフェースとロジックが混在し、修正すべき箇所が掌握できないような渾然としたアプリケーションのマイグレーションに着手すると、ゴールの見えない作業に陥る可能性があります。
マイグレーションにあたっては、こうした前提を理解し、どこを修正すべきかを明確に把握することが重要です。そのためには、マイグレーションの準備作業として、既存アプリケーションの設計変更も行わなければならない場合があります。
以下にマイグレーション実施のおおまかなステップを示します。

図4 マイグレーションのステップ
マイグレーションに際しては、マイグレーション前の環境で、アプリケーションがそもそも抱えていた問題をつぶしておくことが重要です。マイグレーションによって、こうした問題はしばしば顕在化します。しかし新しいバージョンに移行したことによって発生した問題(VCLや言語仕様の変更、コンポーネントの変更による影響)なのか、元々アプリケーションが抱えていた地雷なのかを切り分けておかないと、両者が渾然となったエラーによって、原因究明が難しくなる恐れがあります。アプリケーションがアーキテクチャ的に正しく作られているのであれば、移行作業はそう難しくありませんが、現実には、そうでないケースが多々あります。この点を踏まえて、しっかりとした事前調査をするべきでしょう。
関連情報:
デベロッパーキャンプ資料:「データベースアプリケーション構築技法」#1(PDF:425KB)
デベロッパーキャンプ資料:「データベースアプリケーション構築技法」#2(PDF:393KB)
デベロッパーキャンプ資料:「データベースアプリケーション構築技法」#3(PDF:383KB)
Connect with Us