プログラミング / 記述の概要

  • 2017年12月13日:作成 12年間放置されていた予定項目です(^_^;)

ここ『時代おくれ』には自分が理解確認できたことしか書かない、無検証転載の禁止と言う大原則があり、結果としてこの項目は低レベルかつ尻切れとなってしまいました。何時になるのか解りませんが、天からモノリスが降ってきて私の腰が伸びるまで、この状態で御勘弁ください (^^ゞ。

関数型言語

無謀にも8Bit、Basicマシンの時代に、LISPチップ(拡張ROM)を購入したことがあります。が、初期横着仕様Basicに馴染んでしまった者がその対極にあるLISP拡張命令を使おうと思った時点で破綻しており、攻め来る(( )(( )))かっこ かぁ~っこに悩まされ夢にまで魘されましたが、得るものは何もなく、気が付けば高価な拡張ROMは行方不明・・・。

関数型言語は理解不能です、以上、おしまい。

手続き型言語

手続き型言語で記述する基本はエドガー・ダイクストラ(Edsger Wybe Dijkstra, 1930年5月11日-2002年8月6日)が提唱した構造化プログラミングです。要約すると、プログラムは(1)上から順番に実行される順次、(2)条件によって分岐する選択、(3)条件を満たす限りある範囲を繰り返して実行する反復、の3大制御構造のみで記述し、gotoを使ってはならない、となります。これに従うプログラムは、必然的に全体の流れを制御するメイン部分とそこから呼び出されるモジュール群で構成される事になります。

構造化プログラミングが可能な言語を構造化言語と呼称することがありますが、現在普及している手続き型言語はほぼすべて該当します。ですから、最近では構造化された美しいソースコードしか存在しません・・・などと言うことは絶対に有りません。

確かに構造化に都合の良い言語仕様はありますが、構造化そのものはプログラムを書くテクニックであり、プログラム記述の作法である、つまり構造化は言語の問題ではなく人間の問題だと自分は確信しています。言語の仕様に関わらず、悲惨なプログラムはいくらでもかけます(実証済み (^^ゞ)。

超言語MASUGU

構造化するメリットは何か?それを理解するには、構造化しない事のデメリットを知る事が近道です。

そこで、架空の超言語MASUGU登場です。MASUGUは行番号を持ちプログラムは番号順に実行されます。制御命令はif文とgoto命令のみ*です。変数にややこしい種類や制限はありません。強いて言えばすべて他言語で言うところのグローバル変数で、面倒な手続きなしに自由に使え、なんと気分次第で何でも格納できます。実在した某言語に似ているって?、それは気のせいでしょう (^_^;)。

2018.01.20:追記 *for文も必要だろうって?甘いです。5回なら5回、10回なら10回、同じ事を繰返し書けば良いのです。1000回はどうするって?goto無限ループとif/goto脱出で何とかなりました (その後遺症で今もループ命令が上手に使えない ^_^;)。

プログラミングは先頭から行番号順に、やりたい事を真っ直ぐに記述すればよいので書き易さ抜群です。部分ごとに独立したモジュールとして記述するなどと言う面倒なことはしません、連続した行番号の最初から最後までが塊です。そのため、思いついた処理を好きな場所に記述する、一連の処理を分散して記述すると言うことができます。

なら行番号はいらないって?違います。MASUGUには真っ直ぐ記述が行き詰まった場合に自由自在に脱出できるgoto命令があり、この脱出先を指示するために行番号は使われます。行番号は任意の箇所に好きなだけ挿入できますから、適当な脱出先が見当たらない場合は新しい脱出先を作る事も可能です。

エラー回避で、逃げ道の脱出先の逃亡先のとgotoを連続使用、エラーが出なくなったと大喜びしていたら“無限ループ”に潜伏しただけだった・・・プログラムは永久に終わらない。当時、なぜ構造から見直そうと思わなかったのか?それは、そういう時代だったんです、たぶん (^_^;)。

またMASUGUが採用しているコンパイル不要のインタプリタ方式では、行番号で実行順序を管理する特性を生かし、1行ごとに記述・実行・修正を繰返して、思い付きの集大成としてプログラムが完成します。

つまり、全体像をイメージできなくても思い付いた部分から記述可能で、途中で不都合が発生しても柔軟なプログラム構造が吸収してくれます。まさに理想の超言語、MASUGU万歳・・・って(^_^;)。

当然ですがMASUGUのソースは本人にも読めません。書き終わって時間がたてば過去の自分を呪うことになるのは必至、goto命令が多用されていると解り難さは2階級特進、過去の自分に殺意すら覚えます (~_~;)。これは全体が一塊であるがために、部分を意識することがなく漫然と書いてしまったためです。

当然、読めなければ再利用できませんが、MASUGUのソースは構造的にも再利用が困難です。部分を意識せずに書かれた塊であるため一連の処理がばらばらに配置され、複数の処理が入り混じり処理単位で切り出すことができません。無理に切出しても大幅な見直しが必要になり、書き直したほうが速い!と言う結論に達します。

Step 1:塊の破壊

このMASUGUの逆、読みやすく簡単に部分ごとに再利用できるプログラムが、構造化のメリット、構造化の目指す良いプログラムと言うことになります。実は根本的問題は言語ではなく人間の仕様にあります。MASUGUの仕様でも読みやすく再利用に配慮した記述をすることは可能ですが、塊であるがゆえに混沌の罠に落ちやすい、横着・堕落は簡単だ (^_^;) と言うことです。

まず構造化向きの言語では、全体を塊にしてしまい実行順序を束縛する行番号*を廃止して、モジュール単位の完全に独立した記述と自由な(=必要な)順番で実行することを可能にします。構造化プログラミングでは処理内容ごとにモジュール化し、その部分の集合として全体を構成します。Basic世代の方は行番号無しで、実行順番をどう決定するのか疑問を持つと思います。それは私も最初疑問でしたが、取敢えず後回しとしOSの構造と合わせて解説します。

*必ずしも行番号だけが原因ではなく、MASUGUでさえ複数のファイルに分けて記述しそれをリンクさせる事が可能でした。モジュール化を目指したら行番号が無くなった、が真相かもしれませんが、都合の悪いヤツであった事は確かです。

Step 2:ローカル変数の概念

塊を砕くことはできましたが、グローバル変数しか使えないため汎用性の高いモジュールを書くことができません。グローバル変数はプログラム全体から利用できますが全体で1つしか存在できませんから、あるモジュールを別のプログラムで再利用する場合は、全体の変数名を点検し同じ変数名が使われていたらどちらかを書き直す作業が必要になります。

そこで特定モジュール内でのみ有効なローカル変数の概念を導入します。複数のモジュール内に同名の変数が存在しても、それぞれ独立した変数であり互いに影響せず、自由に(場合によっては無修正で)モジュールを組合わせることができます。わかりやすい変数名をモジュール単位で自由に使用できるメリットもあります。

多くの言語で変数の使用宣言(手続き)が必要です。なんで「変数を使わせて下さい」とコンパイラ様にお願いせねばならんのだ、MASUGUでは必要なかったぞ!と思うかもしれません。それは仕様上、ローカルかグローバルかを明示する必要があるからですが、それ以外にも役立っています。

宣言なしで自由に使えると、変数名を書き間違えると新しい変数になってしまい、値が引継がれなくなります。それでは正常に動作するわけは無く、すべての変数名をチェックし直す必要が生じますが、それも運良く変数名が原因であると気が付いた場合、と言う条件付きです。

ほとんどの場合、変数の宣言に従ってコンパイラが変数名の間違いやバッティングを検出しますから、プログラマはその問題から開放されます。宣言文は「変数を使わせて下さい」ではなく「おい、コンパイラ、俺様はこの変数を使うからバッティングや書き間違いを見張れ!」なのだと思っていれば気分も変わるでしょう(変数ナントカは宣言されていません!とか指摘されてコンパイラにヤツ当たりしないように ^_^;)。

Step 3:関数呼び出し

モジュール単位でローカル変数を使用すると、必然的にモジュール間の変数の引継ぎ方が問題になります。共通で使われる変数はグローバル変数にするのも1つの方法ですが、構造化の思想では好ましくありません。引数付きでモジュールを呼び出す、つまり関数としてモジュールを呼び出す方法が推奨されています。

モジュールがローカル変数のみを使用する関数として定義されていれば、切った貼ったのWindows流 (^_^;) プログラミングも夢ではありません。欠点として引数が多くなると記述が面倒、モジュールが次々とモジュールを呼び出す(入れ子)場合、最初のモジュールにすべてのモジュールのための引数を与えねばならず、さらに面倒になります。

モジュール1は変数AとBが必要(それを処理するorそれで処理する)、モジュール2は変数CとDが必要、モジュール3は変数EとFが必要な場合に、モジュール1→2→3と入れ子呼び出しするならモジュール1にAとBだけでなく(使いもしない)C~Fも与える必要があります。

その不便を補うために、複数の変数を1変数として扱う構造体が準備されています。上記の例では変数A~Fを構造体として定義してまとめておけば、1つの構造体を変数として引継げば良いので大変に便利です。

具体的には、それぞれのモジュールにその構造をもったローカル変数を準備し、それを引数として次々にだいにゅうしていkもづぇヴぁぃあvぇ・ ・ ・ ・  ・  ・ System halted

力尽きました、ここいらが2005年8月現在の私の理解の限界のようです。オブジェクト指向の導入とか先は長いのですが、この続きは後日、私が理解してから改めて・・・トイウコトデ。

2017.12.13:追記 残念ながら、まだモノリスが降ってまいりません。グローバル変数を減らす努力はするが減らず、その一方で必要なグローバル変数を削って全体を複雑にしてしまい・・・と言う段階から先に進めません (^_^;)。続きはあと暫く(気長に)お待ち下さい m(_ _)m

プログラムの実行順序

行番号無しプログラムの実行順序について後回しにしましたが、これに関わってくるのがOSの構造です。現在の主流はGUI(Graphical User Interface)/マルチタスク/マルチウインドウのOSでWindows、Mac OS、Linux(X Window SYSTEM)のすべてがそうです。

MASUGUのようにプログラムが決められた順序でしか実行できない場合、人間は決められた順番で入力や選択を行なわねばなりません。これは人間の次の行動が予測困難なマルチタスク環境下では不都合であり、他のプログラムからの要求を受け取り協調して動作する障害にもなります。

そこで人間の行動や他のプログラムからの要求=イベントでプログラムの実行順序を制御する、イベント駆動方式(event driven)が現在の主流となっています。

  1. 起動したプログラムは、初期設定やウインドウの表示などイベントと無関係な部分を上から下に実行する。
  2. イベントが発生するまで何もしない待機状態に入る。
  3. 文字が入力された・マウスがクリックされたなどイベントが発生すると、イベントに対応するモジュールを(その内部では上から下に)実行する。
  4. 再び待機状態に入り、次のイベントを待つ。

あとは3と4の繰り返しでプログラムは処理を続けます。したがって、プログラム実行の順番は実際に実行されるまで存在しません

確かに、あらゆるイベントに対する検出ループを回し続け起こりうる全ての状況に対応する選択肢を記述をすれば、MASUGUでも同じ事が実現できます。しかし、この場合は予め記述された複雑な順番で実行しているのであって、イベント駆動とは根本的に異なります。

イベントの検出とプログラムの実行順序の決定をOSが一括して行っているため、順番が見えないだけだとも言えますが、少なくとも個別のプログラム内部に事前に決められた実行順序は存在しません

構造化プログラミングの秘訣は全体の処理をいかに的確なモジュールに切り分けるかにありますが、このマルチウインドウ+GUI+イベント駆動の組合せには構造化に非常に都合が良い特性があります。

極端なヒネクレ者 (^_^;) でなければ、自動的にウインドウを単位に分割して記述(コーディング)することになり、その内部では画面を構成する個々のオブジェクトやそのイベントに対してプログラムを記述することになりますから、普通に記述しても自然に構造化されてしまいます。

そのハズなんですが・・・私のプログラムが正しく構造化されないのはなぜか?ソースコードが美しくないのはなぜか?・・・謎は深まる一方です (^^ゞ。

2017.12.13:追記 現在も謎は解明されておりません。人間の仕様の問題、解決不可能!と認めてしまえば楽なのですが、ワタクシそこまで達観できておりませんので、まだまだ諦めずにシツコク頑張る予定です (^_^;)。


項目の目次に戻る サイトのトップに戻る