kr_ryo 徒然日誌 <2005年10月16日分>

三國志製作記117〜パターンに無理やりはめ込む?〜

秋が深まればだんだん寒くなるのかと思いきや、暑くなったり寒くなったり、今日も起きたら暑かったのか、ふとんから飛び出していて、肩が重いというか節々が痛いというか眠いというか、だいたい夜中に蚊にかまれて目が覚めたという、なんだかもうじき11月とは思えない陽気、しかも昨日どしゃぶりだったのがすっかり晴れていい天気、眠気を誘う1日でした、みなさまお休みなさい…(_ _).oO

というわけにもいかず(^^;;A今日も元気に三國志製作です。近頃デザインパターンにすっかりはまった三國志製作ですけども、パターンにはめることで製作が楽ができる面は確かにあります。なんといっても、いやーな感じがする単純コピペが減ります。単純コピペといっても、結局違うところがあるからコピペしてなおすわけですから、精神衛生上悪いものがあります。直しを入れたりすると、無秩序に膨らんだ単純コピペ&微妙修正部分を探し出して直していかないといけないのです。これは面倒なんですよね〜(~_~;)

そこでなんとかしてまとめようとするんですけど、まとめ方に理屈がなく、ただ同じところだけをまとめて別出しするようなことでは、これまた同じところがちょっと違う内容が出た際、結局似たようなまとめたものが複数出てきます。同じところをまとめるということは最適化と言ってよいんだと思いますけど、この最適化は、あくまで現在の対象に対する最適化であって、対象が膨らめばまた変わることもありえるのです。最適化することで変更がかえってしにくくなる、最適化部分を変えることで、そこを利用している部分全部に影響があってできない、ということもありえます。

全部完成してからの最適化ならともかく、まだ途中段階で最適化してしまうと、後々変更がしずらくなる、ということはこういったことが原因です。結局まとめ部分を単純コピペに置き換えて戻すくらいなら、なんのためのまとめかわからず、もうちょっとましな作り方はできんかいな?となり、そのうち、ええい、書き直しじゃあ( ̄□ ̄;)となります(ToT)これを避けるために全体構想を練ってから部分を作るべき、というのは、最適化できるところを想定した上で部分を作っておく、ということにも等しいのですけども、最適化できる部分が全体の中でわかるなら、部分はもうできていることが前提の、机上の空論のような気もしないでもありません。

実際問題、プロのシステム開発においてすら、他人の(しばしば自分の)作ったプログラムを直すくらいなら、一から作った方が早くて正確と言われます。それくらい恣意的でもあり、思いがけないところでつながっていたりするものです。それ以上に、どこでどこを利用しているかなんて、全部把握できるはずもありません。そういう思いは、私自身、製作していけばいくほど、プログラムが出来上がれば出来上がるほど、だんだんわけがわからなくなる、という気がしていくことで体験済みです(ToT)

それを『オブジェクト指向のこころ』では結合度が高いと言っています。結合度が高ければ高いほど1つのプログラムが「1つ」のプログラムで、たった1行直すために全行見直さなければならない、というような事態に陥っているといえましょう。オブジェクト指向プログラムではそれを解体していって、1つのプログラムではなく、オブジェクトという単位で管理することで結合度を下げます。とはいえ、オブジェクト指向プログラムでも、うまく作らなければどのオブジェクトも密接につながっていて、結合度が高いままであることありえます。逆に、なまじ分割したがため、かえってオブジェクト間の見通しが悪くなって、より一層わかりにくいものができあがっているかもしれません。UIと武将などのオブジェクトが密接につながっていれば、UIによる操作ごとに武将オブジェクトが膨らんでいき、本来武将オブジェクトで処理すべき内容ではないUIの変更操作なども武将オブジェクトに取り込まれてしまったりすることになっていたのです。ええい、見通しの悪い!

だからといってオブジェクトを細々作ってしまうと、それはそれで理屈があるわけではないので、作ったのか作っていないのかよくわからない、何がどれを意味するのかわけがわからない状態に陥ります。そうです、理屈です。オブジェクトの数が多かろうが少なかろうが、このために必要なオブジェクトです、というのがはっきりしていれば、いくらかにまとめることができます。その理屈として大きなポイントだったのが「継承」です。抽象オブジェクトから具象オブジェクトに具体化していくわけです。

ところが、動植物の「種」が一目で判別できない位多種多様化しているのと同じように、ただ「継承」だけを使うとわけがわからないくらい細分化されてしまうことになります。継承する理屈がはっきりしていないために、なんでもかんでも継承する、種の爆発が生じてしまいます。武将オブジェクト−武官オブジェクト−豪傑オブジェクト−関羽オブジェクトなんて継承をしてしまうと、呂蒙のはめ所のためだけにややこしい継承をしなければいけませんし、それで整理ができたかというと、なんだかよくわからなくなるだけです(*_*)

ということで、わかりやすいオブジェクト間の関係や、使いやすいオブジェクトを作るためのパターンが、デザインパターンということになります。最適化でもなく、見通しがよくなるわけでもなく、単なる分割でもなく、まとめでもない、けれども後で使いやすくなるのがデザインパターンの目的です。で、使ってみると、確かにプログラム量も最適化より増えますし、デザインパターンとわかっていなければ無意味にオブジェクトが増えて見通しが悪くなり、分割の仕方は型にはまって直感的でなく、知らない人がみたらばらばらのオブジェクト同士がちっともまとまっているようでもありません。デザインパターンとわかった上で使っていないと、わかりにくくなります。それでも、同じような部品を作る際に極端に作りやすくなります。これぞ、パターンの威力!

で、パターンがわかってくると非常に美しく機能的に見えてきます。それこそどこにどのパターンをはめてやろうかという目線になってきます。単純にオブジェクトを作るんじゃなくて、パターンにはまるように作りたくなってくるのです。早くも私も当てはめ症候群に陥っているかもしれません(;^_^Aパターンにはまらない単なるオブジェクトを作ることが、後々使えないし直しにくい、汚いものを作っているような気がするんですね。型を覚えた入門者が、型通りにしかできなくてぎこちないようなもんですかね(^^;A

オブジェクト指向の本も再び新刊がぽつぽつ出だしてきていますが、デザインパターンに触れられていないと、なんだか大事なことを書き忘れた本のように見えてきます。その意味では私がオブジェクト指向を学んだ『オブジェクト指向開発講座』も例外ではなかったりするのです。特に『オブジェクト指向のこころ』では、機能の追加は継承ではなく集約を多用すべきと書いてあるのですけど、『オブジェクト指向開発講座』では、集約については発展途上の概念として1ページ程度で触れられているだけです。逆に『オブジェクト指向のこころ』では、基本がJavaであるため、肝心の集約の実装プログラムが私にはよくわからないきらいがあります。

その上、JavaとDelphiとでは、仕様が根本的に異なっているところがあるようなので、一方では言語の仕様で簡単にできるものが、他方では単純にはできないかややこしくなるということもあるようです。たとえば、Javaでは簡単そうに見えるSingletonパターンが、Delphiではストレートに表現できなかったりするなど、困った面も出てきます。

そう考えると、最近はなんでもJavaになってきているような雰囲気ですね。かつてはVC++かVBだったのが、今ではJavaです。C#もそろそろ流行るのかもしれませんが、無料のJavaに対抗するのは結構大変なんでしょうか。Delphiはあいかわらずですけども(^^;A

話を集約に戻しますと、継承が抽象−具象の縦の関係でもって機能を追加したり内容を変更したりするのに対し、集約は所有包含関係でもって、それを表現します。まさに抽象的でわかりにくいかもしれませんが(^^;A継承は以前お話しましたように、抽象オブジェクト「パソコン」から具象オブジェクト「VAIO」や「バリュースター」を作るような感じです。デスクトップノートブックの違いだけでなく、性能、型番とかも含めるともはや判別がつかないくらい細かくなるのは目に見えています。どこまでも細かく細かく、分類することは実は容易なのです。しかし、それが役にたつかどうかとは別の問題です。

これに対して集約は、「車」オブジェクトに、「エンジン」「タイヤ」「車体」オブジェクトを保持させている関係です。または、「飛行場」オブジェクトに、「旅客機」「戦闘機」「プロペラ機」オブジェクトを保持させている関係とも言えます。厳密には集約とコンポジットに分かれるそうですが、一緒くたに抽象化して集約ということにしておきます(^^;Aで、この保持、というのがよくわからない(*_*)これまた以前お話したように、「エンジン」オブジェクトのポインタを持つだけですむのか、「エンジン」オブジェクトを持つ必要があるのか、ということです。「張飛」オブジェクトに「蛇矛」オブジェクトをどう持たせるのか、というところです……って、今自分で例を作ったとたんに理解してしまいました(^^;A

「武将」オブジェクトたる「張飛」オブジェクトが「武器」オブジェクトたる「蛇矛」オブジェクトを持っているわけです。ということは、張飛も蛇矛もデータを与えられたオブジェクトなので、それぞれをオブジェクトとして実体化して、張飛に蛇矛オブジェクトのポインタを持たせるだけですね。この蛇矛が単なる普通の矛で、槍や刀といった感じで数種類しかないものであれば、いろんな武将が共通して持っていたっていいわけです。武器を持っていないことをポインタがないことで表せば、槍を持つ人数分槍オブジェクトを実体化するメリットはありません。槍が折れるだとか、錆びたとかを表さないといけないならば、人数分槍オブジェクトを実体化する必要がありますけど、そこまで細かくする気はありません(^^;Aで、蛇矛が特別な武器で、強力なものだとしても、槍とか矛とかと並んで蛇矛オブジェクトを作っておけばすむだけです。結局単なるデータの違いでしかありません。これが集約ですね。要は、その分離したオブジェクトの使われる意味を考えなくちゃあならないということです、か。

逆に、ひとりひとり違う武器を持つならば、武将オブジェクトと別にせず、武将オブジェクトのデータとして表せばいいわけです。外出しするのは、外出しすることで同じものをまとめられるからですね。そういう意味でも集約ですね(^^;で、別にこれは、武器とか実際に武将とは異なる概念のものだけではなく、問われてしゃべる内容とか、特殊能力だとかを外に出して武将オブジェクトが所有する関係であってもいいわけです。普通に君主が武将に勝算を聞いて、「勝てるでしょう」と答える場面で、張飛が劉備に対してだけ「俺ならひと暴れで勝てるぜ」と答えるようにしたい場合、継承ならば、武将オブジェクトを継承した張飛オブジェクトについて、武将のしゃべる場面で内容をいちいち変えていかなければならないところ、で、当然、しゃべる内容はすべて武将オブジェクトに含めなければならなく、巨大武将オブジェクトができているところ、しゃべる内容を外に出しておけば、武将オブジェクトもすっきりするし、「しゃべる内容」オブジェクトも修正が容易です。それこそ気まぐれに、武将に応じて変えたものを付け足していけばいいだけになります。もちろんこれを継承で実装しようとしても似たような感じになりますけど、一部だけ変えることなどに対しては、究極的には変える人数分の継承が必要になったり、何階層にもわかれたり、いろいろな組み合わせが面倒だったり(というより、多分できない)することになりそうです。なるほど、継承より集約ですなあ〜(^O^)

個性化を徹底したければ、武将オブジェクトはだんだん枠だけになってきます。逆に、この枠が大事になります。どの武将でも同じ枠を通した動作を行うこと、これがデザインパターンの多くのパターンがパターン化しているところのようです。適切な範囲の枠で、例外がなければ、武将オブジェクトをどれだけ細かくしても、使う方のUIオブジェクトやアプリケーションはどれも武将として抽象的に扱えます。つまり、どれも同じということです。そのことがイマイチわかっていなくとも、デザインパターンに無理やりあてはめていけば、嫌でも枠を通した動作を設計できます。そしてそうできれば、変更にしても多様化にしても、枠の範囲で可能です。問題は枠を超える場合です。一人だけ例外的に枠をはみ出せば、枠を拡張して全員に影響を与えるか、こいつだけ例外に扱う、ということをオブジェクトを使う側が用意しなくちゃあならないのです。まあ、一人だけはみ出すなんてことはなく、結局拡張が必要になってくるんでしょう。それが最初の設計で明らかならばともかく、明らかでなければ途中で多大な修正が必要になってきそうです。しかしそれでも、デザインパターンのこころに沿ったそれぞれの結合度の低いオブジェクト設計をしてさえすれば、そのオブジェクトの修正だけで、すむ、はずなんですけどね…(^^;A

index

〔TopPage〕

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