2003年10月02日
川俣晶の縁側ソフトウェア技術雑記total 7907 count

『「構造化」より優れた「オブジェクト指向」プログラミング』は本当に正しいか?

Written By: 川俣 晶連絡先

 オブジェクト指向を普及啓蒙させる書籍やインターネット上のサイトでしばしば見かける話があります。それは、「構造化プログラミングではこんな問題があるが、オブジェクト指向なら解決できる」というたぐいの話です。しかし、こういう話には、どうも納得行かないなぁ、という感想を持つことが多いのです。このような文脈で出てくる構造化プログラミングは、本来の構造化プログラミングではなく、「やられ役」として仕立てられた存在のように見えます。そして、オブジェクト指向は「正義のヒーロー」として仕立てられているように見えます。しかし、どちらも実態はちょっと違うのではないかと思うわけです。

 それはさておき、前からこの話題は書こうと思っていました。ですが、biac先生に説明をする必要が生じたので、今ここで書く状況になってしまいました。暇もないというのに……。

 とはいえ、知識も見識もある人でも、意外と理解されていない感もあるので、まあ書いてみる価値はあるかも知れません。とはいえ、これは感想文であって、何かの主張が正しいと読者を説得するための文章ではないことはお断りしておきます。私のようなプログラム言語ミーハーは、好きなものに関してキャーキャーと騒ぐことしかできません。

 さてここからが本題です。

 ちょっと前に、オータムマガジンに原稿を書くときにたまたま引っ張り出した言語C++第2版(B.ストラウストラップ トッパン出版)に面白いことが書いてあるのを、たまたまページをめくっていて見つけました。

 その部分の目次を引用します。

1.2 プログラミングパラダイム

1.2.1 手続き型プログラミング

1.2.2 モジュール化プログラミング

1.2.3 データ抽象

1.2.4 データ抽象の問題点

1.2.5 オブジェクト指向プログラミング

 ここでは、オブジェクト指向プログラミングを含めて複数のプログラミングパラダイムを比較しています。これによって、ストラウストラップさんは、オブジェクト指向プログラミングが他のパラダイムとどう異なっているかを示そうとしたのだと思います。しかし、これを見ると、すぐに気付くことがあると思います。じつは、「構造化プログラミング」という項目がありません。では、構造化プログラミング言語として知られるPascalやCとの比較をしていないかというと、そうではありません。それぞれの項目で上げられているプログラム言語を引用してみます。

1.2.1 手続き型プログラミング

 Fortran, Alogol60, Algol68, Pascal, C

1.2.2 モジュール化プログラミング

 Modula-2(この概念を直接サポートしている), C (それを使うことが可能なだけ)

1.2.3 データ抽象

 (特に記述無し)

1.2.4 データ抽象の問題点

 (特に記述無し)

