GUIはどーなってるの
Excel VBAの話の続きです。Excelの操作性とかそういう話ではなく、GUIプログラムはどういう構成はどうなっているか、という話です。
GUIプログラムにおいて、最初に気になる点は次の4つではないかと思っている。
- コンポーネントのディスパッチャー(イベント送出者)は誰か?
- イベントハンドラは、どのように定義/実装されるか?
- イベントディスパッチャーとイベントハンドラはどのように関係付けるか?
- スレッドモデルは何か?
1番はあまり意識する必要がないので、意味が分からないかもしれないが、早く言うとイベントの発行したオブジェクトは何か、ということである。たとえば、Java GUIプログラムの場合、ボタンを押したならButtonオブジェクト自身ということになる。通常は、ボタンを押したりテキストボックスに値を入れたりしたときは、そのコンポーネント自身がイベント発行者になる。
2番は、JavaでいうところのListenerである。Listenerインターフェイスをimplementしたクラスがイベントハンドラになる。(正確にはイベントハンドラの候補になる、といったほうが良いのかも)
3番目は、イベントハンドラをディスパッチャーに登録する方法である。Javaなら、addXxxListenerでイベントハンドラとディスパッチャーを関連付ける。
4番目は、イベント処理のスレッドモデルである。Java Swingならシングルスレッドである。最近のGUIライブラリなら、大抵はシングルスレッドだろう。
では、Excel VBAはどうなっているだろうか。
1→イベントを発行したコンポーネント自身
2→イベントを発行したコンポーネントが張り付いている、一番親のコンポーネント(通常はシートオブジェクトになる)
3→イベントを発行したオブジェクト(の親オブジェクト)がハンドラになっているから、最初から関連付いている
4→たぶんシングルスレッドだと思われ
なんとまぁ、MFCと同じでつか。特にイベントハンドラがディスパッチャーと同じだから、処理が一箇所にかたまってしまう(平たく言うと、処理がみーんなシートオブジェクトのモジュールに書かれてしまう)。だから、下手なExcel VBAプログラムは、処理がみーんなシートやブックのモジュールに固まっていることで見分けられたりする。…いちよう断っておきますが、これはExcel VBAをアプリケーションで開発する場合での話であって、ちょっとしたツールやドキュメントの整理のために作るExcel VBAは、この話の範囲ではないです。この手のツールは、早く作ることが重要であって、プログラムの見通しの良さは2の次になりますから。
話し戻して、とにかく処理が一箇所に固まってしまうので、何も考えないで作るとプログラムの見通しが悪くなる。ボタンを押してセルになんか色を付ける処理と、ボタンを押してグラフを描く処理が同じモジュールに書けば、そりゃみにくくなるでしょ。
で、この対策だが、やはり処理を委譲するしかない。MFCならCWnd::DefWindowProc()とかそんなメソッドをオーバーライドして、メッセージマップに逝く前に、処理をかっさらったりすることも出来るが、VBAはムリ。だから、とりあえずイベントハンドラはシートモジュールに書いておいて、すぐさま別の(標準)モジュールの関数に処理を渡してしまう(委譲)という書き方になるだろう。が、ここで問題が…
前回も書いたが、Excel VBAは構造化プログラムに近く、モジュール志向であるということだ。つまり、データの受け渡しが苦手/面倒臭いということだ。必要なデータはみんな関数の引数に渡してやる必要がある。だから関数の引数が異様に増える傾向になる。昔なつかしきC言語のようなプログラムだ。だからC言語と同じ過ちがVBAでも繰り返されることになる。つまりグローバル変数地獄だ。だから下手なVBAはグローバル変数が多くなる。
話が散漫になってしまったが、何が言いたいかというと、Excel VBAはGUIプログラムに向かないということだ。経験者にしか分からない例えだが、C言語でX Windowシステムのプログラムを書くのに似ている、ということだ。ちなみに私はX Windowプログラムなんて書いたことないですよ^ ^;