ブログ「サイバー少年」

ブログ「サイバー少年」へようこそ!
小学六年生ごろからプログラミングを趣味にしている高校生のブログです。
勉強したことについての記事などを書いています。フリーソフトも制作、公開しています。
(当ブログについて詳しくは「ブログ概要紹介」を参照)

サイバー少年が作ったフリーソフトは「サイバー少年の作品展示場」へ

本「オブジェクト指向でなぜつくるのか」の感想、要約

C言語をやると言いながらまたオブジェクト指向の記事を書くという、やるやる詐欺以外の何物でもありません。

この夏休みは、日経BPの「コンピュータはなぜ動くのか(矢沢久雄氏著)」から始まるなぜシリーズの中の一冊、「オブジェクト指向でなぜつくるのか」を読みました。

この本の前半がすごく面白かったです。

オブジェクト指向言語の仕組みを解説する本というのは、だいたいが現実世界の例えを用いたりするわけですが、
オブジェクト指向の考え方を現実世界に当てはめるのは適切ではないと、この本は言っています。

また、そのような例えで「人間クラスが動物クラスを継承して~」とか説明しても、結局それがどうなのか、オブジェクト指向というのはどういうところで役に立つのか、その説明ではわからないだろうと、この筆者様の持論ではありますが主張しており、

この本では、オブジェクト指向というのがどのような経緯で生まれてどのような問題を解決したパラダイムなのかを、曖昧な例えをせず理論的に説明するという、ありそうでなかった本です。

その説明が前半部分で、後半は主にプログラミング技術以外のオブジェクト指向について説明しています。

どういうことかというと、オブジェクト指向というのはもともとプログラミングの技術でしたが、オブジェクト指向における考え方が優れていたため、設計や要求定義などの上流工程にも応用されていて、その説明をしています。

たとえばUMLを使ってプログラミング以外での物の関係を表現する例などをあげています。

ただ、本の主題は前半部分で落ちてしまった感じで、この後半部分はあまりインパクトなかったですね。

しかし、前半部分が良かったです。

私もバカの一つ覚えのようにオブジェクト指向を連呼していましたが、「結局オブジェクト指向ってなんなの?」という根本的な考えはよくわかっていませんでした。

まあ、今までいくつかのソフトウェアをC#で作った経験から、感覚的にオブジェクト指向設計っていうのはこういうことなんだなというのは多少わかりましたが、

あくまでも感覚なので、具体的な理解をしていないままだったのですが、この本は歴史的経緯をまじえて上手いこと説明しているので、この記事では要約していきます。




オブジェクト指向が誕生する以前(というか流行る以前)、構造化プログラミングというのが主流だったわけですが、もちろんこれよりもっと前には、GOTOだらけの非構造化言語が使用されていました。

非構造化言語の何が問題だったかというと、スパゲッティコードになりやすいので実行時の流れが追いづらかったり、
ローカル変数というものがなかったので、変数をどこが使用しているのかの管理が無駄に大変になってしまうなどの問題でした。

それを構造化言語では、基本三構造をサポートする構文を作ったり、関数の仕組みや、アクセスできる権限を狭めるためのローカル変数や変更されないように引数を渡す値渡しなどで解決しました。

しかし、構造化プログラミングでも解決できなかった問題が2つあるとこの本は言っています。

1つはグローバル変数、関数間でやりとりする変数を作る場合はどうしてもグローバル変数にするしかないわけですが、これは必要以上にアクセス対象を広げてしまいます。

(C言語などでは狭めることはできますが、オブジェクト指向言語ではそれ以上の問題解決をしました。グローバル変数が静的なのに対してインスタンス変数は動的です。)


もう1つはコードの再利用をする機構が関数しかなかったため、非常に貧弱であったということです。

あんまり詳しく本に書いていないので、私が未熟ながら補足しますが、単純に処理の固まりを部品にするだけでは足りないということではないでしょうか。

処理のほかにもデータを部品にしたり、複数の処理やデータがどういう関係で働いているのかを、ひとつの部品に定義することができなかったということです。

もっと他の言い方をすれば、関数は“ステート”を持つことができません。

ステート(データ)と処理(関数)の関係を定義することはできなかったのが、クラスを使うとできるようになったというわけです。

そのステートと処理の定義とそれらの関係の定義を受け持つのが、クラスなのかなと思いました。

