非構造化プログラミング

出典: フリー百科事典『ウィキペディア(Wikipedia)』
移動先: 案内検索

非構造化プログラミング(ひこうぞうかぷろぐらみんぐ)は全てのコードが一つの連続したブロックに含まれているプログラミングパラダイムの一種。プログラムのタスクが必要に応じていつでも呼び出せる小さな部分(関数やサブルーチン)に分けられている構造化プログラミングとは逆である。非構造化プログラミング言語はgoto文のような実行フロー文に依存し、多くの言語で指定されたコードの部分へ飛ぶのに使われている。

非構造化ソースコードは可読性が低くデバッグすることが難しい。そのため、何らかの構造をサポートするプログラミング言語では使われない手法である。しかし、条件文とgoto文の組合せによって任意のプログラム構造が実装可能であり、理論上はプログラミング言語にそれ以外の制御構造は必要ない。非構造化プログラミングはまだMS-DOSバッチファイルのようなスクリプト言語やBASICFORTRAN 66のような古いプログラミング言語で使われている。goto文(ジャンプ)は呼び出し手続きより僅かに性能が高いとはいうものの、現在のCPUアーキテクチャでは無視して良い程度になった。実際、不適切なそのような文の使用はコードを混乱させたりコンパイラ最適化を阻害してしまい、有害である場合がある。なお、一方で例えば proper tail call と呼ばれている末尾呼出しをジャンプ(goto)に変換する最適化は (1)明確かつ理論的な裏付けのあるプログラム変換になっている最適化であり、(2)「意味的に明確な、再帰で書かれたプログラム」を、スタックの無制限な伸長のような実行時の問題なく評価できるものである、など、重要なものでもあり、「僅かに性能が高いとはいうものの、現在のCPUアーキテクチャでは無視して良い程度」といったようなgotoに対する捉え方は、実は誤りである。

アセンブリ言語はほとんどが非構造化言語である。なぜなら基本的な機械語には構造が決して無いからである。それが持つ唯一の構造は、基本的な(スタックベースのマシンによくある)「サブルーチンジャンプ; Jump to Subroutine」命令や、関数の始めと終わりを示すなどのコンパイラなどが必要とする記述だけである。

現代の用途[編集]

現代のプログラミングの多くは構造化されている。しかし、構造化パラダイムでは制限が強すぎることがあり、一部のロジックは非構造化の方が簡単に表現できる(構造化プログラミングを参照)。

例として、いわゆる「途中リターン」がある。これは、手続き型言語における、関数の途中からのリターン、すなわち残りのコードを実行せずに当該関数から復帰させるというフローである。これは非構造化的だが有用であり、多くの構造化手続き型言語で可能であるが、資源の確保と解放など対になっていなければならない処理の片方を実行されなくしてしまうという危険があるなど、非構造化的さに由来する危険もある。この危険に対処できる finally という機能がある言語もあるが、無い言語ではコーディング規則などで「途中リターン」が制限される場合があることが例示されることがある。同様のことはループからの脱出などにも当てはまる。

一方で、純粋関数型言語では、あらゆる場所が「途中リターン」になっているようなものと言え、手続き型言語中でも純粋な関数であれば、むしろ途中リターンで書いたほうが単純でわかりやすくむしろ構造化されているとも言える。つまり表面的なコーディング規則で教条的に「途中リターン禁止」などとするのは、構造化というものを全くわかっていない証拠でもある。

また、例外処理継続も非構造化パラダイムの例である。より正確には、gotoや前述の「途中リターン」のような非構造化パラダイムを、なんとか構造的に扱えるようにしたものである。たとえば継続は Goto 文の機能を汎用化したものと言える。

構造化プログラムの構造を関数の木構造として捉えた場合:

  • リターンによって現在いるノードからひとつ上に脱出する
  • 例外によってキャッチされるまでノードを上に辿る
  • 継続によって以前訪れた別のノードに移動する

といった捉え方ができる。

関連項目[編集]