Windows 用のアプリケーションで他人のソースを改修する時に恐いのは、 いわゆるイベント(†1)である。 イベント自身は Windows の都合で勝手に出てくるものであって、 それを制御しようとすると思わぬことになることが常である。
VC++ でも、Delphi でも X-Window でも、考えはほぼ同じだと思うので、 VB で例を示す。
このような画面があるとするとき、
+-------------------------------------------------+ | | | 受付番号 [ ] 台帳番号 [ ] | | | +-------------------------------------------------+受付番号を入力する欄が txtUkeNum, 台帳番号を入力させる欄が txtDaiNum とする。
一方が決まれば他方は決まるので、そこは自動にしたい。 では、一方のテキストを変化させたときに他方を変化させればよいわけである。 ここでは、受付番号の始めに 'D-' を付けたものが台帳番号とする。
VB でテキストボックスの変化を知るには Change イベントを引っ掛ければよい。 と、思って書いてみる。
' 受付番号が入力されたら台帳番号を変える
Private Sub txtUkeNum_Change()
txtDaiNum.Text = "D-" + txtUkeNum.Text
End Sub
' 台帳番号が入力されたら受付番号を変える
Private Sub txtDaiNum_Change()
If Left(txtDaiNum.Text, 2) = "D-" Then ' (左の二文字を抽出)
' D- が書いてあったら受付番号を変更
txtUkeNum.Text = Mid(txtUkeNum.Text, 3) ' (三文字目から最後を抽出)
Else
' 書いてなければ無効として受付番号を消す
txtUkeNum.Text = ""
End If
End Sub
これでは、まず、期待通りに動かない。 さらに、一文字書き出したところでこのプログラムは反応しなくなる。
どうなるか、というと、受付番号を [1] と入力すると、
txtUkeNum_Change が発動し、txtDaiNum を 'D-1' に変更する。
すると、txtDaiNum_Change が発動し、txtUkeNum を '1' に変更する。
VB の場合はこの時点で無限ループに陥る。txtUkeNum_Change が発動する。
ごく簡単な例であるし、イベントの起こる条件をかなりあいまいに取っているが、 イベントの連鎖の例として理解していただけると思う。
さて、簡単な例ながら、イベント連鎖の本質がここにある。
イベントを処理している間に他のイベントを起こすのは、
予測がつかない結果を引き起こす場合が多い、ということである。
一般的な人間が物事のつながりを認識できる範囲は限られている。 そのために因果関係を判断する裁判所があり、または、 つながりを読むのを職業とする将棋や囲碁のプロがいたりするわけである。
私たちはそういうことが得意だろうか? 仮に得意であったとしても間違わない自信があるだろうか。 先にあげた職の方には申し訳ないが、 最終的に判断を間違っていてもそのこと自体は非を問われないと思う。 しかし、私たちがやっているのはコンピュータを確実に動作させることである。
それならば、読めないことはしないことである。 イベントのつながりが読めないなら、 知らないうちにイベントを起こすような操作をするべきではないのである。
かといって、いつ起こるか判らないではないか、といわれれば、そのとおりであって、 こればかりはそれぞれの開発言語なり、OS の癖を知るしかない。 そのためには実践の前にイベントを引っ掛ける実験を欠かさないで欲しい。
イベントを引っ掛けるというのは、 本来アプリケーションがしようとしていたことの横槍を入れることである。 横槍を入れたことの影響をきちんと把握することと、 その影響を最小限に押さえることが確実な動作に繋がると考える。
よく、グローバル変数を使うと全体に影響するから云々、という話があるが、 イベントに関して言うと少なくとも私の周りでは取り上げられないことである。 グローバル変数は少なくともソース上に全てのつながりが書いてあるので、 よくソースを読めばいいことだが(そうもいっていられないが)、 イベントに関してはソース上では判らない動きである。 自分の開発範囲ですんでいるならまだしも、 多人数で開発するならよけいな横槍を入れるには細心の注意が必要である。
実は、今回の結論は前回の結論(楽をしようぜ)と、
矛盾とまでは言わないが相反する。
たとえば VB で開発する人にとって、デザイン画面のプロパティ(†2)を、
全て確認するのは不可能に近い。
今回はソースというのを文字に限定した上で話を展開したが、
OS 、または開発言語によるイベント処理はこのプロパティ設定に近いといえる。
コンボボックスに Sort が設定されているなら、
ソースコード上になくてもコンボボックスは勝手にソートをする。
これは、まさにイベントが発動しているわけである。かといって、
ソース上に改めてソートルーチンを起こすほど開発現場は暇ではない。
ソース上にいいタイミングでコメントを置いておくしかないので、
なかなかバランスが難しい。
†によって示した注釈。