VBにおけるテンプレートの必要性理解
プログラミングにおいて、DRY原則 - 「自分を繰り返すな」 - は、クリーンで効率的、かつ保守可能なコードを書くために欠かせないものです。この原則は、C++のような抽象化技術に対する限られたサポートのために冗長性が一般的なVisual Basic for Applications(VBA)のような言語で特に重要になります。
異なるオブジェクトタイプに対して同様の機能を実行する複数のコードスニペットがある場合、より効率的な解決策を検討する時が来ています。同様の操作を繰り返しコードに頼らずにどう統合できるでしょうか?
VBA内で、あるいは適用可能な新しいツールを使用することで、テンプレートを(ある意味で)活用する方法を掘り下げていきましょう。
問題: VBAにおける繰り返しコードスニペット
次の例を考えてみてください。ここでは、異なるタイプに対して本質的に同じことを行う2つのコードスニペットがあります。
Dim i as Obj1
Set i = RoutineThatReturnsObj1()
i.property = newvalue
Dim i as Obj2
Set i = RoutineThatReturnsObj2()
i.property = newvalue
この場合、両方のルーチンが異なるタイプのオブジェクトで代入とプロパティの設定操作を行っていることが明らかです。プログラマーは冗長性を減らすために、より一般化された解決策を作成したいと考えています。
意図された解決策
一般的なルーチンの作成
繰り返しコードを排除するために、プログラマーは両方のシナリオを処理できるルーチンを提案します。
Sub MyRoutine(o as ObjectType, r as RoutineToInitializeObject, newvalue as value)
Dim i as o
Set i = r
i.property = newvalue
End Sub
しかし、ネイティブVBAはC++のような高度なテンプレート機能を持っていないことに注意が必要です。したがって、VBAの制限内で同様の効果を得ることは難しい場合があります。
代替手段: VBAと共に.NETを使用する
従来のVBAはC++のようなジェネリックやテンプレートをサポートしていませんが、**Visual Studio Tools for Office (VSTO)**への移行は有効な代替手段を提供します。アプローチを現代化することに前向きであれば、.NETでジェネリックを使用することができます。
ジェネリックの実装
以下のように、.NETのコンテキストでジェネリックを活用できます。
Function MyRoutine(Of O)(R As Delegate, newvalue As Object) As O
Dim i As O = CType(r.Method.Invoke(Nothing, Nothing), O)
' どのプロパティを使用するかを指定するために別のパラメータが必要です。
' そして、リフレクションを使って値を設定します。
i.property = newvalue
return i
End Function
この例では:
- Of Oは、実行時に指定できる型パラメータを表します。
- CTypeは、呼び出されたデリゲートの戻り値を希望する型にキャストするために使用されます。
- プロパティの値を設定するためにリフレクションを利用し、指定されたプロパティへの動的なアクセスを提供します。これは従来のVBAでは不可能です。
結論
従来のVBAはC++のようなテンプレート機能を欠いていますが、コードの繰り返しを最小限に抑えるための代替方法があります。Visual Studio Tools for Officeと.NETを使用することで、ジェネリックを活用し、動的で再利用可能なコード構造を作成できます。
VBAプロジェクト内で異なるオブジェクトタイプに対して頻繁に同様のコードを書いている場合は、開発環境を現代化することを検討してください。これらの変更を受け入れることで、コードの明瞭さが向上するだけでなく、ソフトウェア開発のベストプラクティスにも合致します。
VB内の制限と可能性を理解することで、クリーンで効率的なコードを書き、DRY原則に効果的に従うことができます。