クラスの仕組みによって、使用者がステートを操作するのではなく、クラスに記述された処理が自らのステートを操作する方法が普通になり、使用者はなにもしなくてもいいわけです。

クラスというのは非常に色んなものを定義できるうえに独立性の高い機能になりました。


これにより、コード再利用のイメージが、“使用者が部品を使ってなにかする”ではなく“使用者が部品に勝手になにかやってもらう”という感じになりました。

つまり、クラスというのは自身が意思を持っていて、勝手に色々やってくれると見ることが出来るようになって、つまりクラスの擬人化です。

そのような見方をできるようになったことが、前述のようにオブジェクト指向の考えを現実世界に当てはめようとしてしまう原因であると、筆者様は言っているような気がします。


さて、上記の問題を解決するために、生まれるべくして生まれたのがオブジェクト指向であると本には書いてあります。

つまり、オブジェクト指向とはいきなり無からぱっと登場したのではなく、それまでの時代背景があって、その上で改良を重ねて生まれた技術なのであると言っています。

私もC++とかのオブジェクト指向はそういう経緯かなと思いますが、Smalltalkは無からいきなり生まれたんじゃないかと思います。
どうなのでしょうか。

Smalltalk開発者のアラン・ケイ氏が、「Smalltalkは現実世界を参考にして作った」と言っていたような気がしないでもないのです。

私はSmalltalkについてよく知りませんので、無理に言及するのはやめておきますが。


さて、ではオブジェクト指向ではどのように構造化プログラミングで解決できなかった問題を解決したのか、それを本では解説しているので要約します。

オブジェクト指向の三大要素はクラス、継承、ポリモーフィズムだそうですが、それぞれの存在意義について本では書いていますね。

まずクラスです。
クラスにはこれまた三つの目的があると、書いてあります。

1つは、関連する関数と変数をひとつにパッケージ化できるということ。
もう1つは、外部に見せる必要のないメンバーを隠すことが出来るということです。

ただし、これらは前述のようにC言語などでもできました。

しかし、決定的に違うのは、最後の「たくさん作る」仕組み、ようするにクラスからインスタンスを作る仕組みです。

これでなにが変わるのかというと、主にコレクションを作るときに違いますね。

たとえば名前クラスというのを作って、名前を保持するフィールドと、漢字表記で返すメソッド、ひらがな表記で返すメソッドを定義したとします。

もし「たくさん作る」仕組みがなければたくさんの名前を管理することはできません。

もしたくさんの名前を管理したかったら、どうするでしょうか。

そもそも、たくさん保持しないといけないのはデータだけであって、処理の部分は1つでいいわけですから、では名前フィールドだけを配列にするでしょうか。

それでもいいですが、その場合において名前を返すメソッドを呼びたければ、データの対象のインデックスを指定しなければなりません。

また、名前フィールドのコレクションの管理をたとえば二分探索木にしようとなったときに、二分探索木としての処理は二分探索木に書かなければなりません。

つまり、本来「名前を管理する」という意味だけを持たせることが理想なのに、二分探索木を使うということまで定義してしまいます。

ではデータを名前クラスの外に出して、データだけを管理するクラスを作って、名前クラスのメソッドの引数にデータを渡すなどの処理をするでしょうか。
それでは構造化プログラミング時代に逆戻りです。


では、名前クラスをコピペしてたくさん定義すればいいのでしょうか。
それはメチャクチャです。

同じ処理のコードをたくさん書くことになりますし、名前の数を動的に管理することができないためそもそもコレクションとして終わっています。

しかし、その二つを解決してなおかつ、まるでクラスをコピペしているような機能を提供したらどうでしょうか。

それがインスタンスの仕組みだと、私は思いました。
すこし本の解説から外れていますが。

インスタンスによって、クラスをたくさん作れるようにするわけです。

インスタンスによって、まるでデータだけでなくそれに付属する処理も、データごとに存在しているかのような扱いができます。

実装的には、データがたくさんメモリに配置されるのに対し、処理はひとつだけですが。

処理はクラスごとにデータと一緒にまとめられて、密着しているので、「どこのデータを処理する」なんて指定は不要です。

インスタンスというものは、データだけでなく、処理までもをデータの一部にしてしまったということです。

これがオブジェクト指向の考え方じゃないと実現できなかった芸当です。


オブジェクト指向の三大要素のもう1つは、ポリモーフィズムです。

これについて上手く説明することはわたしには出来ませんが、本には呼び出す側を共通化する仕組みだと書いてあります。

