意外と知られていない構造化プログラミング、あるいは構造化プログラミングはデータも手続きと一緒に抽象化する、あるいはストロヴストルップのオブジェクト指向プログラミング史観

書いた人: ると
書いた日: 2014年1月18日 (2014年1月23日 よみやすさのために細部を修正)

猫型プログラミング言語史観(1) 〜あるいはオブジェクト指向における設計指針のひとつ〜という記事がありました。手続き型からの発展としてのオブジェクト指向という史観を書いた記事です。しかし、そこで次のように述べられている史観は少々単純化しすぎです。

手続き型プログラミングでは手続きを抽象化することで保守性を挙げることに成功したが、データを守ることには失敗してしまった。そこでオブジェクト指向はデータと手続きをひとかたまりにすることでデータを外から守るというコンセプトを打ち出した。

手続き型プログラミングの時代は、少なくとも思想的にはそこまで暗黒的ではありませんでしたし、「データと手続きをひとかたまりにする」のもオブジェクト指向以前からある考えです。そこで、実際に歴史を交えつつ構造化プログラミングの考えや、ストロヴストルップ(C++の作者)によるオブジェクト指向プログラミングの定義を見てみましょう。

構造化プログラミング以前、あるいはかの偉大な計算機科学者にして文芸的プログラミングの提唱者であるクヌースが学部時代に書いたタコ足フローチャート

ダイクストラが構造化プログラミングを提唱する前、1960年代ごろはプログラムといえばフローチャートで設計するものでした。かの偉大な計算機科学者にして文芸的プログラミングの提唱者であるクヌースですら学部時代には次のようなタコ足フローチャートを書いていました

数十ノードからなる複雑なフローチャート

ここには何も「構造」がありません。単純な処理をするノードが雑然と散らばり、線がノードを縦横無尽に繋いで1つの塊になっています。これではプログラムを実行したときにどのように処理が進み、どのデータが変化するのかわかりません。

構造化プログラミング、あるいはデータと手続きの階層的抽象化、あるいはgotoを無くせばいいというわけではなく、あるいは順次・反復・分岐のみで書けばいいというわけではなく、あるいは構造化定理はあまり関係なく

そんな中、プログラムをブロックに分けて書いた方がバグが少ないというのが経験的に少しずつわかってきました。そして1968年、ダイクストラはCommunications of the ACM誌に“Go To Statement Considered Harmful” (「goto有害論」)という記事を寄稿します。また、ダイクストラは翌1969年に開催された学会“Software Engineering Techniques”において“Structured Programming” (「構造化プログラミング」)という論文を発表します。「構造化プログラミング」での主張はおおまかには次のとおりです。

つまり、既に構造化プログラミングの最初の論文においてデータの抽象化が主張されていました。データの抽象化の重要性はその後も書籍版『構造化プログラミング』(1972年)や、“Structured Programming with go to Statements” (「goto文を使った構造化プログラミング」)(1974年, クヌース)でも繰り返し強調されています。

余談ですが、ダイクストラによる記事「構造化プログラミング」ではgotoにはほとんど触れていません。また、現在では構造化プログラミングの条件として順次・分岐・反復が挙げられる場合がありますが、「goto有害論」では順次・分岐・反復(+手続き呼び出し)には固執しておらず、プログラムの進行状態を簡潔に表せればよいとしています。そして機械的にgotoを除いても見透しが良くなるわけではないので機械的にgotoを除くのは推奨しないとしています。

