コアスクリプト、マジックナンバー多すぎないか?

皆さんもお感じになられているでしょうが、
コアスクリプトって、説明のないマジックナンバーが非常に多いですよね。
例えば……
・イベントIDで、0がこのイベント、-1がプレイヤー
・イベント起動のトリガー(プレイヤーから接触、自動実行など)が1とか3とかになっている
・スキルの効果範囲の設定では、1~14が使われているが、定数化されていない
などで、しかもこれらについては、コアスクリプト内では一切コメントが付いていません。

通常の大規模プロジェクトの場合、こういうのは定数を設けるのがセオリーですが、
コアスクリプトはそれをしていないため、初めてコアスクリプトを読む人は、
ある程度熟練のプログラマでも、面食らうんじゃないでしょうか。

これに関しては、以前もここのタイムラインでちょこっと触れたのですが、
尾島氏ひとりでやっているから、いちいち定数を作るところまで
労力が回らないんじゃないか、という意見が出ていましたが、
僕は今回、ちょっと眉をひそめる状況に出くわしました。

それは、MVで作ったプラグインをMZに移植していたところ、
原因不明のエラーが起きて、デバッグに苦心しました。
このエラーの原因は、MVにあった、Graphics.BLEND_ADDという、
画像の合成方法に対する定数が、MZでは廃止されていた
ことが原因でした。
なぜ定数を廃止したのか、理解に大変苦しみました。

もしかしたら尾島氏は、定数化に否定的な考えを持っているのかもしれません。
定数だと分かりやすいのは事実ですが、定数が多くなると、それだけ、
実行のパフォーマンスが落ちたり、時には逆にプログラムが読みにくくなる……という
考えをお持ちなのかもしれません。

実際僕はかつて、WindowsのVisual C++で、MFCを使っていましたが、
これには、これでもかというほど、定数がありました。
確かに可読性は上がりますが、定数の実際の値を調べるのが面倒になることがありました。
尾島氏も、それを考慮して、敢えて定数化せず、マジックナンバーを直接使う方式を
採用しているのかもしれません。

これに関して、皆さんの考えを伺いたいです。
「面倒に思った」などの感想でもいいし、「こうすればよくなる」などの改善案でも、
何か、思ったことがあったら、気軽にお聞かせいただけると嬉しいです。
 
ブレンドモードの廃止に関しては、PIXI.BLEND_MODES http://pixijs.download/release/docs/PIXI.html#BLEND_MODES で定義してあるのをツクール側で再定義する必要はないのではないかと思っていたので、廃止自体はそんなに不思議ではありません。
ただコアスクリプトの中で PIXI.BLEND_MODES の定数は(たぶんSpriteでしか)使われてないので、つーかーえーよー!! とは思ってます。

でマジックナンバーの件なんですが、例えば Game_Interpreter の commandXXX って数字がズラーっと並んでるのとか、ダメなコードの例に出していいんじゃないかと思うぐらいです。
他にもおっしゃるように、コアスクリプト全体にマジックナンバーが散見されてげんなりです。

そもそもツクール本体でも変数とかスイッチが数字でしか指定できないのも、BASICとかCOBOL、PASCALの時代じゃないんだから、この制限はなんの修行だよって感じです。
とりあえず今、変数・スイッチを名前で指定できるプラグイン作ってるところです。

今時はJS実行側でかなり賢く最適化してくれますし、変にコード側で工夫しても裏目に出たりするので、整数指定にこだわるのは意味ないんじゃないかなぁ。
これはもうロジカルな判断ではなく、尾島さんが「整数信仰」みたいなものを持ってる感じはします。

ただ、たぶん前に「尾島さんの手が回らないんじゃないか」と書いたの僕だと思うんですが、今もやっぱりそれが主要な原因とは思ってます。
優秀な人を増やせばいいんでしょうが結局は要するに「予算がないんじゃい!」とゆーね。予算つけてやってプリーズ!
 
最後に編集:
なるほど、ツクールは動作中に変数が追加されることはないから、最初に一気に変換しちゃってもいいわけですね。
今僕が作っているのは都度走査しているので、若干速度的にどーかなと思ったりしてたんですよ。

ちなみにこれ、MVから移植というか作り直しの、めっちゃ途中。
https://github.com/tonbijp/RPGMakerMZ/blob/master/TF_Condition.js
 
最後に編集:

fspace

ユーザー
マジックナンバー多いなぁ、というのは自分も感じてました。

ただ、定数として名前を付けている部分もあるので、リテラルで書くことを良しとしているわけでもないのかなとは思います。おそらく、名前を付けることでやや記述が崩れるのを嫌っているんじゃないかな、と。