1.2.5 オブジェクト指向プログラミング

 (特に記述無し)

 こうして見ると、PascalやCは、ストラウストラップさんによって無視はされていないものの、「構造化プログラミング」という分類にはなっていません。では、そもそも「構造化プログラミング」とは何かというと、うろ覚えの記憶を辿っていくと、たかだか3つの制御構造で全てのプログラムを記述できる、というような話だったような気がしますが、定かではありません。しかし、もしそう解釈するなら、この目次構成は素直に読み取ることができます。ここでストラウストラップさんが述べているのはプログラムとデータの構造についてであって、制御構造についてではないからです。

 そのように考えてみると、これだけで「構造化プログラミング」と「オブジェクト指向プログラミング」がそもそも比較可能な概念なんだろうか、という気持ちが湧いてきます。

 次に注目すべき点は、最も典型的な「構造化プログラミング」言語とも言えるPascalと、みんながよく知っているC言語の微妙なポジションの相違です。この分類で行くと、Pascalは「1.2.1 手続き型プログラミング」に含まれますが、「1.2.2 モジュール化プログラミング」に含まれません。C言語は、双方に含まれますが、「1.2.2 モジュール化プログラミング」を直接はサポートせず、使うことが可能であるだけとされています。

 では、「1.2.2 モジュール化プログラミング」とは何か。この本では、「互いに関連した手続きとそれらが操作するデータの集合は、よくモジュール(module)と呼ばれる」と記述されています。そして、このプログラミングパラダイムは、

 どのモジュールが必要か決定せよ。

 データがモジュール内に隠れるようにプログラミングせよ。

 としています。更にそれに続いて、「このパラダイムは、"データ隠蔽の原理"としても知られている」と書かれています。

 ここから、いくつかの興味深いことが読み取れます。

 まず、Pascalが「モジュール化プログラミング」に分類されていないことは、(本来のオリジナルの)Pascalはモジュールに分ける能力を持っていないことを意味します。典型的な「構造化プログラミング」言語がモジュール分割機能を持たないということは、モジュールに分ける機能を「構造化プログラミング」の特徴として数えることはできないことを示します。

 ではここでいうモジュール分割機能とはどういうものなのか。直接サポートしているのは、おそらく、ほとんどの人が知らないModula-2というプログラム言語であるとしています。しかし、Cでもできるとしています。では、具体的にCをどのように使うと、「モジュール化プログラミング」になるのでしょうか。一見、ソースファイルを分割すればモジュール分けが成立しているように見えますが、そうではありません。それではデータが隠蔽されないからです。通常のグローバル変数は、プログラムの全体からアクセス可能になるのがC言語というものです。もしかしたら、今時のC言語は、extern宣言をしてやらないと警告を食らうので、アクセス可能と意識していないかも知れませんが、それは不可能ではないはずです。それとも最新のCでは不可能なのかな。最近の動向は見てないので分かりません。ごめんなさい。別の言い方をすれば、たとえアクセスしなくても、同じ名前のグローバル変数を別のソースファイルで宣言するとリンク時に名前が重複したというエラーになるでしょう。これは隠蔽されていないことを示していると思います。

 しかし、この本では、「使うことが可能」と書いてあります。どうすれば使えるのでしょうか。おそらく、staticキーワードを活用するのでしょう。staticキーワードを付けた変数や関数のスコープはそのモジュール内に限定されます。外部からはアクセスできず隠蔽され、他のモジュールに同名の変数があっても共存します。

 このようなstaticキーワードを活用したモジュール化プログラミングは、1980年代の後半、学生時代に実際にやっていたものです。当時、生産性向上に寄与する、なかなか良い方法であるという感想を持ちました。しかし、それと同時に、データ隠蔽を意識してstaticキーワードを使えるCプログラマはあまり多くないという感想も持ちました。

 ここで話を戻します。

 こうして見てみると、データ隠蔽という概念は、オブジェクト指向の専有物ではないことが分かると思います。それは、モジュール化プログラミング言語で使用可能なものであって、オブジェクト指向でしか使えないものではありません。ということは、オブジェクト指向の人達の中に見かける「継承は絶対に許さない。カプセル化こそが最も重要」という立場を取るとすれば、オブジェクト指向プログラミングの絶対的な優位性は揺らぐことになります。単なるデータの隠蔽が使えるだけで良ければ、モジュール化プログラミングという選択肢もあり得るわけです。実際には、そんなに単純にモジュール化プログラミング置き換えられるものではありませんが、世間で流れている俗説ほど、オブジェクト指向の優位性は確固たるものではない感じがします。

 こういう前提で今一度、オブジェクト指向プログラミングの特徴を整理してみましょう。とりあえず、異論があることは承知の上でいくつかのオブジェクト指向プログラミングの特徴を書き出してみます。

・カプセル化

・継承

・ポリモルフィズム

・クラスの再利用

 まず、カプセル化は、既に見たように、モジュール化プログラミングのデータの隠蔽と対応する概念と考えられるので、オブジェクト指向固有の特徴とは思えません。しかし、カプセル化プログラミングとモジュール化プログラミングはイコールではありません。インスタンスの生成という手順に決定的な差があります。モジュール化プログラミングはインスタンスの作成という機能を持たないので、これはオブジェクト指向固有のものと位置づけられると思います。(もしかしたら、これも、他のパラダイムにもあることかもしれませんが、分からないので、こういう前提で話を進めます)。これも項目に追加しましょう。ここでは、○=オブジェクト指向以外にも見られる、●=オブジェクト指向固有、ということにします。

○カプセル化

●インスタンスの作成

・継承

・ポリモーフィズム

