kr_ryo 徒然日誌 <2004年12月12日分>

三國志製作記84〜オブジェクト指向みたび〜

いやあ、もう12月も12日、後残すところ今年も19日、なんだかそんな感じがしないほどのあったかい日が続きます(^-^)北海道ではどかんと雪が降っているようですが、こちらでは私はコートもまだ着てません。小春日和というか、冬がこないというか…(T-T)

さて、前回2本目の「コマンド処理の流れ」を書いたところでふと思ったのが、このまま進めばあまりに処理ルーチンが巨大になり、複雑怪奇に枝分かれする!という先々への恐怖感でした( ̄□ ̄;)1つのコマンドに1つのボタン、似たような処理はまとめるとはいえ、まとめた部分ははや何がなんだかわからないだけの量になりつつあります。

ところで、実は最近ちょっとした(?)手術をしまして、大きな病院に行ったんです。そこでは当然内科や外科などの各科がありつつ、受付や会計や検査などはひとつだけしかありません。そこで起こるのが皆様ご存知、会計待ち検査待ちの人ごみの山(*_*)病院にとっては当然会計などは集中した方がよいわけです。その分各科は診療だけで済みますからね。しかし会計はまだしも検査は患者の取り間違いは本当に起こらないのかな、と思うほどの状態です。別段番号札があるわけでもなく名前の呼び出しだけ、だいたい病院に来るのは病人けが人ばかりなのに、あまりに人が多くてあせらせることしきり。年寄りは当然多いながら、ああ、病院には行きたくないな、と思わせますわ〜(‥;)

まずもって、病院というのはどこでもそうでしょうが、あまりに人が多くていかにさばくかという感じになっています。元祖がやっぱりナイチンゲールや赤十字などの野戦病院からスタートしてるせいでしょうか?看護師さんはあわてる必要がなくともいつもあわててるように見えます。やっぱり野戦病院ですな(~_~;)