まあ、個人的にはすべて名前を付けるべきだと思いますが……。


・イベントIDで、0がこのイベント、-1がプレイヤー

0-1だけ特別な名前を付けて、それ以外はそのまま数値として扱うという一貫性のなさを嫌ったんじゃないかと。


・イベント起動のトリガー(プレイヤーから接触、自動実行など)が1とか3とかになっている
・スキルの効果範囲の設定では、1~14が使われているが、定数化されていない

この辺りは配列で複数指定することがあるので、一行のコードが複数行になるのが嫌だったのかなと。

JavaScript:
Game_Action.prototype.isForFriend = function() {
    return this.checkItemScope([7, 8, 9, 10, 11, 12, 13, 14]);
};

Game_Action.prototype.isForFriend = function() {
    return this.checkItemScope([
        Game_Action.TARGET_XXX,
        Game_Action.TARGET_XXX,
        Game_Action.TARGET_XXX,
        Game_Action.TARGET_XXX,
        Game_Action.TARGET_XXX,
        Game_Action.TARGET_XXX,
        Game_Action.TARGET_XXX,
        Game_Action.TARGET_XXX,
    ]);
};

Game_Character.prototype.processMoveCommandなんかでも、わざわざクラスに別名を付けて記述を短くしたりしていますし、長くて単調な記述を嫌っていそうな感じはしますね。


でマジックナンバーの件なんですが、例えば Game_Interpreter の commandXXX って数字がズラーっと並んでるのとか、ダメなコードの例に出していいんじゃないかと思うぐらいです。

これも多分長くて単調なswitch文を書きたくなかったんじゃないかなと。

JavaScript:
const { code, parameters } = command;
switch(code) {
    case 101: return this.showText(...parameters);
    case 102: return this.showChoices(...parameters);
    // ...
}


このエラーの原因は、MVにあった、Graphics.BLEND_ADDという、
画像の合成方法に対する定数が、MZでは廃止されていた
ことが原因でした。
なぜ定数を廃止したのか、理解に大変苦しみました。

これについてはとんびさんの言う通りで、廃止は正しい判断だと思います。


そもそもツクール本体でも変数とかスイッチが数字でしか指定できないのも、BASICとかCOBOL、PASCALの時代じゃないんだから、この制限はなんの修行だよって感じです。

エディタからは名前で指定、コード上からは対応する数値を操作、という方針自体は効率的で正しいんじゃないかと思います。

問題なのはところどころこの方針が徹底されていないことですね。メッセージに変数を埋め込む場合だったり、メモタグに変数を指定する場合だったりです。自分は変数のIDが数値で表現されていることよりも、メッセージやメモタグの仕様に問題を感じます。


ちなみにこれ、MVから移植というか作り直しの、めっちゃ途中。
https://github.com/tonbijp/RPGMakerMZ/blob/master/TF_Condition.js

確か PluginCommonBase は @type が string や file の場合には、特定のサフィックスを付けないと正しく動かなかった気がします。ただ、付けると今度は埋め込みができなくなりますが……。

正直なところ、いろいろと問題を感じていて、個人的には PluginCommonBase はおすすめしません。
 
みなさんコメントありがとうございます。
いろいろと腑に落ちる所があったのですが、
Graphics.BLEND_ADDについてだけは、少し語りたいことがあります。

MVにあった、ArrayやStringのcontainsメソッドは、
公式がincludesを採用したことにより、当初、削除される予定でした。
しかし、僕はdeprecated扱いでいいから残してくれ、と相談し、
その意見が通りました。
これは、MVプラグインの中で、MZでも変更なしで動くものが
少なくないことを発見したのですが、その多くがcontainsを使っていたからです。

もし、僕がGraphics.BLEND_ADDが廃止されたことをその時知っていたら、
これも同様の理由で、deprecated扱いで残すことを提案していたでしょう。
実際、MVでこれらの定数だった部分を見ると、別の変数ではなく、
即値で書いているところを見ると「逆に可読性下がってるじゃん」って
思わずにはいられませんでした。

この定数の話は以上ですが、
やはりマジックナンバーを少なめにするのは、結局は尾島さんご自身の好みによる
部分も、あるのかな……と皆さんのご意見を拝見しながら思っていました。
 
もし、僕がGraphics.BLEND_ADDが廃止されたことをその時知っていたら、
これも同様の理由で、deprecated扱いで残すことを提案していたでしょう。
確かに、アニメーションとかの機能は残してんだし、この定数も使わないとしても残すべきだったでしょうね。
おっしゃる通り、削除するほど構造がガラッと変わってるわけではないので。
 

