構造化されていないということ

この節の要点

  • Goto文の様なジャンプ命令を極力、順接、選択、反復のプログラミング構造で置き換えることでプログラマが理解できるプログラムを作成する手法を構造化プログラミングと呼ぶ。
  • 構造化プログラミングを行うための方法として段階的作成法がある。

計算科学者であるエドガー・ダイクストラは、1960年代にGoto文がプログラムに与える悪影響を議論しました[6]。

当時のプログラミング言語、たとえばFortranやCOBOLで記述されたプログラムにはGoto文が多用されていました。

Goto文とは、ラベルを指定することで、指定したラベルが割り当てられているソースコード中の処理地点に移動する制御命令です。

Javaでは、Goto文が意図的に除外されており、現時点では利用することができません\(\dagger\)。

ですが、他の言語、例えば、CなどではGoto文が存在しており、図1で示すようなプログラムを作成することができます。

#include<stdio.h>

int main(void) {

	int n = 9, j = 0, i;
First:
	if (j < n) {

		i = 0;

	} else {

		return 0;
	}

Second:
	if (i <= j) {

		goto Third;
	} else {

		printf("\n");

		j = j + 1;
		goto First;
	}

Third:
	if (i > j/2) {

		printf("%d", j - i);
	} else {
		printf("%d" , i);
	}

	printf(" ");

	i = i + 1;

	goto Second;
}
図1:C言語におけるGoto文の例
0          
0 0         
0 1 0        
0 1 1 0       
0 1 2 1 0      
0 1 2 2 1 0     
0 1 2 3 2 1 0    
0 1 2 3 3 2 1 0   
0 1 2 3 4 3 2 1 0  
図2:図1のプログラムの実行結果

ここで、図1のプログラムを読んで、図2の結果が予想できた人は優秀です。もちろん図1の様な極端な例は稀ですが、Goto文の濫用は、図1のプログラムのような状況をたびたび招いてしまいます。図3にフローチャートを示してみましょう。

図1のプログラムのフローチャート

図3:図1のプログラムのフローチャート

このダイクストラのGoto文に関する議論の中では、プログラムの動作を正しく理解するという観点から、ソースコード内で先頭から順に現れる命令の順序と、プログラムを実行した時に時系列順で実行される命令の順序がなるべく対応付けられているべきであるとの主張がなされました。図3を見る限り、命令の順序が時系列順で並んでいないことがわかると思います。

ここで、図3の実行順序を整理すると、図4のように変形することができます。

図1のプログラムを整頓したフローチャート

図4:図1のプログラムを整頓したフローチャート

整理した図4を見る限り、命令の実行順序が直感的に分かるようになり明らかにソースコードの見通しが良くなったことがわかります。

この主張を発展させる形で、1972年に構造化プログラミング(Structured Programming)と題した小論文[7]を記したことに端を発する、 人間が理解できうる大きさでプログラムをうまく構造化する という効率的なプログラミングの形式手法は、今尚プログラマが知っておくべき重要な考え方です。

ダイクストラは、プログラムが計算を組織化したものとみなしました。本文中では、正しさを証明によって保証できる、数え上げ、数学的帰納法、そして抽象と呼ばれる3つの計算の構造を定義しました。そして、これらの中から対応付けることができる、 順接 、 選択 、そして 繰り返し と呼ばれるプログラムの構造(図5)を示しました。

フローチャートで示す順接(a)、選択(b)、繰り返し(c)のプログラム構造

図5:フローチャートで示す順接(a)、選択(b)、繰り返し(c)のプログラム構造

また、これら構造によって形作られる構造化されたプログラムの 段階的作成法(step-wise program composition) を提案しました。数学的証明によって紐付けられた構造を組み合わせてプログラムを形作るこの作成手法は、全体を通して数学的に証明できており正しく動作するプログラムを作ることになる、というわけですね。

[6]: E.W. Dijkstra, ``Go-to statement considered harmful'', Communications of the ACM, Vol.11, pp.147--148 (1968)

[7]: E.W. Dijkstra, C.A.R. Hoare, and O.J. Dahl, ``構造化プログラミング'', サイエンス社 (1975)


\(\dagger\): ただし、ラベル付きcontinue文やラベル付きbreak文などを使うことで似たような制御をすることができます。