ColdFusionMXでは新たにCFCが導入されました。CFCを使ってデータベース関連処理などをコンポーネント化 することによって、異なる種類のデータベースに対応したアプリケーションを開発するといったような場合にプログラムの再利用性を高めることができるようになりました。
例えば以下のような場合を考えてみましょう。
CFC概要:ユーザー情報を登録/取得するコンポーネント
メソッド:
addUserData() ユーザー情報の追加処理メソッド
getUserData() ユーザー情報の取得処理メソッド
Oracle用とSQLServer用それぞれに対して上記の仕様を持ったCFCを作成しておけば、案件に応じてCFCを入れ 替えるだけで他の部分のプログラムは変更しないで済みます。
ですが、この時にひとつ問題があります。Oracle用とSQLServer用のCFCを別々の担当者が作成した場合に、 作成したCFCのインターフェースが微妙に異なってしまう可能性があります。例えばメソッドの引数に指定する型(type)、 や必須かどうか(required)などです。こうしたインターフェースの微妙な違いは当初は不具合 としてすぐには見つかりませんが、CFCがいろいろな場面で利用されるにつれて顕在化してくることが多い のでなかなか厄介です。
そこで、ここではCFCの継承の仕組みを使って、こういったインタフェースの不一致を防ぐ機能をCFC自身に 持たせる方法をご紹介したいと思います。
まずCFCのインタフェース仕様を定義します。と言っても特別なことをするわけではなく、CFCに定義したい メソッドを記述していきます。ただし通常のCFCと違って以下の点が異なります。
・メソッドの中身にはダミーを入れておく
・インタフェースをチェックする基本CFC(ステップ2で作成)を継承する
このCFCは直接呼び出されることはなく、実際に利用されるCFCの雛型にあたるものです。今回のサンプルソースでは 「UserDataInterface.cfc」という名前で作成しています。実際に利用されるOracle用ユーザー情報操作コンポーネント やSQLServer用ユーザー情報操作コンポーネントはこの「UserDataInterface.cfc」を継承します。
GetMetaData()という関数を使うとCFCが実装するメソッドおよび継承元のCFCのメソッドなどの定義情報を取得することが できます。この関数を利用して、自分自身と継承元のメソッド情報を比較して、違いがあれば例外エラーを出す関数 「InterfaceCheck()」を作成し、この基本CFCに実装しておきます。この基本CFCは特定のビジネスロジックには依存しません。 ですので今回のようにデータベース関連処理に限らず、様々なケースで利用することができます。今回のサンプルソースでは 「BaseInterface.cfc」という名前で作成しています。
最後に実際に利用するCFCを作成します。このときに以下の2点をCFCに加えます。
・CFCの初期化処理部分(CFCOMPONENTタグと最初のCFFUNCTIONタグの間)で「InterfaceCheck()」をCFINVOKEタグで呼び出す
・インタフェースを定義したCFC(ステップ1で作成)を継承する
今回のサンプルソースでは「UserDataOracle.cfc」(Oracle用)「UserDataSQLServer.cfc」(SQLServer用)という名前で実際に利用される CFCを作成しています。(サンプルなので実際のSQL文は記述していません) もし、UserDataOracle.cfcやUserDataSQLServer.cfcに定義さ れているメソッドの各種属性がUserDataInterface.cfcの定義内容と異なっていると、CFOBJECTタグやCreateObject()関数でこれらの コンポーネントを生成した段階で例外エラーが発生し、具体的にどの個所が異なっているかを下図のように指摘してくれます。

これらのコンポーネントの関係を図示すると下図のようになります。

このように同じインタフェース仕様をを持っているけれども内部実装が異なるCFCを複数作成したい場合には、雛型となるCFCを 作成し、雛型と実際に作成されたCFCのインタフェースを比較する仕組みを組み込んでおくことで、実装時のミスを防ぎ、インタ フェースの一貫性を保証させることができます。今回作成したサンプルではインタフェースに定義されたメソッドが実装されているか? メソッドの属性は一致しているか?引数の名前や属性は一致しているか?といったことをチェックするようにしています。ですが、実装 側で雛型には存在しないメソッドを新たに追加することについてはチェックしていません。システムの要求定義によってはそれもチェック するようにした方が良い場合もあるでしょう。ご興味のある方はサンプルの「BaseInterface.cfc」を改良してみていただければと思います。
今回は以下のサンプルソースを添付しています。
サンプルソースの利用方法
1~4を同じディレクトリに入れて、3または4を呼び出すcfmファイルを作成します。3または4のメソッド定義の中の属性を 変更したりすると2で定義されている内容と異なるという旨のエラーが表示されますので、それでインタフェースチェック の機能が働いていることが確認できます。