土屋つかさの技術ブログは今か無しか

土屋つかさが主にプログラミングについて語るブログです。

リファクタリング:コマンドメソッドの返値制約を廃止できた

 今はテキストウィンドウのクリック待ちアニメーションアイコンを作っています。アニメーションアイコン自体はそんなに大変ではなかったんですが、それを文字列の末端に挿入しようとすると(いつものごとく)あの機能も足りない、この機能も足りないとなり、コア実装を延々弄っております。その過程で割と大規模なリファクタリングを行ったのでメモ。

 スクリプト用の組み込みコマンドは全て対応するメソッドが存在しています。これをコマンドメソッドと呼んでいます。これまで、コマンドメソッドの返値には必須が1個、任意が1個存在しました。

 必須な返値は:continueか:end_frameのどちらかを返すという物で、前者であればそのまま次のコマンドを実行、後者であればそこでそのコントロールの今フレーム中でのコマンド処理を終了するという物でした。コマンドの用途によって、どちらを返すかを書き分けていたわけです。

 余談ながら、初期はこれをtrue/falseにしていたのたですが、returnの付け忘れで潜在バグが発生していた為シンボルで明示し、どちらでもない物が返ったら例外で落とす(!)ようにしていました。

 閑話休題。コア実装を作り込んで行くうちに、:end_frameを返さなければいけないコマンドメソッドというのがどんどん減っていき、最終的に「:end_frameを返すだけのコマンド」という特殊なメソッドだけで:end_frameを返せば良いということが分かりました(しかも、内部的にそのコマンドを呼びだしているのはwaitコマンドだけ)。というわけで、このコマンドだけを特殊処理にして、必須の返値その物を廃止することにしました。

 もう一個の返値は、次のフレームに実行するコマンドを返す物です。司エンジンではコマンドは実行されると強制的にキューから廃棄されるため、毎フレーム実行して欲しいコマンドは自分自身を登録しなおす必要があるのです(逆に言うと、1回しか実行される必要がない物は、自分自身の存在管理をしなくて良い)。

 これを返値で行うのが良いことなのかについてはイマイチ判然としていなかったのですが、どうせreturnが必須なのであればそこに盛り込んだ方がコードが短くなるだろうという判断で返値にしていました。しかし、前述の理由でreturn自体が必須でなくなった為、次フレーム用にコマンドをスタックする専用のメソッドを作り、そちらに処理を移す事にしました。

 これらの修正によって、これまでコマンドメソッドでは必須だった返値付きreturnを一掃することができました。可能な限り煩雑な制約を用意したくないので、これが上手く動いたのはラッキーでした。