k41531

構造化プログラミング

本記事は、Clean Archtecuterという書籍の第4章構造化プログラミグを読んで自分なりにまとめたものです。プレゼンの台本のような形で記録が残っていたのでブログ記事として供養させていただきます。


構造化プログラミングは、gotoを手放すことで機能分割を手に入れる。

構造化プログラミングが生まれた時代は、今のコンピュータと比較して、巨大で壊れやすく、遅く、信頼性が低い、時代。

そして、ソフトウェア危機が叫ばれ始めた時代でもありました。1960年代後半。

ソフトウェア危機とは、ハードの高性能化によって出来ることが増え、したいことも増える。したい事が増えるのでソフトウェアの需要は上がるが、ソフトウェアを作成するコストが増大になり、需要を満たせなくなるというものです。

プログラムが複雑になるにつれて、正しいように見えるプログラムが失敗する。これは、今の現場でも感じることがあると思います。この正しいように見えるというのは、人間の感覚という曖昧なものに頼っているから引き起こされます。

では、どうすればそのプログラムが正しいと言えるのか、学者たちは考えます。

ここで出てくるのが、計算機科学者ダイクストラです。ダイクストラという名前はどこかで聞いた事がある人はいるのではないでしょうか?

証明をするのがが大好きな学問と言えば数学。ダイクストラは、ソフトウェアの開発に数学の証明を活用するということを思いつきます。 学問として大先輩にあたる数学を、コードに結びつけて証明を可能にする事ができれば、正しいという錯覚に悩まされなくて済むようになります。

正しさの証明で大事なことは「分割統治」です。数学で何かを証明するとき、大事なのは証明したい対象を分割する事です。学生の頃経験があると思いますが、証明の回答を記述するときは、上から順に正しい事を並べていき、最終的に証明したいことに繋げます。

この「分割統治」をプログラムに適用したい。しかし、goto文を使うことにより「分割統治」ができない場合があると明らかになります。逆に言えば、goto文を適切に使えば、「分割統治」ができるという事です。

このgoto文の適切な使い方が、選択「if/then/ else」や反復「do/while」といった制御構造に対応します。これらの制御構造のみを使えばプログラムを証明可能な単位まで分割できそうです。

また、当たり前すぎて忘れていましたが、もう一つ大事なものに「順次」がありました。「順次」は処理を順番に実行するというとても単純な構造ですね。

この「選択」「反復」「順次」は以前から特別なものだと知られていました。プログラムが分割統治で証明できそうな可能性が出てくる2年前、ベームとヤコピーニの二人の学者があらゆるプログラムは「順次」「選択」「反復」の3つで特定できるということを特定していたからです。(構造化定理)

プログラムは、「順次」「選択」「反復」の3つで特定できる 「順次」「選択」「反復」で書いたプログラムは、分割統治が使える。

この2つのの発見によって、「構造化プログラミング」が生まれます。

「GOTO文は有害だと考えられる」 と題された論文が出版されます。もちろんこの論文を書いたのはダイクストラです。

これによって、プログラミングの世界は炎上します。

今の時代であれば、SNSあるので幾らでもネガティブな投稿ができますが、当時はそんなものは使えません。ただ、ジャーナル(学術雑誌)に投書はできました。そして、非難する投書は実際に行われました。

当初は、その論文を強く支持するものと猛烈に非難するもので対立、議論は論争となり、以後10年間も続いたそうです。

現代の炎上は、炎上するような内容を投稿した人が謝罪する形で終結しますが、この炎上の結末は異なります。

火種であるダイクストラの勝利に終わったからです。

この結果、現代のほとんどの言語においてgoto文が息を潜めているのです。

オブジェクト指向プログラミングも関数型プログラミングも端的に述べれば構造化プログラミングの一種という事です。goto文が使えないのですから。

構造化プログラミングが、モジュール(部分的なプログラム)を証明可能な単位まで分割できるようにしてくれるということはわかっていただけましたか?

