プログラム悪戦苦闘日記

はてなダイアリーからの移行(遺物)

GUIはどーなってるの

 Excel VBAの話の続きです。Excelの操作性とかそういう話ではなく、GUIプログラムはどういう構成はどうなっているか、という話です。

 GUIプログラムにおいて、最初に気になる点は次の4つではないかと思っている。

  1. コンポーネントのディスパッチャー(イベント送出者)は誰か?
  2. イベントハンドラは、どのように定義/実装されるか?
  3. イベントディスパッチャーとイベントハンドラはどのように関係付けるか?
  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 VBAGUIプログラムに向かないということだ。経験者にしか分からない例えだが、C言語でX Windowシステムのプログラムを書くのに似ている、ということだ。ちなみに私はX Windowプログラムなんて書いたことないですよ^ ^;