kr_ryo 徒然日誌 <2005年9月4日分>

三國志製作記112〜オブジェクトのつながりと組織所属関係〜

オブジェクト指向で開発したプログラムは、変更や修正に非常に強いといわれています。というのは、実際のいわゆるプログラムはそれぞれのオブジェクトごとに独立しており、たとえ同じプログラムといえども、別のオブジェクトから別のオブジェクトに命令を送るには、命令を受ける側の予定している命令内容を通じてしか操作できないからです。携帯電話をオブジェクトにたとえると、携帯電話は携帯電話が予定した命令しか受け付けませんよね。たしかにいろんな機能があるし、メールなどで文字を打てるといっても、携帯電話でプログラムは作れません(^^;;

で、命令を受ける側が予定している命令内容だけが、そのオブジェクトの外から操作できる、ということは、その操作さえ変えなければ、オブジェクトの中身をどう変えようが、他には影響がないのです。だから変更や修正に強いと言われるのです。携帯電話の中身が実はごっそり変わっていて、カバーだけが一緒だったとしても、同じ操作であれば使用者は特段気にはなりませんね。それで動作がパワーアップ、たとえば音声がクリアになったり、メールの保存容量が変わっていたりすれば、万々歳です(^-^)

ところがいくら変更に強いといっても、オブジェクトに対する操作自体を変えたら、やっぱり影響が大きく出ます。そのオブジェクトに対する操作をさせようとしているオブジェクトのプログラムからはエラーが出ますし、その操作の結果を受け取って何かしようとしていた部分ならば、結果も変わってくるかもしれません。皆さまも経験があると思いますけど、携帯電話を変えたら操作性がこんなに違うのか!と思う、あれと同じ感じです(*_*)同じ会社の後継機でも勝手が違うところ、違う会社のものなら、なんでこの機能が無いのだ、とか、こんな挙動なんて!と、とまどうことしきり(~_~;)数字キーと数個の機能キーしかないのに、えらく違っていますよね〜

ところがまあ、逆に操作を変えることで便利になったり使いやすくなることもあります。これも皆さま経験されているかと思います。オブジェクトも同じで、やっぱり変更はありえる話なのです。ただ、オブジェクトを操作するオブジェクトとの関係は、最初に設計していきます。これはオブジェクトの設計図であるクラス図というものです。以前掲載しましたよね(^^;小さな図からはじまっていろいろな内容を次々書き込み、だんだん大きくなっていきます。これによって、それぞれのクラス間の操作はだいたい洗い出せることが多いのです。

ところが、やっぱり洗えないところは洗えないもので、武将などを選択するリスト表示とそれぞれのオブジェクトとの関連が、クラス図には現れていないけれども非常に密接な関連を有しているのに、きちんと図示できてません。いろいろな組み合わせが多くて複雑になるわりに、それほど意味があるわけではないんですよね〜(~_~;)これを図示するにはクラス図というものではなく、ステートチャート、状態遷移図というもので表した方がいいのかもしれません。しかしこれはユーザ命令、つまりコマンドと非常に密接に関わっており、まだそこまで詳細に作れていないんですよね(^^;A現状はオブジェクトを作っては挙動を確かめ、操作を作っては挙動を確かめの状態です。

しかも恐ろしいことに、確かめ確かめ作ってきたオブジェクトの操作やプログラム、いつのまにかだんだん多くなってきたようで、いざ設計図どおりに作ろうとした時には、妙にきちんと出来上がったものを変えることになることになってしまいました(*_*)やっぱりテストとはいえ、きちんと動くものを作ろうとすればそれなりにしっかりした形になります。しっかりした形になれば、消したり変えたりはこれまたなかなか人情としてはしずらい(~_~;)しかも同じことでまたエラーを出しつつ修正するなら、テスト部分をきれいにして使おうと思うのもこれまた人情。

ところがそういうわけにはいかなくなります。たとえば軍団オブジェクトと武将オブジェクトとは、それぞれ操作しあう関係です。なんのこっちゃ?というのは、軍団、武将、という名前にひっぱられているからです。オブジェクト、を中心に考えてみます。

たとえば、ユーザが軍団内の団員を見たいと思います。そうすると、リストで軍団を選択し、団員を表示せよという命令を選択→軍団リストが呼ばれ、自分自身に参加している武将の一覧を表示するために参加武将の名前を順番に武将オブジェクトに問い合わせる。→問われた武将オブジェクトが名前を答える→軍団オブジェクトが順番に参加武将の名前をリストに答える→リストが答えられた武将の名前を順番に表示する、こういう感じでプログラムが作られていきます。もちろんリストは、軍団オブジェクトにも武将オブジェクトにも、名前を問い合わせることになりますが、名前を問い合わせられたら答える、という操作は、あくまで軍団オブジェクトや武将オブジェクトに作られていて、リストはその操作を呼び出すだけです。これがオブジェクト指向プログラムの基本ですね。

また手続指向型プログラムの話になりますが(^^;A同じことを手続指向型プログラムでしようとすると、リストのプログラム側で、さっきと同じユーザの命令があれば、まず軍団データを見に行き、軍団データに含まれる参加武将IDを得た上で、そのIDの参加武将データを見に行くという流れになります。つまり、こういう一連の作業プログラム全部をリスト側で作ることになります。当然、城データに含まれる武将をみたければ、似たようなプログラムながら、参照相手先データが軍団データではなく城データとなった形での同じ手順のプログラムを書く必要があります。命令内容ごとにちょっとだけ違う似たようなプログラムを書いているとだんだん嫌になってくるので、なんとかまとめてサブルーチンという、繰り返して使える汎用性が高いものを書こうということになります。

それがオブジェクト指向プログラムだと、はるかに簡単にはるかに汎用性が高くなります。なんといっても、リストは軍団オブジェクトに、軍団オブジェクトが持っている、参加武将報告というコマンド(操作)を実行するだけですからね。それが城だったら、城オブジェクトが持っている、所在武将報告というコマンドを指示するだけでいいのです。

とはいえ、同じような内容ながら、軍団オブジェクトと城オブジェクトのそれぞれの武将報告という操作は、それぞれ軍団オブジェクトと城オブジェクトに分かれているので、それぞれ同じようなプログラムを書く必要があります。しかし、同じようなプログラムといっても、結局自分の中のデータである参加武将一覧を参照して参加してる武将オブジェクトに名前を聞く、という操作を実行するだけです。で、結局最終的に武将オブジェクト側では、名前を答える、という操作が書かれているだけです。これは当然、リストが直接、武将オブジェクトが名前を答える、というような操作を実行させることもできます。これだけで、似たような内容ながら実は違う内容の命令を簡単に書けますね。簡単、というより、直感的、といえます(^-^)つまり、それぞれのオブジェクトは、自分自身に関係するものは自分で処理するようプログラムを書くんですけど、他のオブジェクトに関係するものは、他のオブジェクトとその操作を呼び出して終わりなんです。

そうすると、他のオブジェクトの操作が変わっちゃったら、それを呼び出している側には当然エラーが出ますね。まあ、動いてからエラーが出るくらいなら、動く前にこりゃおかしいぜ、とエラーを出してくれる方が、まだ気づきやすいといえます。形式上はエラーが出ないとしても、実質結果がおかしければ、それはそれで困ったバグということになります。たとえば、城の所属武将を答えるという操作が、城オブジェクト側で、その中身が城の所属武将の子どもを答えるという内容に修正されていたならば、おかしなことになります……そんな凝った間違いは普通はできないですけども(^^;A

さて、そういう各オブジェクト間の操作のやりとり、これをメッセージのやり取りともいうわけですけども、そのメッセージのやり取りもプログラムの大きな要素となっています。というよりも、自分自身による処理以外は、他のオブジェクトとのメッセージのやり取りです。そのためこのオブジェクト同士のやり取りを設計するのが先程のクラス図です。そこで私は、軍団オブジェクトと武将オブジェクトとを直接結びつかせたわけではなく、させていました。

これまでの説明では、軍団オブジェクトと武将オブジェクトは直接やり取りしています。直結していますね。こういう設計もありはありでしょう。ところで、軍団に参加する武将は、同格の連中ばかりでしょうか?もちろん違いますね。大将の曹仁や張遼が、部下の龐徳や楽進やなんかと意見が違っていたりして、なかなか大変ではありました。それでも、大将は大将ということで、部下を抑える権限がありました。参謀だって、実戦には出ない、ということで、全然部将とは扱いが違います。さて、当然大将は1人だとして、じゃあ、ある軍団には何人副将がいて、何人参謀がいて、何人部将がいるのが妥当でしょうか?

非常に難しい、というより、正解はないような気がします。副将なんていらない、ということもあれば、趙雲にケ芝をつけることもあります。参謀をつけたくても誰もいない、なんてこともあるでしょう。はたまた、手持ちの20人全員出撃させたいということもあります。ところが…もうお分かりのように、よくあるゲームでは、誰がどういう役割で何人参加できて、全部で何人参加できる、ということが、固定です。

これは設計上仕方ない面もあるんですよね(~_~;)軍団と武将との関係は、総大将として1人、副将として2人、参謀として1人、部将として6人、というように決めておかなければ、軍団内の参加武将というデータを用意できないんですよ。よくあるのは副将は10人までとか、参謀は5人までとか最大値で準備することですけども、SWGの建艦制限同様、いつの日か上限は超えられそうなこともありますし、なんでこの上限?と思われることもあります。だからといって、副将300人、参謀100人というような、誰もがそこまで達しないであろうような上限を作るのは、できないことはないですが、かなり無駄です。確かに大は小を兼ねます。とはいえ、毎日スーツケースを持って出勤する人はいないでしょう。

となると、最適化、つまり、どこまでが適当か、ということを考えるのがプログラマーの仕事になります。そして、数十隻でいいじゃろうと思っていたら、1万隻10万隻なきゃ嫌だと言われるわけです(^^;Aしかもそれがプログラム全体を左右するような仕様であったりもします。なかなか慎重にならざるを得ませんね。

軍団オブジェクトと武将オブジェクトとの関係も、そのまま直結するとすれば、軍団内のどういった役割を持つ武将オブジェクトが誰それ、というような情報を持つ構造を軍団オブジェクト側にプログラマーが用意しておかなければなりません。逆に武将側で俺は張飛軍団の大将だ、というような情報を持たせてもいいわけです。ここで、役割というものを、武将側で持つのか軍団側で持つのかが問題になります。軍団側で持たせると、無駄のないように(無駄があったとしても、それはそれで)上限を事前に作らないといけません。武将側で持たせると、軍団側には、自分自身では大将が誰で、副将は誰と誰とで何人いて、という情報が無くなります。少なくとも参加武将情報は必要でしょうから、それを持っているとして、毎回それらの武将に君はどんな役職かね、と問い合わせることになります。

こう考えていくと、まだしも役割は武将オブジェクト側に持たせる方が、ややプログラム的には処理が増えそうながらまだ汎用性が強くなります。とはいえ、武将オブジェクトがかなり軍団に縛られた感じではありますね。軍団に参加していない武将でもからの役職情報を持っているわけですから。

ところで、これはいつも参考にしている「オブジェクト指向開発講座」ですが、ここに問題となる例が出ています。兼務です。つまり、ある軍団の参謀かつ、英雄の側近というような兼務を表現することができなくなります。なんとなれば、役職データは1つしか持てませんからね。もしこれを兼務用にもう一つ、ということになれば、当然先程から議論している、軍団側に役職データを持たせたこと同様、上限問題だとか無駄問題だとか生じます。兼務なんて全然ないかというと、諸葛亮を出撃させるごとに、丞相から総大将に役割変更させるのもどうかな、という気がしませんか?かといって、軍団内役割と別の内政的役割を持たせたとしても、丞相として軍団を率いるというのと、やっぱりちと変わってきます。

ここでオブジェクト指向の知られざる重要概念、関連のオブジェクト化というものが登場します。どういうことかというと、役割、をオブジェクトにしてしまうのです。役割オブジェクトは、武将オブジェクトと軍団オブジェクトを結ぶ、ひとつのオブジェクトです。これまで武将と軍団との間をなんとはなしに結んでいた関連を、オブジェクトとして登場させるのです。これで役割オブジェクトさえ作れば、丞相と総大将どころか、同一軍団の中で副将兼参謀なんてこともできます。軍団と武将とを結ぶ役割オブジェクトを、役割ごとに作るだけですからね。

しかしながら、一人何役というのは、机上の上では可能ですけれども、実際はどれかひとつしか意味がないことが多いのです。あ、丞相兼総大将兼発明家兼主君のお守り兼裁判官兼事務員なんてひとり何役もできる人もいないではないですが、まあ、珍しがられるように例外です(^^;Aその辺はできる、けど、バランスでやっぱり一人一役ということも考えられなくはないです。しかし、作られた上限よりはるかに意味があります(^-^)

と、いうような役割オブジェクト、実は設計図には入っていたのですけど、オブジェクト生成テスト中にすっかり軍団オブジェクトと武将オブジェクトが密接に連絡しあうようになってしまってました。関連オブジェクトというのは結構概念的に難しく、オブジェクト生成初心者にはなかなかわかりづらかったのです(^^;しかし、やっぱり必要ということで間に割っていれようとしたとたん……そう、最初にお話した通り、操作を変えなくちゃあならなくなり、なかなかどうして、全部総取っ替え程度のすさまじい変更になっています…(ToT)現在進行形なのは、変更中だからです(*_*)この辺は「オブジェクト指向開発講座」でも話題にありましたけど、変更に強いオブジェクト指向の中でも、後から変更するにはつらい部分だそうです…まあ、まだ作りたてだからまだましか、というところ(--;)これからまた、がんばることにしましょう(^-^)

index

〔TopPage〕

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