2005年02月09日
川俣晶の縁側ソフトウェア技術雑記total 7936 count

オブジェクト指向プログラミングの本質とは何か? 本当にソースコードは分かりやすくなるのか?

Written By: 川俣 晶連絡先

 最近、オブジェクト指向プログラミングの話題を書いていないので、最近思っていることについて軽く書いておく価値があるかと思って書いておきます。

 契機となったのは、あるところで、以下のような主張を見たためです。

 (自分の受け取り方による意訳的な要約です)

ソースコードを、オブジェクト指向プログラミングによって実現すると、一部分だけを見ても分かるようになる

 これを読んで、「それは嘘だろう」と思いました。

 なぜ嘘と思うのか、それを軽く書いておく価値はあるだろうと思ったのがこれを書いた理由です。

 まずは、いくつかの前置きの文章から。

自分の位置づけ §

 現在のところ、私は自分を「誤解されたオブジェクト指向プログラミングの擁護者」と位置づけています。

オブジェクト指向プログラミングの位置づけ §

 オブジェクト指向プログラミングは1つの有効なプログラミングパラダイムであって、その特徴を活かす場面に正しく適用すれば、それなりの成果を期待できると思います。

 しかしながら、オブジェクトの万能幻想という宗教性の強い思想によって、「特徴を活かす場面に正しく適用」するという試みが阻害されていることが多いと考えます。

 つまり、オブジェクト指向プログラミングは上手く機能していないことになります。

 これを解消するために、デザインパターンであるとか、アスペクト指向といった非オブジェクト技術を導入してオブジェクト万能幻想の崩壊を防ごうとしているというのが、1990年代後半以降の歴史的な流れであると認識します。

 しかし、パターンやアスペクトの導入はプログラミングに不必要かつ過剰な複雑さを導入することであり、このような「穴を見つけては新しい詰め物を探して詰め込む」ような対策は長続きしないと思われます。

 そこで、本来あるべきオブジェクト指向プログラミングの使い方は、オブジェクト指向プログラミングの特徴を把握し、それが有効に機能する場面に限って適用し、そうではない場面ではあえてオブジェクトによって実現しようとしないことである、という仮説を立ててみています。

 ちなみに、「あえてオブジェクトによって実現しようとしない」とは、そもそもオブジェクトという存在が一切含まれないプログラミング、あるいは存在しても補助的な役割しか果たさないプログラムを意味します。オブジェクトによって表現できないもの「だけ」をパターンやアスペクトに頼るものとは意図するところが全く異なります。

オブジェクト指向プログラミングの本質とは何か §

 オブジェクト指向プログラミングで最も重要な概念はカプセル化だと思いますが、データを隠蔽するという概念そのものはモジュール化プログラミングなどでも見られるもので、オブジェクト指向プログラミング固有とは言えません。

 細かい議論を全てはしょって、唐突ではありますが、継承こそがオブジェクト指向プログラミングの固有の本質であろう、という前提を立てます。

継承とは何か §

 ポリモーフィズムの有無によって、継承は全く異なる2つの機能性を持ちます。

 ポリモーフィズムの無い継承は、極めて不正確に要約すれば定義の階層化を実現するものです。クラスAとクラスBが共通に利用する定義はクラスCに記述し、それぞれクラスCを継承すれば、定義は1つしか書かずに、複数のクラスがその定義を含むことができます。継承の階層が深くなると、ある機能がどのクラスで実現されているか見通しが悪くなる場合がありますが、基本的にはさほど難しい話はありません。

 もう1つは、ポリモーフィズムのある継承です。これが今回の本題だと思います。つまり、オブジェクト指向プログラミングの本質は、ポリモーフィズムのある継承であるという考えに最近到達したということです。これは、オブジェクト指向プログラミングがブームになった初期の時期に言われていたオブジェクト指向プログラミングの本質論と極めて近い……かもしれません。(それを理解していたとは言えないので、断言は到底できませんが)

ポリモーフィズムのある継承とは何か §

 結論から先に書きます。

 ポリモーフィズムのある継承とは、抽象化であると考えています。

 たとえば、汎用出力クラスの出力メソッドを叩くと出力が行われる事例を考えます。その際、そのプログラムは、出力先が「具体的」にファイルなのか通信回線なのかメモリなのかを意識する必要はありません。つまり、「具体的」ではないプログラムになります。言い換えれば、抽象化が実現されます。

なぜ抽象化するのか §

 結論から先に書きます。

 抽象化を実現することにより、より少ないコード、より複雑度の低いコードによって、目的とする機能が実現できると考えます。

 隠蔽も複雑度を下げる効能があると考えていますが、抽象化も複雑度を下げることに効能があるのではないか、というのが最近の発見です。もちろん、そう思っただけで正しいかどうかは別問題です。

 言い換えれば、ソースコードの複雑度が上がりすぎて開発が破綻してしまうことを抑止するための手段として、抽象化は強力なツールになるということです。

抽象化のデメリットとは何か §

 それにも関わらず継承が忌諱される傾向にあるのは、これが強力すぎる劇薬であるためでしょう。継承の正しい本質を把握せず、宗教的な教義に盲目的に従うだけでは、継承を使うプログラマの方が継承の毒にやられて倒れかねません。

 抽象化のデメリットとしては、とりあえず以下の2つが考えられます。

 まず第1に、抽象的な表現は分かりにくさを生みます。あるコードが具体的にどんな仕事を担っているのか、ソースコードの断片を見ただけでは分からなくなります。ゆえに、以下の主張は、複雑度を下げるために正しく抽象化を行っているプログラムでは成立しない、と考えます。

