【テクニカル・上級編】【上級プロ】クラスモジュールとファクトリーパターンの導入:複雑なアセンブリ合致パターンを拡張性高くオブジェクト指向で構築するリファクタリング – SolidWorks VBA解析バイブル

スポンサーリンク

SolidWorks VBAの限界を突破する:アセンブリ構築におけるクラス設計とファクトリーパターンの実装

SolidWorksの自動化において、`swApp.ActivateDoc` を繰り返すだけの「場当たり的なスクリプト」は、もはやエンジニアリングとは呼べない。数千点の部品を扱う大規模アセンブリにおいて、モジュールレベルの変数が乱立し、エラーハンドリングが散逸したスパゲッティコードは、将来の保守コストを劇的に増大させる。

今日は、VBAというレガシーな枠組みの中で、いかにして「オブジェクト指向」の設計思想を注入し、拡張性の高いアセンブリ構築エンジンを設計するか、その極意を伝授する。

—

なぜ「手続き型」のVBAは破綻するのか

SolidWorks APIはCOMベースであり、オブジェクトの生成と破棄の管理が極めて重要だ。
`swApp` や `swModel` をグローバル変数に垂れ流し、`Set` 文を羅列するだけのコードでは、メモリリークや、不完全な合致(Mate)によるアセンブリの不安定化を回避できない。

我々が目指すべきは、部品(Component)を「データ」として扱うのではなく、振る舞いを持つ「オブジェクト」として定義することだ。

—

1. ファクトリーパターンによる「合致」の抽象化

複雑なアセンブリを構築する際、部品ごとに固有の合致ロジック(同心円、距離、角度など)をメインルーチンに書くのは愚策だ。`MateFactory` クラスを導入し、部品種別に応じた合致インターフェースを統一する。

実装例:IMateStrategy インターフェースの概念

VBAには厳密なインターフェース機能がないため、クラスモジュールをインターフェースとして定義し、ポリモーフィズムを擬似的に実現する。

‘ クラスモジュール: IMateStrategy (インターフェースの役割)
Public Sub ApplyMate(ByVal swAsm As SldWorks.AssemblyDoc, ByVal swComp As SldWorks.Component2)
‘ このメソッドは派生クラスで必ず実装する
Err.Raise 999, “IMateStrategy”, “メソッドが実装されていません。”
End Sub

具象クラス:ShaftMateStrategy

‘ クラスモジュール: ShaftMateStrategy
Implements IMateStrategy

Public Sub IMateStrategy_ApplyMate(swAsm As SldWorks.AssemblyDoc, swComp As SldWorks.Component2)
‘ ここに軸部品特有の同心円合致ロジックを記述
‘ swAsm.AddMate5 …
End Sub

—

2. メモリ最適化とオブジェクトのライフサイクル管理

VBAはガベージコレクションが脆弱だ。SolidWorks APIのオブジェクトは参照カウントで管理されているため、不要になった `Component` や `Feature` オブジェクトは、明示的に `Nothing` を代入してメモリを解放し、参照カウントを減らす必要がある。

特に、巨大アセンブリのループ処理では、以下の作法を徹底せよ。

‘ 推奨されるメモリ解放パターン
Dim swComp As SldWorks.Component2
For i = 0 To UBound(vComps)
Set swComp = vComps(i)

‘ 処理実行
Call ProcessComponent(swComp)

‘ 厳密なメモリ解放
Set swComp = Nothing
Next i

チーフアーキテクトの知見:
`DoEvents` をループ内に挟むことは必須だが、過度な呼び出しはパフォーマンスを劣化させる。`100回に1回` 程度の頻度で呼び出すのが、UIのフリーズを防ぐ最適解だ。

—

3. Windows APIによる「異常検知」の先制

SolidWorksの標準エラーハンドリングだけでは、バックグラウンドでのダイアログ表示による停止(モーダルダイアログによるハングアップ)を防げない。`User32.dll` を呼び出し、ウィンドウクラスを監視することで、自動化を中断させない堅牢なシステムを構築する。

‘ モジュール: WinAPI_Helper
Private Declare PtrSafe Function FindWindow Lib “user32” Alias “FindWindowA” _
(ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr

Public Sub ForceCloseDialog(ByVal dialogTitle As String)
Dim hWnd As LongPtr
hWnd = FindWindow(vbNullString, dialogTitle)
If hWnd <> 0 Then
‘ エラーダイアログを強制的に閉じる、またはスキップする処理
End If
End Sub

—

結論:コードは「資産」であれ

今回示した「クラスモジュールによる責務の分離」と「ファクトリーパターンによる拡張」は、一見するとコード量が増え、煩雑に感じるかもしれない。しかし、半年後に仕様変更が起きたとき、`Main` プロシージャを一行も書き換えず、新しい `MateStrategy` クラスを追加するだけで対応できるとしたらどうだろう?

優れたエンジニアは、動くものを作るのではない。仕様変更が起きたときに、最小限の修正で済む「構造」を作るのだ。

SolidWorks VBAというレガシーな環境であっても、設計思想をモダンに保つことで、それは強固な自動化資産へと昇華する。明日からの開発では、`Sub` の中身を空にしてでも、クラス設計から書き始めてほしい。それが、プロフェッショナルへの第一歩である。

タイトルとURLをコピーしました