と、話がそれましたが(^^;会計や検査など共通の処理とされる部分は、いろんなところから処理が集中するため、正しく処理を分岐させたり、適切な処理をしたりするだけでも大変です。具体的にいうと、あるひとつの処理の流れをつくったとします。A→B→Cと処理の固まりを作ったとして、Bが他とも共通な内容であれば、それだけ別にします。別の処理の流れX→Y→Zのうち、YとBはほとんど共通であれば、この処理はYを作らずX→B→Zとするとメモリを節約できます。

もちろんX→Y→Zとしてもいいわけですが、そうすると、さらに別の流れJ→K→Lで、KとBが共通なのに、これもJ→K→Lと、重複が目立ちます。コマンドごとにこれをやっていくと非常に無駄です。病院で各科それぞれに会計と検査の職員と場所を準備して、同じことをさせれば無駄だと思うでしょ?(^^;

というわけで処理BはABC、XBZ、JBLと、これで3つの処理を受け持つことになります。まったく同じであればいいんですが、これまただいたい微妙に違うところがあるのです。だいたい受け入れは共通でも送り出しはCZLと別々です。これを受け入れに応じてAならC、XならZという風に正しく分けなければいけません。3つならまだ頭の中で処理できます。しかし人間は7つ以上の別々の事柄は頭の中では一度に記憶できず、100を超えたら、無事に超えれるかどうかは保障の限りではありません(*_*)

2つ目の処理の流れで早くもやばいっ!と思ったのが先週でした(^^;;そこで色々図表を使おうかとか、紙に書いたりしようかと思いましたが、それは巨大で大量な処理の流れを全部把握して、間違いなく送り出しできるかどうか自信が持てなくなったせいです(;_;)病院同様、処理ごとに番号札を持たせて流そうとしたんですけども、番号の重複や誤配で見るも無残なエラーの山を築きそうな気はします(TдT)

こういう、処理や機能に着目して、順番に流す方法が前回お話しました手続指向型といいまして、これまた前回なんとか理解しようとしたオブジェクト指向型と対置されます。ネットでオブジェクト指向と手続指向とを合わせて検索すると、私のこの徒然日誌の過去の分が出たりして面白いですが(^^;;前回以来なんとかオブジェクト指向に進もうとしたものの、やっぱり今までは明らかに手続指向型思考でしたねえ〜(*_*)で、まさに手続指向型プログラムの限界がどうやらこのことらしいのです。巨大になるとわけがわからなくなる(*_*)

先週来、なんとかオブジェクト指向とやらを理解しようと、本屋やら図書館やらネットやらを調べまくったところです。これならわかる!と思ったものもあれば、これならわかる!とわかった内容では理解できないようなものもあり(T-T)百花繚乱、なるほど、みんながわからないというのがよくわかる、という状況です(^^;;Aどれかで書いていましたが、わかる!とかかんたん!とか書かれる位だから、簡単にはわからないものだ、と(^^;A確かにその通り。なんにせよここまででわかったことは、オブジェクト指向とはまさに思考方法、概念(パラダイム)であって、オブジェクト指向を理解することはプログラム製作にパラダイムシフトを起こすことだ、と。

特に手続指向型プログラム言語を使った経験があると、オブジェクト指向を理解しがたくなる、といわれます。私もポケコンからスタートして、HSPも含めVisualでないBASIC系列の期間が長かったものですから、これら手続指向型の影響は十分受けています。かつてCのプログラムなんかを見て、なぜ行番号がないのだ!とか思ったくちです(^^;;どこにジャンプすればいいのだ!と。

そういう意味ではプログラムに対する自分史って実は長いじゃあないですか(^-^)って今更気づきました(^^;;Delphiを含むWindowsプログラム歴が短いということですね(^^;;いまだに手続きや順番を意味するプログラムっていう言葉を使ってますし(^^ゞと、まあ、ほんとはソースコードという言葉を使えますが、プログラムの方がなぜか一般にはなじみがあるようですので、使っていたりします。

とはいえ、Javaなどオブジェクト指向言語が主流となる昨今、これは私自身もパラダイムシフトを起こさないとついていけなくなる可能性があります(x_x)というより、現状の三國志製作すらやばくなる、と(*_*)

オブジェクト指向に向けての前フリはこの辺にして(^^;;では、オブジェクト指向ならほんとにこういう問題が生じなくなるのか、という必要性の問題を検討したいと思います。そのためにはやはりオブジェクト指向についてちゃんと理解しないといけません(^^;AAなんとか理解しようと務めましたが、皆様にちゃんとお話できるかどうかで理解がより深まり、かつ、正しいかどうかの批判にさらされうることができると思いますので、まずは説明からいきたいと思います。

オブジェクト指向のオブジェクトとは、「もの」です。しかしどちらかというと「対象」という方がなじみがありますね。英文法でいうところのSVOとかあった、あのOです。オブジェクトのO。Sはサブジェクトでしたね。この辺からだんだん嫌な感じはするものです(^^;;対象であるから、何か、なんです。自分でない、何か。ものはものですが、なんかわからんものがごろんと転がってる感じ。いや、ふわふわ浮遊しているとでもいいましょうか?(^^;;

オブジェクトとは何か、という哲学的議論は実はあまり意味がないようです。何か、で十分ですが、その何か、は、外からは中身が見えません。実はからっぽ、というわけではなく、外からは見えないという意味で他と区別された何かです。こいつをカプセル化と呼びます。オブジェクト指向の一要素です。

もちろん、このオブジェクトたる何か、には何か仕事をさせるつもりでいます。何かに何かさせるというのもわかったようなわからんような話ですが、実を言うとこの何かというのは、なんとでも決めれるという意味です。必要に応じてなんとでも決めれます。この何か、に意味を持たせるのをオブジェクト分析といいます。三國志でいえば、オブジェクト候補は武将ですね。ぶしょーと名前をつければ、なんかわからんものが蛇矛を持って虎髭の…いや、まだ、そこまで具体的にしてはいけません(^^;;無名武将Aみたいなオブジェクトとして検討を進めてみましょう。

オブジェクトに武将と名前をつけたとたん、めちゃくちゃ具体的な何か、になってしまいました(^^;本当はよーく検討してオブジェクトは決めないといけないようです。しかし三國志ならやっぱりぶしょーでしょう(^^;;プレイヤーはこの武将に命令を下し、武将が何かするわけですから…!

さて、オブジェクト候補として武将を検討しましたが、話を戻すと、このオブジェクト武将には武力などの能力や、実行しろと命令されたコマンド内容などのデータを持っています。さらに、コマンド内容に応じて行動する手続や、訓練するなどして自らの能力を変更させる手続をも持っています。このオブジェクト武将は、こういった与えられたデータの中身を通常は外には見せないし変えられもしないという性質を持たせます。これが先程のカプセル化です。

通常というのは、必要があれば見せたり変えたりすることができるということです。張飛オブジェクトが曹豹オブジェクトをぼこすかに殴っても曹豹オブジェクトの武力データは変わりませんが、ちゃんと訓練コマンドを与えてぼこすかに殴れば、曹豹オブジェクトの武力データは上がる(かもしれない)、ということです。いや、その前に恨みデータが上がりそうですが(^^;;

そして、たとえ曹豹オブジェクトの武力データが上がるとしても、張飛の訓練という方法によって上がるという発想なのではなく、曹豹オブジェクト自体に訓練されれば武力が上がるという手続を持っていて、そこに張飛の訓練があったという内容を曹豹オブジェクトが受け取ってはじめて武力上昇手続が働き、その手続の結果によって曹豹オブジェクトの武力データが上がるという順番を踏みます。ややややこしいですか?(^^;

手続指向型ならば、訓練コマンド→対象(曹豹)の能力上昇判定→OK→対象の能力上昇、という手続を取ることでしょう。これをオブジェクト指向では、対象(曹豹オブジェクト)自体の中に、訓練を受けるという手続をもっていて、訓練を受けるというコマンドを与えられれば、対象の中でその手続が成否を判定して、それにより対象の能力を向上させるという風に、オブジェクトの中にオブジェクトができることは全部用意することになります。

ここまでだとあまり違いがはっきりわかりませんね。とりあえず、オブジェクトには独自のデータや手続を持っていて、それにはプログラムの他の部分から直接操作したりすることはできず、オブジェクト自身がもつ操作専用の方法(たとえばコマンドインターフェース)を使わなければならない、ということをカプセル化と呼びます。オブジェクトが他と区別された何か、であるなら、やはりオブジェクト自身のことはオブジェクト内部で処理させるという発想ですね。

それから、無名武将オブジェクトはデータが異なる以外は同じふるまいをします。データによって違うふるまいをする、というところまで同じです。ところがもちろん、誰に話しかけても「劉備様、ご命令を」としゃべるのではおもしろくない(^^;たまには「お、兄者、なんだい、なんでも言ってくれよ」とか、「孫策様、いかがされましたか」とか言ってほしいものです。こういう、基本は同じだが、もの(人)によって違うという要素があれば、もとのオブジェクトをベースに改造をほどこした別のオブジェクトを作ることができます。これを継承といい、これまたオブジェクト指向の一要素です。継承先のオブジェクトは、もとの部分はまったく同じなので中身を書く必要がないので、重複を省けます。

しかし、どうも話によると、あまり継承は多用しない方がよいようです。たとえば量産型オブジェクトに対して紗亜専用オブジェクトは頭に飾りがあって赤い塗装がされていて、速度が早い、というものがあったとします。ここで紗亜専用オブジェクトというのを作るのではなく、もとの量産型オブジェクト自体のデータとして飾りの有無、速度、塗装色などを用意して、紗亜専用のものだけデータを変えればすむだけです。これならわざわざ紗亜専用オブジェクトというものを用意する必要はありません。

そういう意味でオブジェクト分析をみっちりすれば、あまり無駄な違いの表現のためだけに細かいプログラム表現を作成する必要はなくなるのです。継承をするならば、どうしても必要なものだけにする、ということです。それは、抽象化→具体化の流れ、分類の流れの時のようです。分類とは、よく言われる、人間は、霊長類で、哺乳類で…というやつです。抽象化すればするほど、いろんな違いを含みますが、細かい差異は無視されます。この抽象化←→具体化がわからないとオブジェクト指向は誤った方向に進むようです。

量産型オブジェクトと紗亜専用オブジェクトという違いは、確かに抽象化←→具体化です。しかし量産型オブジェクトと紗亜専用オブジェクトは結局並列です。おそらく上位に座苦というオブジェクトがあるのです。これに怒無とか慈無とかいう類がこれまた並列であって、さらに上位に機動歩兵というオブジェクトがあるのです。機動歩兵の並列に、下位オブジェクトにたとえば木馬を含む戦艦オブジェクトや、下位に虚亜ファイターを含む戦闘機オブジェクトなどが並びます。その上位は兵器オブジェクトでしょうか。こう考えていくと、わざわざ座苦や怒無といったオブジェクトを作るより、機動歩兵オブジェクトをみっちり分析して、種類の差異をデータで表現できるよう全部含むようにした方がよさそうです。そう、オブジェクト指向とは抽象化指向なのです。差異をできるだけひとつで含むような、上向き方向なのです。

これに対して、手続指向型は細分化です。とにかく細かく細かくわけていきます。具体化に向かう方向ですね。手続きというのが究極的には1本しかありえない、同時に1つの流れが複数の道を進むことはない、ということからして、想定された分岐はありつつも、実現する流れは個別具体的なたった1本だけなのです。だからこそ、その究極の1本が正しくあるよう、様々々々々な道を事前に作っておくのです。使われるのが1本であったとしても、それが最後まで正しくあるよう、途中で様々々々々々々な道を事前に作る、それは細分化そのものですね。

という手続指向型の頭でオブジェクト指向の継承を考えていくと、どんどん細分化、具象化の道をひた進みます。たとえば、機動歩兵の機種ごとに紗亜専用オブジェクトを用意したりするわけです。下手に継承を利用すると、ちゃんと抽象化したオブジェクトを準備し、究極的には上位の数個のオブジェクトにまとまる、というのではなく、どんどかどんどか細かくなり、ある機種から継承された紗亜専用オブジェクトを継承した、ある戦場で使われた紗亜専用オブジェクトと、さらにそれを継承した、次の戦場で使われた、前の戦いの結果で壊れた部分を補修した紗亜専用オブジェクトとを別に用意したりしてしまうのです。なるほど、これだと手続指向型とはいわないものの、継承が複雑になりすぎです。

まあ、そのうちあんまり細かい差異を考えすぎて嫌んになっちゃったり、完成しなくなったりするもんですが、実際にそうなって完成しなくなったシステムなんぞを見たり聞いたりしたことはあります(~_~;)複雑すぎる方向がまずい。単に差異を強調しているだけなのです。オブジェクト指向とは、差異を吸収して抽象化して簡単にする方向をもった思考法なのです。

特に私もこれは誤解していました。たとえば、ある親オブジェクトに対して機能追加のために継承した子オブジェクトがあったとします。機能追加ですから、子オブジェクトの方が親オブジェクトよりも広くて大きいと考えられます。はい、そう思った人手を挙げて…!(^o^)/

はい、そうですね、これはオブジェクト指向思考では間違いです(x_x)どういうことかといいますと、親オブジェクトの方が広い、と考えなければならないのです。なんとなれば、継承元の親とはすなわち抽象化ですから。差異が表現されていなくとも、継承元の方が広い「概念」なのです。機能のあるなしは、差異の表現でしかなく、ある機能がなかろうが、親の方が広い概念なのです。機能追加をもって広くなる、と考えることは、抽象的ではなく機能分析的なのです。こういう方向の継承はよろしくないようです。

たとえば、テレビを見れるパソコンを考えてみましょう。今はやりのテレパソですね。これはパソコンにテレビ機能を付けたと考えられます。だからといって、「テレパソ」が「パソコン」より広い言葉でしょうか?違いますね。もちろんパソコンが広い抽象的な言葉なのです。

さらに、私が今前にしているVAIOや、マックやバリュースターといった違い。これはすべて「パソコン」に含められますね。ところがそれを、VAIOの同じ機種で、ハードディスクが40Gか60Gかの違いをオブジェクトとして継承していくのはまずいのです。そもそもVAIOだろうがバリュースターだろうが、同じパソコンオブジェクトの中でのデータの違いでしかありません。パソコンオブジェクトにOSデータを含めれば、マックとの差異も表現できます。結局みな同じ「パソコン」に含まれるのです。ハードディスクの容量の違いで継承するのではなく、パソコンオブジェクトのデータの違いとなるようパソコンオブジェクトの中身を分析するのです。

ということから考えると、機能の追加なんぞ、カメラがついたりテレビがついたりする程度ならば、場合によってはパソコンオブジェクトのデータ中にそもそも含めておくべきだったのです。もちろんその機能があまりに大きいのであれば、継承すべきでしょうが、だいたいのところ、下位オブジェクトの相違が大きく、まるっきり違うように見えるが上位のオブジェクトには含まれてしまうというものである場合にのみ継承すべきでしょうね。先程の話でいえば、パソコンオブジェクトの下位オブジェクトはタブレットPCとデスクトップとノートブックといった違いまででしょうか。それもオブジェクト分析でいえばあやしいところです(^^;また、兵器オブジェクトのうち機動歩兵オブジェクトと戦闘機オブジェクトは分けた方がよさそうですが、座苦や怒無の違いは機動歩兵オブジェクトのデータの差異に包含させるべきです。

こう考えていくと、いかに具体的な事柄を抽象化できるかというのがオブジェクト指向分析のようです。必要な、個々具体的な事柄や「もの」をすべて挙げ、どんどんまとめて最上位の概念を作る、と。もうさらに上位にはまとまらなくなった段階で、そのまとまり全部に共通する要素を最上位オブジェクトで用意し、本質的な差異が出てはじめて下位に継承する、ということになります。

なるほど、安易に継承してはいけない、というのは、継承が下向き思考であるため、安易に使うとすぐに細分化していき、全然抽象化の方向には向かわないせいですね。

と、まあ、ここまで分析したところであまりにながくなりすぎました(^^;、最近だんだん長文化傾向が続きますので、さすがにオブジェクト指向の最後の要素、多態性とオブジェクト指向分析の実践は次回まわしにいたしたいと思います。。。

index

〔TopPage〕

このページへのリンクはフリーです。
このページについてのご意見、ご質問などは、kr_ryo_green@yahoo.co.jpまでお願いします。
Copyright 2004© kr_ryo All rights reserved.
訪問件数