さらに余談ですが、よく「任意のプログラムは順次・分岐・反復の組み合わせで書ける」とか場合によっては「プログラムの本質は順次・分岐・反復である」とか言われる、いわゆる「構造化定理」ですが、実際にはフローチャートに関する定理で、「入口と出口が1つずつであるような制御フローチャートは、スタックを追加すると3種の基本構造(順次・反復・分岐)とスタックの組み合わせによる等価なフローチャートに変換できる」というものです。これは論理回路はNAND素子だけで表せるとか、λ式はSとKという2つの関数(コンビネータ)だけで表せるといったものに近く、きれいなプログラムを書くためのものではありません。また、制御フローチャートに関する論文なのでプログラムの重要な要素であるデータ構造とか、制御以外の処理とかは範囲外ですので、「プログラムの本質は順次・分岐・反復である」とかいう話ではありません。なお、論文ではスタックと2種の基本構造(順次・反復)の組み合わせに変換する定理も示していますが「構造化定理」と言った場合は3種版を指すのが普通のようです。また、この論文が出たころはまだ「構造化プログラミング」という言葉も無かったので「構造化定理」という言葉も論文中では出てきません。

オブジェクト指向プログラミング、あるいはデータ抽象+共通点の明確化、あるいはストロヴストルップのオブジェクト指向プログラミング史観

では、オブジェクト指向プログラミングとはなんなのでしょうか。この質問を10人に聞くときっと30種類ぐらい答が返ってくると思います。そんな中、C++の作者であるストロヴストルップは1987年の“What is "Object-Oriented Programming?"”という論文でオブジェクト指向プログラミングを次のように「データ隠蔽」および「データ抽象」の延長上に位置付けています。

データ隠蔽データ型の詳細を特定のモジュールの中に隠す
データ抽象「データ隠蔽」 + データ型を組込みデータ型と同じように扱えるようにする
オブジェクト指向プログラミング「データ抽象」 + データ型間の共通性を継承により明確にする

詳細は以前私が書いた記事「2011年に読んだ論文紹介 または私は如何にして心配するのを止めて静的に型付けされたオブジェクト指向言語を愛するようになったか」をどうぞ。

つまり、「データを外から守る」というのはオブジェクト指向プログラミング以前からある話である、と位置付けられています。

ちなみに、オブジェクト指向プログラミングの原始的なアイデアは実は先程の書籍版『構造化プログラミング』でも既に紹介されています。ここからもオブジェクト指向プログラミングは構造化プログラミングからの延長上にあるということがわかります。

なお、ここで紹介したのはあくまでストロヴストルップ流のオブジェクト指向プログラミング観であり、他の例えばアラン・ケイなどはまた異なったオブジェクト指向プログラミング観を持っています。様々なオブジェクト指向プログラミング観についてはsumimさんの記事「オブジェクト指向の概念の発明者は誰ですか?」が参考になります。

まとめ、あるいは元の記事との繋がり、あるいは構造化プログラミングやオブジェクト指向プログラミングは現在では当たり前の前提となっていてみんなその先を議論している、あるいは構造化プログラミングやオブジェクト指向プログラミングは現在では当たり前の前提なので細かい歴史的な部分はみんな気にしていない

このように、手続き型プログラミングの時代には既に構造化プログラミングという形で手続きとデータ両方の抽象化が主張されていました。そしてオブジェクト指向プログラミングはその延長と位置づけることもできますが、それは「データと手続きをひとかたまりにすることでデータを外から守るというコンセプトを打ち出した」という訳ではありません。データを他から守るというのはそれ以前からあり、オブジェクト指向プログラミングの要点はデータ型間の共通性を継承により明確にする方にありました。

一方、ここで挙げた構造化プログラミングの文献では、手続きやデータをまとめて抽象化しようとは言いますが、具体的な抽象化方法についてはあまり詳しく述べられていません。また、ここで挙げたオブジェクト指向プログラミングの論文でも共通性を明確化するとは言いますがより詳しい指針などはあまり挙げられていません。そういった、具体的な詳しい方針について考える段階に来るとようやく元のnkgt_chkonkさんの記事に繋がっていくのではないかと思います。

参考文献、あるいは自宅にいながらにして歴史的一次資料を読めるワールドワイドウェブのすごさ、あるいは歴史的一次資料を保存して電子化して公開する人たちのありがたさ

Tips: 一部資料はACM会員専用ですが、ACM会員じゃなくてもタイトルで検索すれば他のところで公開している場合があります。