これ以前にも共通サブルーチンというのがあって、ようするに関数でした。

これは、何か特定の計算などをする“呼び出されるロジック”を共通化するための仕組みでした。

しかし、逆にそれらのサブルーチンを“呼び出すロジック”も、共通化することが出来るであろうと、いうことです。

いわば「共通メインルーチン」を定義するための仕組みであると書いてありました。


たしかに、先ほどの名前クラスを挙げますが、漢字表記で名前をゲットしたり、ひらがな表記で名前をゲットしたり、ローマ字表記で名前をゲットしたりと、
そこの違いがあっても、その文字列を表示するとかの以前や以後の処理は変わらないことが多いです。

しかし、名前をゲットする関数を呼び出す部分を動的に差し替える機能がなかったので、それぞれ固定的に書くしかありませんでした。

しかし、名前クラスを継承した漢字名前クラスやひらがな名前クラスを定義し、そこにそれぞれの表記法で名前を返すメソッドを実装して、

それだけではメソッドのインターフェースが統一されている保証がありませんので、名前クラスの“名前を返す”メソッドのオーバーライドという形をとれば、その保証ができます。

こうすれば、呼び出し側にしてみても、表記法によらない抽象的な名前クラスだけを扱う処理をひとつ書けば、あとはどこからでもインスタンスを差し替えれば、違う処理を呼び出せるようになるわけです。

これが呼び出すロジックの統一です。


話は変わりますが、オブジェクト指向の三大要素はクラス、ポリモーフィズム、継承なのに、ポリモーフィズムで継承を使うというわけのわからない状態になっています。

これは、C++やJava、C#などの言語では、ポリモーフィズムと継承を実現するために両方とも言語機能としての継承(前者の継承とは別の意味)を使うことに問題があると私は思います。

実装の継承とインターフェースの継承という言葉があって、オブジェクト指向の三大要素としての継承を実現するのが実装の継承、ポリモーフィズムを実現するのがインターフェースの継承であると認識していますが、

そもそも言語機能としての継承は実装の継承のための用途に限定して、インターフェースの継承はJavaやC#にある言語機能としてのインターフェースに任せれば、

実装の継承、インターフェースの継承なんてわかりづらい二つの言葉は存在し得なかっただろうと思います。

まあ、言語機能としての継承やオーバーライドは、継承やポリモーフィズムを実現するための機能をうまいこと整理できる仕組みだったんでしょうね。


さて本題に戻して、その実装の継承、すなわち継承の意味について、本では、クラスの定義をそのまま拝借できる仕組みと書いてあります。

ようするに、安全なコピペです。

子クラスは、親クラスの内容をそのまま拝借して、拡張する部分だけを子クラスには記述します。

コピペしていると、親クラスで変更があったら全て書き直しですが、継承だと親クラスを参照することになるので、問題ありません。


また、クラスを継承すると、それは親クラスの内容を全て子クラスも保持しているわけですから、子クラスが親クラスとしても扱えることを保証することになりますが、
それは前述のインターフェースの継承のほうの仕組みなので、純粋なここで述べている継承とは別の領域だと思います。


以上の三大要素があるオブジェクト指向言語では、構造化プログラミング以上のコードの再利用、保守性の向上を実現できるようになったというわけです。

この本の前半が言いたいことは、こんなところでしょう。

また、コードの再利用のレベルが大きく上がったことにより、フレームワークという面白い仕組みのライブラリの発展形のようなものが出来たり、
クラスの関係をパターン化するデザインパターンというものが生まれたりしたと、書いてあります。


数ヶ月前に、GoFデザインパターンについてひとつずつ勉強していましたが、なかなか面白かったですよ。

そのことや、今回取り上げた本のおかげで、もうVB.NETでオブジェクト指向言語を覚えてから3年以上経ちますが、オブジェクト指向について考えなおすことができました。

それによって何か覚えたり成果が生まれた訳では、あまりないのですが、オブジェクト指向というものの正体に一歩近づくことは出来たので、良かったです。


というか、C言語やらないといけないんですが…。

tag: プログラミング オブジェクト指向 OOPL 構造化プログラミング クラス

コメント

コメントの投稿

トラックバック

トラックバック URL
http://cyberboy6.blog.fc2.com/tb.php/422-b95bfc22
この記事にトラックバックする(FC2ブログユーザー)

当ブログをご利用(閲覧等)になる場合は必ず「当ブログの利用規定」をお守りください。