MOSS リストアイテム取得メソッドの怪

2008/10/31
★★★★
今回は、MOSS の開発系の話。MASUDAQ.COM 提供予定の MOSS Web パーツの開発を進めていた所、一つの謎にぶち当たった。それは、MOSS のオブジェクトモデルを利用して、リストアイテムを取得するロジックについてだ。
MOSS のリストは、Microsoft.SharePoint 名前空間の SPList クラスで表現される。
この MOSS のリスト SPList に対して、リストアイテムは、同名前空間の SPItem で表現される。
SPList オブジェクトから、SPItem を取得するインターフェースは、多数にあるが、今回の開発では、リストアイテムの ID が分かっていたため、リストアイテムの ID をキーにして、リストから、該当するリストアイテムを取得するロジックをコーディングする必要あがった。
ここで、MOSS オブジェクトモデルリファレンスを参照し、以下の二つの方法によりリストよりリストアイテムのオブジェクトインスタンスが取得できることが分かった。

//一つ目の方法 SPList list = null;
int itemId = 5;
//SPListのインスタンス化は略
SPItem item = list.GetItemById(itemId);

//二つ目の方法 SPList list = null;
int itemId = 5;
//SPListのインスタンス化は略;
SPItem item = list.Items[itemId];

一つ目の方法は、実にオーソドックスで、プログラマーに優しいメソッド名 GetItemById() メソッドを利用した例。筆者的には、少々手間はかかるかもしれないが、プロパティやらインデクサやら特定言語(ここでは、C#)のメソッド拡張は、好まない。何故なら、言語独自の拡張されたメソッドの定義を行わなければ、第三者が見ても言語特有の知識を有することなく、プログラムを判読可能であるからだ。
二つ目の方法は、正に C# ここにありといったような、リストアイテムのコレクション (SPListItemCollection) オブジェクトから、インデクサに値を指定して、 SPItem を取得する方法である。
両方の方式とも返却値に違いは無い。ではどう使い分けたらいいのか?内部実装は同じで冗長なインターフェースが定義されているだけなのか?筆者を疑問を抱き、二つの方式を評価することにした。
まずは、パフォーマンスの観点で評価した所、GetItemById メソッドを利用した場合と、SPListItemCollection のインデクサを利用した場合では、パフォーマンスに圧倒的な差があることが分かった。
結果、SPListItemCollection のインデクサを利用した場合より、GetItemById メソッドを利用した方が圧倒的にパフォーマンスが高いことが分かった。
リストアイテム件数が少ない場合は、パフォーマンス的な違いは僅差しかないが、1万件位のリストアイテムを保持するリストでは、もちろんハードウェアのスペックにもよるが、体感できる程の処理速度の差があった。
さらに、色々と調査した結果、GetItemById は、ハッシュテーブルのようにキー (ここでは、リストアイテムの ID) からバリュー値 (ここでは、リストアイテム) を取得するようなロジックになっているのではと推察された。
SPListItemCollection のインデクサを利用した場合については、リストアイテムのコレクションから順次リストアイテムオブジェクトを取り出し、取り出されたリストアイテム ID と引数(インデクサ)より入力されたリストアイテム ID を評価し、同値であった場合は、そのインスタンスを返すロジックになっているのではと推察された。
筆者の最近の傾向もそうであるが、C# でオブジェクトモデルを扱う場合、インターフェースにインデクサが定義されていれば、何故か誘引されてしまいインデクサを利用してしまうことがある。
これは、.NET Framework の標準のオブジェクトモデルの多くのコレクション系のクラスにインデクサが定義されており、もちろん、GetItemById のような戻り値のみで見ると重複しているインターフェースの定義がなく、特にインデクサを利用した場合に性能的な劣化は無いという慣れからインデクサに誘導されてしまっているのだろう。
.NET Framework のオブジェクトモデル自体はさほど問題にはならないと思うが、各種のプロダクト用に定義、提供されている API には、十分注意を払うことが必要だと悟った。

コメント (0)

コメントの投稿