Reflectionパターン考察

アーキテクチャパターンで触れたように帳票フォーム編集パッケージにReflectionパターンを採用しました。

フォーム上のテキストボックスでは、Caption, FontName, FontSizeなどのプロパティを持たせて、これらプロパティに応じた印刷を行うようにします。これらのプロパティはプログラム上もクラスのプロパティとしてインプリメントしています。このような仕組みで印刷を行う処理は問題なく書けます。今回はこれらのプロパティを編集できるようにしなければなりません。プロパティ毎にSetter, Getterを呼んでいてはプロパティエディタの機能は到底作れないのでDelphiに備わっている実行時型情報(RTTI)を利用して、オブジェクト・プロパティ名文字列・値を指定してプロパティを設定・取得する汎用的なメソッドを定義しました。

キーになるのがプロパティ名なので、プロパティのコレクションを扱ったりプロパティの値を列挙したり、Undo, Redoを実現したりといったことがやりにくく似通った処理の記述が増えてリファクタリングが必要になってきました。そこでプロパティを一つのオブジェクトして扱うように改めました。プロパティを表すオブジェクトは実行時型情報から作り出します。このようにすることでプロパティのコレクション・列挙を扱うのに通常のクラスライブラリが使えるようになり、文字列解析処理も減りました。冗長な記述もなくなって結果的にプログラムがすっきりしたと思います。

実行時型情報などのメタデータを使って汎用性を持たせるパターンをReflectionパターンと呼びます。

Reflectionパターンについて別の例で考察してみました。販売管理を考えてみると、伝票番号・商品・数量・単価・金額などが伝票の属性として必要になります。これをシステムにインプリメントするとき、2つのアプローチがあると思います。一つは伝票をクラスとし伝票番号などの属性をクラスのプロパティにするものです。もう一つは伝票をコレクションとして扱い、個々の属性は属性名をキーとするコレクションの要素として扱うものです。

クラスプロパティによる表現では業務分析により導出したモデルがそのまま設計上のクラスになります。金額の計算は金額=数量*単価といった具合に直感的な記述ができるのです。デメリットは汎用的に属性を扱うことができなくなることです。コレクション要素による表現では汎用的に属性を扱うことができますが、属性相互の関係式はItem['金額'].Value=Item['数量'].Value*Item['単価'].Valueといった風に冗長な記述になってしまうデメリットがあります。

オブジェクト指向ではこの2つの表現に関わる矛盾を解決してくれません。Reflectionパターンは一つの解決策なのです。これ以外に言語仕様でカバーできる物もあります。私が扱った言語の中で、JavaScriptは連想配列の要素はそのまま属性になります。Perl,
Rubyもクラス属性とコレクション要素を簡単に変換できる機能を備えています。Accessではほとんどの局面で属性をコレクション要素として扱いますが、フォームではフィールド名・コントロール名がそのままフォームのプロパティ名になります。使ったことはありませんがO/Rマッピングも同様の問題を解決するための物でしょう。

クラスプロパティ表現とコレクション要素表現の矛盾、決定打がないためにあちらこちらでいろんな解決策が模索されている状態ととらえられそうです。

現在はIDEの機能を利用することを前提にクラスのプロパティ表現としています(IDEとアーキテクチャ参照)。

Google検索:Reflection パターン, ドメインモデル, O/Rマッピング