ソースコードを、オブジェクト指向プログラミングによって実現すると、一部分だけを見ても分かるようになる

 第2に、抽象化には対応する物理的な実体が存在しないので、絶対に正しい唯一の方法はありません。仮にそれがあるとしても、それを反映することはプログラムで必要とされない複雑さをも導入することになり、複雑度を下げるという意図に反します。つまり、そのプログラムに適した個別の「抽象化モデル」を構築することが必要とされます。

 「抽象化モデル」は、UMLのクラス図のようなものとは異なることに注意が必要です。「抽象化モデル」は、対象とする物事をどのように抽象化するかをモデル化したもので、実際のクラスと直接対応するものではありません。

 プログラムに変更が発生した場合、「抽象化モデル」で表現できる範囲内であれば、驚くほど迅速に変更に対応することができます。(たとえば、量子通信装置が開発された時、従来通りのデジタル情報を扱うだけなら、汎用入出力クラスを継承して量子通信クラスを作るだけで実現できる)。

 しかし、既存の「抽象化モデル」では対応できない変更が生じた場合は、プログラムの根底から再構築するような再設計が要求されるか、あるいは、汚いコードhackで対応する必要が発生します。

ソースコードを修正せずに拡張できる、という誤り §

 オブジェクト指向プログラミングでは、ソースコードを修正せずに拡張できることが良いことであり、それが実現できるように設計すべきだという意見があります。

 その意見が誤りである理由は、上記に示されています。

 つまり、「抽象化モデル」の再構成が要求された場合には、いかに拡張に備えたソースコードであろうと修正せずに乗り切ることはできません。

 従って、ソースコードを修正せずに拡張できるように備えることはコストの割に効能が限定された手法であり、お勧めではありません。

「抽象化モデル」の再構成に適応する手法 §

 基本的に「抽象化モデル」の再構成は、事前に予測できない出来事だと考えられます。予測できるぐらいなら、それを踏まえた「抽象化モデル」を構築できるためです。

 従って、「抽象化モデル」の再構成に適応するために可能な手法は1つしかありません。つまり、いつでもソースコードのどの部分でも再構成ができるように備えることです。そのためには、重複のないシンプルなコードを記述する必要があります。

 ここでは、書き換えが容易になるように配慮してソースコードを書く、という手法もあり得ないことに注意が必要です。どのように将来再構成されるか分からないソースコードである以上、未来に行われるであろうソースコードの書き換えをあらかじめ予測し、それを配慮する方法はありません。

抽象化賛歌 §

 抽象化とは、有限のリソースを用いて、より多くの問題を解決する手段の1つ、と考えて良いと思います。

 従って、より多くを望むなら、抽象化の推進は避けて通れません。

 特に実用ソフトにおいては、利用者の評価基準が上がっているために、抽象化を適切に行わずして、開発者の持つ有限の時間や計算機能力で必要な機能を持ったプログラムの開発は困難と言って良いのではないかと思います。

余談 §

 抽象化とは、文脈病―ラカン・ベイトソン・マトゥラーナ 斎藤環 青土社 (感想その5「インターネット上の論客が致命的に物足りない理由」)で紹介した学習段階のステップアップと無関係ではないような気がします。つまり、コンテキスト性の問題とも関連します。

 言い換えれば、インターネット上に見られる知性の後退と、従来と比較して継承軽視を伴うオブジェクト指向プログラミングの流行的傾向は、同じような構造的要因によるものかもしれない、という問いかけがあり得えるかもしれません。

余談: なぜ私の書くソースは難しいと言われるのか §

 これらの話から、なぜ私が自信を持って単純明快に書いたはずのソースコードが難しいと言われることが多いのか、その理由が見えてきます。

 つまり、こういうことです。

 ソースコードに適切な抽象性を持ち込むことで、ソースコードの複雑度は低減され、短くすっきりしたコードが得られます。

 しかし、抽象性を持ち込むことは、ソースコードから具体的な分かりやすさを奪う行為と背中合わせです。つまり、難しくなるのです。

 これは、オブジェクト指向プログラミングではない場合にもあり得る話だろうと思います。プログラムに抽象的な構造を与える方法は、継承だけではありません。

継承と上手く付き合うには §

 継承と上手く付き合うには、以下のことに注意を払うと良いのではないかと思います。思い付いたことだけ、暫定的にリストアップしておきます。

  • YAGNIの原則を貫き、拡張性に配慮するための継承は行わない
  • 抽象化モデルを意識し、できればそれを表現する (具体的な方法は?)
  • 複雑度の低減という効能を意識する。複雑度が減らないならあえて抽象化する意義は無く、むしりデメリットだけが残る

Facebook

キーワード【 川俣晶の縁側ソフトウェア技術雑記
【技術雑記】の次のコンテンツ
2005年
02月
25日
テスト駆動開発とgenerics
3days 0 count
total 1980 count
【技術雑記】の前のコンテンツ
2005年
02月
08日
正しい読み方は何か、"^"記号の名称についての極めて不完全な調査
3days 0 count
total 16087 count

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

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

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

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

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

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

管理者: 川俣 晶連絡先

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