fspace

ユーザー
もし、僕がGraphics.BLEND_ADDが廃止されたことをその時知っていたら、
これも同様の理由で、deprecated扱いで残すことを提案していたでしょう。

@deprecatedの判断は難しいですね。あまり古いAPIを残しても邪魔なので……。

マイナーバージョンを上げたときに@deprecatedを付けておいて、メジャーバージョンを上げたときに消すという方法はよく使われるので、理想的にはMVのバージョンアップで予め@deprecatedを付けておいて、MZのリリース時に削除するのがよかったのかなとも思います。

非推奨期間を設けた場合、削除して動かなくなるプラグインというのはもうメンテナンスされていないということなので、これらは元から使用にリスクを伴うプラグインです(バグを踏んだ瞬間に詰むので)。そういうプラグインについては、フォーラムあたりに報告してもらって、別の人がメンテナンスを引き継いだり、代替プラグインを製作したりした方が健全かな、と。まあ、問題は誰がそれをやるんだということですが、今のフォーラムを見ていると対応してくれる人はそこそこいそうな感じがします。


実際、MVでこれらの定数だった部分を見ると、別の変数ではなく、
即値で書いているところを見ると「逆に可読性下がってるじゃん」って
思わずにはいられませんでした。

「PIXIの定数を再定義すべきじゃない」と「rmmz_core以外でPIXIに触るべきじゃない」が競合した結果、最悪の形で解決した感じになってますね、コレ……。確かにこれならまだGraphics.BLEND_ADDの方がマシですね。しかも、検索してみたらrmmz_core以外でも数か所PIXIを参照してるという……。blendModeもよく見ると、PIXIのプロパティを上書きして意味を変えてる……?
 

Fossil

ユーザー
非推奨期間を設けた場合、削除して動かなくなるプラグインというのはもうメンテナンスされていないということなので、これらは元から使用にリスクを伴うプラグインです(バグを踏んだ瞬間に詰むので)。そういうプラグインについては、フォーラムあたりに報告してもらって、別の人がメンテナンスを引き継いだり、代替プラグインを製作したりした方が健全かな、と。まあ、問題は誰がそれをやるんだということですが、今のフォーラムを見ていると対応してくれる人はそこそこいそうな感じがします。

「MZ」の「MV」プラグインを使用するために作成されたプラグイン「Fossil」があります。

Fossilは、「Graphics.BLEND_ADD」などの古いコードを追加しま

(これは機械翻訳です)
 

elize

ユーザー
私は、「熟練して全てのマジックナンバーの意味が瞬時に理解できるほどに熟練すればそっちの方が楽で、それが現実的に可能」であるためにマジックナンバーを良しとしているように思えます。開発者レベルにコードを熟知し手足指先のように扱えるようになると、その感覚になるのではないでしょうか、私はまだ程遠いですが、そのようなお考えを感じます。
 
私は、「熟練して全てのマジックナンバーの意味が瞬時に理解できるほどに熟練すればそっちの方が楽で、それが現実的に可能」であるためにマジックナンバーを良しとしているように思えます。開発者レベルにコードを熟知し手足指先のように扱えるようになると、その感覚になるのではないでしょうか、私はまだ程遠いですが、そのようなお考えを感じます。
熟練すればOKというのはあまり解決方法として良くなくて、アホでもOKにしとかないとよろしくない。
なぜなら僕はアホだから(笑)

たぶん頑張れば一瞬ぐらいその境地に達することはできるでしょうが、次の日にはアホに逆戻りしていること間違いなしです。
僕は苦労とか修行とかしたくないので「頑張らなくてもそこそこわかる」感じになってて欲しいのです。
 

elize

ユーザー
熟練すればOKというのはあまり解決方法として良くなくて、アホでもOKにしとかないとよろしくない。
なぜなら僕はアホだから(笑)

たぶん頑張れば一瞬ぐらいその境地に達することはできるでしょうが、次の日にはアホに逆戻りしていること間違いなしです。
僕は苦労とか修行とかしたくないので「頑張らなくてもそこそこわかる」感じになってて欲しいのです。
どの程度のアホまでフォローするか...という境界が大事なように思います、初めて読む人がドキュメントとか一切なしで理解できるコードまでにしてしまうと冗長すぎて可読性落ちると思うので、どのくらい歩み寄るか?という...

「それにしてもコアスクリプトはマジックナンバー使いすぎ」、ということであれば否めないです。開発側も匙加減についてはちょっとやり過ぎた、くらいに思ってるんじゃないですかね...
 
トップ