大きなプログラムを小さく小さく分割していき、最終的に出てくるものは、ダイクストラが述べた、「選択」「反復」「順次」です。

このような基盤の上に、構造化について分析が活発になります。 「goto文」論争が終結し始めた1970年代後半から1980年代にかけてです。

ここで、最初を振り返りますが、

正しいという錯覚に悩まされないために、数学によってプログラムの正しさを証明したい。

というのが最初のモチベーションでした。

ダイクストラの勝利に終わり、構造化に対する研究が活発になり、最後には証明される。と思いきや

プログラムの正しさが、正式に証明される(ユークリッドの階層が構築される)ことは遂にはありませんでした。

ダイクストラのプログラムを数学的に証明するという夢は途絶え、消え去ってしまったのです。

今日のプログラマーは、その頃に比べてはるかに複雑なプログラムを構築することができています。プログラムを数学的正しいと証明できないにも関わらずです。

なぜでしょうか、もちろん構造化プログラミングの後に続くオブジェクト指向やその他いろんな要因はあると思いますが、シンプルに考えてみましょう。

プログラムの正しさを数学的に証明する。 この世界にあるのは、数学だけではありません。私たちには科学(自然科学)があります。

ここで、もし数学は科学では?と思った人がいたら、「数学 科学ではない」でググってみください。私はググりました。

ということで、 科学でなら証明ができます。

科学で証明すると言いましたが、これには語弊があります。 実際には、科学の理論や法則は正しいと証明することができませんし、それが数学との決定的な違いでもあります。 ですが、私たちは科学が正しいと信じています。

例えば、運動方程式$ma=F$ この式が正しいと証明することはできません。 いくら実験をしても、正しそうな結果をいくら重ねても、どうしたって正しくないと証明される可能性が残っています。

ただ、私たちはたくさんの証明されていない式に命を預けています。

科学の世界における証明とは、真ではないということを証明することなのです。

数学と科学を比較してみましょう。 数学において、定理を証明する時は、小さな正しいを積み重ねていき、最終的に正しい定理にたどり着きます。 科学において、法則を証明する時は、小さな正しくないをぶつけて、それでもなお残った法則が正しいのです。

科学では真ではないということを証明すると聞いて、プログラミングの世界でも似たようなことを聞いたことがあると思った人がいるかもしれません。

テストです。

ダイクストラは、「テストはバグが存在しないことではなく、バグが存在することを示すものである」と述べています。

つまり、テストによって、プログラムが正しいということは証明できないが、正しくないということは証明できる。テストを十分に行って正しくないということが証明できないのであれば、そのプログラムは十分に正しいと言える。

正しい・正しくない・証明できる・証明できないなど少し混乱するとこではありますが、ご理解いただけたでしょうか。

プログラムの証明は、科学の証明と似ている。この事実は驚くべきものではないでしょうか? よく巷ではプログラミングって数学が必要なの?と言われています。 この問いへの回答は様々あると思いますが、世間一般的に、そしておそらくプログラマーの目線でもソフトウェア開発は数学に近いものだと考えられています。 しかし、このような事実からソフトウェア開発は数学より科学に近いものであると考える事ができるのです。

繰り返しにはなりますが、プログラムはどんだけ頑張っても正しくないことを証明できないことによって、その正しさを証明しているのです。

ただし、これは分割統治が可能なプログラムにおいてです。 一番最初に戻ってください、gotoを制限なしに使ったプログラムでは分割統治ができないという話をしましたね。

まとめです。 構造化プログラミングのアイデンティティとは、プログラムを正しくないと証明できる単位にまで分割する事ができるということです。 goto文は分割を不可能にしてしまうため、追放されたのです。

アーキテクチャという大きな枠組みにおいても、機能を分割するというのがベストプラクティスだと考えられている根源がここにあります。

ソフトウェアアーキテクトは、正しくないと証明できる部品の組み合わせによって成り立っているのです。