・クラスの再利用

 次は、継承とポリモーフィズムですが、これもオブジェクト指向固有であると考えておきましょう。本当は、「多態に対応するデータ指向プログラミング」というものもあるようなので、正しいかどうか分かりませんが。ストラウストラップさんはこの本で取り上げていないので、このまま話を進めましょう。

○カプセル化

●インスタンスの作成

●継承

●ポリモーフィズム

・クラスの再利用

 最後は再利用ですが、これは当然、モジュール化プログラミングでも想定される使い方です。モジュールごとの独立性が高まれば、モジュール単位で他のプログラムに転用することも容易でしょう。というわけで、オブジェクト指向固有ではないと見なすことにしましょう。

○カプセル化

●インスタンスの作成

●継承

●ポリモーフィズム

○クラスの再利用

 こうしてみると、オブジェクト指向固有の特徴は5個のうち3個ということになって、それでもオブジェクト指向プログラミングには優位性があると言うことが出来ます。

 しかし、世間で流れる俗説ほど圧倒的な優位ではありません。

 では、こういう俗説はどうして生まれたのか。おそらく、モジュール化プログラミングという概念が、きちんと世間に流布されないまま、曖昧にC言語を使ってお茶を濁していたためでしょう。本来のPascalと、Modula-2(どちらも、ニクラス・ヴィルト先生の創り出したプログラム言語)をみんなが使っていれば、こういう俗説は流れなかったかも知れません。

 というわけで、話はここで終わりですが、余談を2つ。

 余談その1

 うろ覚えですが、Modula-2では、外部に見せる変数や手続きと、外部から取り込んで使うものを指定する機能があったと思います。たとえば、モジュールA、モジュールB、モジュールCと3つのモジュールがあるプログラムがあるとき、モジュールAはモジュールBの機能を使うが、モジュールCの機能は使わない、ということが明示的に示すことができたような気がします。こういう機能があると、プログラムの他の部分への依存性の少ないモジュールの作成が容易になると共に、モジュール間の関係の複雑性を軽減できるかもしれません。その点で、JavaやC#は、同じ空間に存在するあらゆるpublicなクラスへのアクセスを可能にしてしまいます。たとえばC#のusingは、ある名前空間へのアクセスを許すわけではなく、ある名前空間への短縮表記を可能にするだけのことで、特定の何かへのアクセスを許したり禁止したりするような機能は持っていません。そのような点で、実は、今時のJavaやC#のようなプログラム言語は、Modula-2を完全に超えているとは言い難いかも知れない、などと根拠はないけど思ってみたり……。

 余談その2

 脱オブジェクト指向主義により、継承とポリモーフィズムを禁じ手とした場合、比較表は以下のようになります。

○カプセル化

●インスタンスの作成

○クラスの再利用

 こうしてみると、本当に訳に立つかどうかは分からないけれど構想してみた脱オブジェクト指向プログラミングは、インスタンスの作成機能を備えたモジュール化プログラミング言語によって実現できるのかもしれません。(かなり曖昧で怪しい言葉)

 すると、脱オブジェクト指向主義が指向するのは、モジュール化プログラミングの直接的進化形、スーパーモジュール化プログラミングである、と言えるかも知れません。

 というのは、その場の思いつきの妄言なので、真面目に噛み付いたりしないように (笑)。

Facebook

このコンテンツを書いた川俣 晶へメッセージを送る

[メッセージ送信フォームを利用する]

メッセージ送信フォームを利用することで、川俣 晶に対してメッセージを送ることができます。

この機能は、100%確実に川俣 晶へメッセージを伝達するものではなく、また、確実に川俣 晶よりの返事を得られるものではないことにご注意ください。

このコンテンツへトラックバックするためのURL

http://mag.autumn.org/tb.aspx/20031002144545
サイトの表紙【技術雑記】の表紙【技術雑記】のコンテンツ全リスト 【技術雑記】の入手全リスト 【技術雑記】のRSS1.0形式の情報このサイトの全キーワードリスト 印刷用ページ

管理者: 川俣 晶連絡先

Powered by MagSite2 Version 0.34 (Alpha-Test) Copyright (c) 2004-2018 Pie Dey.Co.,Ltd.