読者です 読者をやめる 読者になる 読者になる

t-hom’s diary

主にVBAネタを扱っているブログです。

VBA スパゲティコード生む禁じ手 ~GoToプログラミング

VBA

今回は、ただのお遊びである。

役に立たないばかりか、下手に参考にすると有害である。
VBAにはGoTo命令がある。On Error GoToのことではなく、普通のGoToだ。

決して「活用しよう」などと思ってはいけないが、遊びでコードを作る分には頭の体操になって良いかもしれれない。

GoTo命令を使うと、任意のラベルにジャンプできる。
ラベルは文字列にコロンをつけたものだ。

これを使えばループ命令を使わずにプログラムが書ける。。。というより、コンピューター内部ではループ命令はジャンプに置き換えられているので、GoToを使った方法はよりマシン語に近い書き方ということになるかもしれない。

また、ラベルを使えば、条件分岐はIfブロックではなく単行のIfで事足りる。
※これもマシン語に近い書き方であるが、マシン語の方は比較結果を一度フラグレジスタに入れてからジャンプする。


さて、GoTo使ってFizzBuzzを書いてみた。

Sub GoToFizzBuzz()
    i = 0
L:
    i = i + 1
    If i > 100 Then GoTo L4
    If i Mod 15 = 0 Then GoTo L1
    If i Mod 3 = 0 Then GoTo L2
    If i Mod 5 = 0 Then GoTo L3
    Debug.Print i
    GoTo L
L2:
    Debug.Print "Fizz"
    GoTo L
L3:
    Debug.Print "Buzz"
    GoTo L
L1:
    Debug.Print "FizzBuzz"
    GoTo L
L4:
End Sub

これをフローチャートへ落とし込むと、以下のようになる。
フローチャートは久しく描いていないので厳密に合ってるかどうかは不明)
f:id:t-hom:20150914234202p:plain

これはまだラベルLに収束するから分かりやすい方だが、GoTo命令はどこへでも好きなラベルにジャンプできるので、その性質をフル活用してしまうと、フローもあさっての方向へ飛んでいってしまう。

ある程度大きなプログラムで広範囲にわたってGoToが使われた場合、もはや作った本人ですら読めなくなることが多い。
そしてソースコードは絡みに絡み、おいしいスパゲッティの出来上がりというわけだ。

これが、GoToを使うなといわれる所以である。

次にGoSubという命令を紹介する。
この命令はラベルに飛ぶところまではGoToと同じだが、Returnという命令で呼び出し元に戻ってくる。
いわば、原始的なプロシージャのようなものである。

今度はこれを使ってFizzBuzzを書いてみた。
一部ループと終了処理にGoToを使用しているが、分岐はGoSubのみで実装した。

Sub GoSubFizzBuzz()
    i = 0
MainLoop:
    GoSub Judge
    If i < 100 Then GoTo MainLoop
    GoTo Fin

Judge:
    i = i + 1
    flg = False
    If i Mod 15 = 0 Then GoSub FizzBuzz
    If Not flg And i Mod 3 = 0 Then GoSub Fizz
    If Not flg And i Mod 5 = 0 Then GoSub Buzz
    If Not flg Then Debug.Print i
    Return

Fizz:
    Debug.Print "Fizz"
    flg = True
    Return

Buzz:
    Debug.Print "Buzz"
    flg = True
    Return

FizzBuzz:
    Debug.Print "FizzBuzz"
    flg = True
    Return

Fin:
End Sub

※面倒なのでフローは割愛。

さて、コードは長くなったが、GoSubは必ず元の場所に戻ってくると分かっており、あさっての方向にジャンプする心配が無い。
(飛んだ先でさらにGoTo島流しなんてのは無いという前提)

プログラミングの黎明期には、GoSubの登場は画期的だったことだろう。
今ではプロシージャの分割やIfブロック、Loop命令、For命令などがあるのでこれらの命令を使うことは無い。

でもたまには、便利に使っている「あの機能」が無かったらどうなるんだろうと考えるのも楽しい。
皆さんも一度、チャレンジしてみてはどうだろうか。
きっと普段当たり前に使っている機能の、本当の価値が分かると思う。

ただし、大事なことなので二度書くが、決して「活用しよう」などと思ってはいけない。

※GoTo擁護派というのもあるらしく、そのあたりを学ばれた方がメリット・デメリットを踏まえて使うのはアリかもしれません。ただ、少なくともプログラミングの腕によほどの自信がなければ、実務コードでは使うべきではないと思います。

以上

当ブログは、amazon.co.jpを宣伝しリンクすることによってサイトが紹介料を獲得できる手段を提供することを目的に設定されたアフィリエイト宣伝プログラムである、 Amazonアソシエイト・プログラムの参加者です。