nounai.output(spaghetiThinking);

趣味と実益を兼ねて将棋プログラム(研究ツールなど)を作ってみたいと思う私の試行錯誤とか勉強したことを綴ってゆく予定です。 主目的はプログラミングの経験値稼ぎですが、コンピュータ将棋の製作も目指してみたいとも考えています。

5/11(Sat) - クラス設計についての考察

クラス設計について、ちょろっと考えたこと。

全体の骨格について

できる限り、構成はCSAが策定する対局サーバのような感じにしたい。CSA方式は役割の分業がわかりやすく、設計的にも良いように思える。また、将来自前のAIを組んだ時、floodgateや選手権に参加するための作業負担を最小(プロトコルの実装+α程度)にできる。AIプログラミングはいずれ挑戦するつもりでいるので、その時本質的な作業以外でロスが発生しそうなことは避けたい。(自前の)既存UIがCSA仕様に近い形になっていれば、ローカル環境でのテストも捗るし、多分私のモチベーションもキープできると思う。やりたいこと(UI設計や将来のAI開発など)をやって、かつそれに付随する本質的でない「作業」はあらかじめ最小化しておきたいのです。

なので、大まかな形としては対局サーバが局面の更新等が発生した際に両対局者に現局面を送信、対局者は相手の番ならスルー、という感じにしていこうと思う。

また、対局サーバはUIとは全く無関係な位置にいる。「クライアント」に対するメッセージの送信やその応答の処理、審判とかマッチメーカーとしての機能だけが重要である。

対局サーバが行う外部とのやり取りに着目する。最低限を考えれば、外部の要素でやりとりが必要なのは対局者のみである。よってサーバはどんな場合でも一様に「クライアント」に対する送受信を考えれば良いようにしたい。UI関連の要素とは「一切」関係を持たないようにしたい。当然、対局サーバのコード中にUIのイベントリスナなどが組み込まれているような状況も避けたい。この辺は「通信」に関わる部分を別のオブジェクトに分離し、オブジェクトコンポジションによってうまく抽象化する術はあるだろう。(仮に、AWTによってGUIを構築する場合、)「通信」オブジェクトがAWTのイベントリスナとかを持つようになれば、対局サーバの本質部分は汚されずにすむ。
※今のところは、Mediatorパターンによって対局サーバとUIの分離を図ろうと考えています。

「局面」まわりのクラス設計

将棋の構成要素を考える。現在の「局面」があって、局面を構成する要素としては「駒の配置」「盤」「駒台」「手番」おそらくこれらが最低限必要になる。この中には持ち時間(や棋譜)も含まれることがあるだろう。とにかく、「局面」が現在のすべての(中立的な)情報を持っているものと考える。 今回考察したのは、「局面」はインタフェースで規定するのが良いのではないかということ。これは言い換えれば、サーバから与えられた「局面」から必要な情報を取得するインタフェースのみを規定し、実際の「局面」を構成するオブジェクトの中身はAIのコードとは独立になるようにしておきたい、ということになる。

プレイヤー人間を想定する場合や、GUIとして提示することを考えれば、「局面」を構成する要素は要素オブジェクトの複合物として表現されている方がいい(もちろん扱いやすい設計であることは確かだが)。なので局面やそれを構成する要素たちをどう構成するかはオブジェクト指向的な色が強い話である。クラス設計がかなり重要になってくるし、練りまくって今後改良(変更)したりしていくことが考えられる。私はOOP熟練者ではないので、この辺はかなり試行錯誤を繰り返しながらになるだろう。

一方、プレイヤーとしてAIを想定する場合はオブジェクト指向的な成分が人間の場合より減るのではないかと思う。AIを書くのであれば、盤面などのデータ構造はプリミティブ型やその配列を使うだけで十分である。AIの高速化をガチで目指す人や、AI開発のノウハウが蓄積してきて、どんな構造がよさげかわかるようになってきた人・・・要はAI開発者としてレベルが上がってきた人でない限り、データ構造はC言語のノリで気楽に決められる。シンプルな構造なら、仕様変更はそれほど行わなくて済むはずである。よって、「局面」として望ましいデータ構造はAIとUI(人間)では隔たりがある。ということが言えると思う。AI的には、プリミティブ型の戻り値で「盤面の配列表現を返す」「現在の手番を返す」いうインタフェースが最低限規定されていれば良い。実際の「局面」の構造はオブジェクト指向的により良い設計を目指して試行錯誤すればいいし、その時にAI側の実装に影響が出るようにはしたくない。インタフェースとして規定するだけであれば、局面オブジェクトや盤オブジェクト、駒オブジェクトなどのクラス設計の問題とAIプログラミングの実装は完全に分離できるようになると考えられる。AI用のシンプルな表現を(定数なども含め)先に決めてしまい、設計した局面オブジェクトが(インタフェースに規定したメソッドによって)AI用の形式をエクスポートできる機能を保証するようにする。

また、AIの実装において「こういう仕様(値)で戻ってきた方が楽なのにな~」と思うことがあれば、(多少効率は悪くなるが)Adapterパターンを用いてデータを再変換し、その上で利用していくことにすれば良いと思う。これによって、局面インタフェースは(メソッドの追加はあっても)既存メソッドの変更をすることがなくなる。局面インタフェースを基軸にして開発が捗る・・・はずである。


今回の内容は以上です。
もし、開発の中でノウハウが蓄積してきてより良い設計アイデアが出てくれば、その時作成したAdapterクラスなどをベースにインタフェースを再設計して最初から組み直せばいいんじゃないかと考えています。スパイラル開発の要領ですね。

コードの再利用を意識しようなどとは思わず、今回はノウハウを蓄積するための1回目のスパイラルと割り切り多少無軌道でも固められる部分から固めていけばいいかなと。実装が不慣れなせいも少なからずあるのでしょうが、私は「ああでもない、こうでもない」と言いながら手を止めてしまう性分のようなので、こういう風に実装経験が積みやすい枠組みを自ら整えてやることも大事かなと考えています。