自語りになりますけど昔自分もスクリプト制作の有償請負で痛い目を見た経験があるので気持ちは分かりますよ。何故かというと、プラグインの改造依頼としてよくそういうプラグインが持ち込まれてとてもツラいからです。 解読する手間やリスクを含めて請求すると「高くない?」となり、 新規に作り直しましょうと提案すると「なんで?」となり、 これは改造できませんと断ると「実力がないのかしら?」となります。 だからといって「クソコードなんでムリです(意訳)」なんて言えば角が立つのは避けられないわけで……。 少しでもこういう事態が減ればいいなと思って書きました。
RPGツクールXP発売時点ではスクリプト素材という概念もありませんでしたけど
今は不特定多数の人間がシステムをこねくり回す事まで想定しないといけない時代になったんですよね
オレ用オブジェクトアンチパターンは海外の二大競合プラグインでよく見ます。
というより、Yの付くプラグインがそれを基本として広めてしまったのが悲劇の始まりでしょうか。
オレ用オブジェクトパターンは、一括で初期化するとエディタで調べやすくなるので使い方次第。
こちらの記事はここでの数々の反応も含めて、全面的に信頼できる内容であると認識しました。
基本指針とさせていただきます。有益な記事をありがとうございます。
私が使っているプラグインパラメータの格納方法ですが、オレ用オブジェクトではあります。オブジェクトに入れたほうが調べやすいことって何かありましたっけ?
const setting =(function(){
//プラグインパラメータを一度展開。
const param = getParam();
//一度にオブジェクトにまとめる
return {
value:Number(param.value),
name:String(param.name),
};
})();
プラグイン制作者も一介のユーザに過ぎないのであまり気に病む事も無いと思いますよ。間違いなく一番他人に迷惑かけてるプラグインだろうなとは思ってましたが、こちらの記事を読んで確信に変わりました。
そらそうでしょう。ここの意見見る限り、そちらは対応できなくても仕方ないといった感じなのでしょうか?
パラメータを手動で探す手間が減って、settingから入力補完でパラメータを探せます。
単純に「JavaScriptに慣れるため」「MVの戦闘システムの構造を理解するため」「こういうこともやろうと思えばできるよ的な例」として作ったのですが、時間がたつにつれまずいことには気づきました。
間違いなく一番他人に迷惑かけてるプラグインだろうなとは思ってましたが、こちらの記事を読んで確信に変わりました。
ちょっと気になったのは、ES2015からの機能についてです。
最近「ツクールのバージョンが1.5なのでプラグインが動かない」というコメントをよくいただきます。
たいていは「アップグレードして」で解決するのですが、それができない方もいるわけでして・・・。
もうMVではES2015からの機能が使えない方に合わせるのが正解なのではないかと思い始めています。
ここの意見見る限り、そちらは対応できなくても仕方ないといった感じなのでしょうか?
立ち絵や一枚絵、歩行グラ等の画像素材オーダーメイドの相場は大体数千円から数万円程度だと思うんですよ。
それならプラグイン素材もそれにケが生えた程度出せば十分だろ、勿論バグなんて出したら許さね~からな~と
同人依頼慣れしているゲーム作者ほど相場を見誤ってトラブルに発展するケースはそこそこ聞きます。
ES5対応の目的は主にIE対応のために行われるものですが、
モダンブラウザ以外のブラウザを完全に切り捨てるなら、最低でもES6でいい気がしますね。
プラグインの有無の判定とパラメータのパースはツクールのエディタ側が悪いよなって気がしますね。プラグイン側に委ねた結果こうなってる感じ。
evalは素人が使うと危険なのは間違いないですね。むやみに使わず、危険性をきちんと理解して運用していれば問題ないと思います。
JSON.parse(JSON.stringify(...))は、確かにパラメータのパースに使うのは結構微妙ですが、replacerを使って再帰処理を書く場合は、普通に書くよりも安全に書けたりします。
俺用オブジェクトに関しては、煩雑にさえならなければわりと容認派です。ただ、プラグイン1つのために大量にグローバル変数が量産されるのは頂けないですね。
Graphics.frameCountの誤用は、そのままUnity感覚で動作確認せずやってしまうケースが多いんだろうなあって感じしますね。
基本的にプラグイン書く人は全員、Airbnb JavaScript スタイルガイドを読んでほしい感はありますね。
あとまあ、PrettierやBeautifyのようなオートフォーマッターを使ってほしいですね。この2つが守られてれば最低限読みにくいコードにはならんと思います。
let/constに関しては、イミュータブルを意識してなるべくletも使わないようにしてほしいですね。
おそらくこの記事のターゲットとしては、ピュアなJavaScriptをそのまま書く人を想定してるのかもしれないですけど、もし可能ならどんどんNode.jsのフレームワークを使いまくるべきだと思います。
今はTypeScriptやBabel、ESLint、JSDocのような便利なツールもあるわけですし。
まあでもやっぱ、技術レベル的に厳しいものがあるのかなって感じもしますね・・・
プログラミング初心者が下手に無限ループのバグを引き起こしやすいアルゴリズムを自前で書くよりも、このような致命的なバグが発生しにくい方法を使ったほうが保守性等の観点から安全だという意味です。JSON.stringifyがよしなにしてくれるから安全というのは何かおかしな感じがします。結局は想定されるすべての入力に対して正しい出力を定義しなければならないはずで、そもそも別の目的を持った関数をもってきて特殊なケースはいい感じにしてくれるはず、とはならないのでは?
const array = [1, 2, 3, [4, 5, 6, [7, 8, 9]]];
// 再帰関数をちゃんと書いたコード
const before = (a) => {
let data = [];
const recursiveFunc = (target) => {
for (let value of target) { // for (let i=0; i<target.length; i++) value=target[i] だとより煩雑に
if (Array.isArray(value)) {
recursiveFunc(value); // 一歩間違うと無限ループバグを引き起こす
} else {
data = [...data, value];
}
}
};
recursiveFunc(a); // recursiveFunc の呼び出し先が 2 回とも異なる
return data;
};
// JSON.stringify で再帰関数を書いたコード
const after = (a) => {
let data = [];
JSON.stringify(a, function (key, value) {
if (!Array.isArray(this[key])) {
data = [...data, this[key]];
}
return value;
});
return data;
};
console.log(before(array), after(array));
// (まあこのサンプルだと array.flat(2) でも同じ結果だけど・・・)
そもそも、ES6以降の構文を使うなら関数型言語的にメソッドチェーンを多用しない理由もないと思います。自分も関数型的な書き方を意識してほぼconstで書きますが、レガシーなオブジェクト指向のツクールでそれを要求するのは少し酷な気もします。
console.log(
$dataActors
.slice(1) // または .filter(Boolean)
.filter(({ classId }) => classId === 3)
.map(({ nickname }) => nickname)
);
ちなみにlodashはMITですよ。あくまで僕個人の考えですが、同じ処理なのに人によって全く書き方が異なるという処理は少ない方がいいと思います。同値比較のためだけにlodashを入れてライセンスが複雑になるよりはいいかなと思ってます。
「トランスパイル後のスクリプトだけしか公開しない」という前提がそもそもおかしいんです。トランスパイラは変換後のJavaScriptが読みづらいのでツクールではあまり使用する気になれないのですよね。
プログラミング初心者が下手に無限ループのバグを引き起こしやすいアルゴリズムを自前で書くよりも、このような致命的なバグが発生しにくい方法を使ったほうが保守性等の観点から安全だという意味です。
実際、このように JSON.stringify で書かれていた方がコードの数が少なく、どういった問題があるのかどうかまで比較的早く知ることが出来るので、自前で書くよりも既にあるものを使って書いたほうが分かりやすいこともあるかと。
そもそも、ES6以降の構文を使うなら関数型言語的にメソッドチェーンを多用しない理由もないと思います。
実際に関数を用いてループを行ったほうが無限ループバグが起こりにくいので、使わない手はないかと。
ちなみにlodashはMITですよ。あくまで僕個人の考えですが、同じ処理なのに人によって全く書き方が異なるという処理は少ない方がいいと思います。
「トランスパイル後のスクリプトだけしか公開しない」という前提がそもそもおかしいんです。
ソースコードもまとめてGitHubなりに公開するべきで、トランスパイル後のコードは動作軽量化のためにMinifyされているのがベストだと思います。実際にPIXI.jsのリポジトリもそのように運用されていますし。
それに、ソースマップをコードの中に埋め込むという方法だってあります。
僕は致命的なバグだと思いますね。確かにハマれば確実に「無限ループが発生している」ということに気づくとは思いますが、「なぜ無限ループが発生しているのか」に関しては再帰関数では気づきづらいものだと思います。(ただこれに関しては過去の経験の話に直結しそうなので、深追いしないでおきましょう。)無限ループって致命的なバグでしょうか。ハマれば確実に気付くのであまり深刻な事態になることは少ない気がします
とりあえず、「安全かどうか」に関しては食い違いが大きいようなので、ひとまずこれについては置いておきましょうか。コードが短いことと簡潔であることは同じではないと思います。JSON.stringifyを使うにはその仕様をしっかりと理解する必要があるので、むしろコードとしては複雑化しています。余計なこと(toJSONなど)をされて悩むことにもなりかねません。
flatで代用できるということに関して深い意味はありません。サンプルコードがちょっと悪かったですね。実際、記載いただいたコードも再帰で書かれた関数はオブジェクトの配列に対してflatとして動作しますが、JSON.stringifyで書かれた関数はflatとして動作しません。
const array = [
{
name: "ユーザー", type: "フォルダ",
content: [ { name: "ぬこ.png", type: "ファイル", content: "猫の画像" } ],
},
{
name: "デスクトップ", type: "フォルダ",
content: [
{
name: "ログ保管庫", type: "フォルダ",
content: [
{ name: "20180304.log", type: "ファイル", content: "ごにょ" },
{ name: "20180305.log", type: "ファイル", content: "ごにょごにょ" },
{
name: "後で消す", type: "フォルダ",
content: [
{ name: "20180312.log", type: "ファイル", content: "ごにょごにょごにょ" },
{ name: "20180832.log", type: "ファイル", content: "ごにごにごにごに" },
],
},
],
},
{ name: "todo.txt", type: "ファイル", content: "今日の夕方、牛乳を買う。" },
],
},
];
fspaceさんの仰る一般的なオブジェクト指向の概念に、JavaScriptそのものの文化がどれだけ含まれているのだろう、というのが少し疑問ですね。条件分岐やループのために新しく関数を定義するというのは、オブジェクト指向(というか手続き型)ではあまり一般的ではないように思うので、そのレベルまで要求するのはやめた方がいいかなと。
最近のWEBフロントエンド開発ではむしろJSだけでなく、パッケージマネージャーを用いた開発が一般化していますし、それを否定してしまうと時代に逆行してしまうのでは・・・?と僕は思いますけどね。小さな処理に逐一パッケージを使用するJavaScriptの文化には反対派ですね。
MZではプラグイン設定でリンクを貼れるようなので、そこにGitHubのリンクを貼っておけばよさそうです。ただ、それぞれのプラグインがそれぞれの方法でトランスパイルするソースコードをまとめて管理するとなると、それもそれでなかなか面倒なものがあります。
なんというか、fspaceさんとは宗教的な違いがあるようですね・・・。おそらく、どうしても互いに譲れない部分がありそうです。
まあでも、記事の最後の方に書かれていた「私論として話さざるを得ない部分が多く」の部分はそういうことですよね。
そもそも論として、再帰関数を直で書こうがJSON.stringifyを使おうが、どんな処理の流れになるのかをしっかり分かっていないと使えないし書けないわけですよね。何もJSON.stringifyで再帰関数を書くことが悪いとは言い切れないと思うんですよ。
どちらの書き方にも気を付けるべきポイントはあるし、メリットもデメリットもあるんですから、コードを書く人間がその良し悪しをどう使い分けるかという話かと思いますけどね。
flatで代用できるということに関して深い意味はありません。サンプルコードがちょっと悪かったですね。
件のサンプルコードでは、単純に配列の展開しか行っていなかったので、同じ結果を得るためには実はflatでも出来るんだけどねっていう話だったんですが。
多分、array変数がこのように、オブジェクトパラメータから親子関係を作っているタイプのものなら真意が正しく伝わったのかなって感じがします。
fspaceさんの仰る一般的なオブジェクト指向の概念に、JavaScriptそのものの文化がどれだけ含まれているのだろう、というのが少し疑問ですね。
そもそもJavaScript自体、他の一般的なオブジェクト指向言語とは異なる文化の流れがあり、また配列や関数のメモリ上の扱いも特殊と言われています。
(例えば new Array(1) と new Array(999999999) で、実際に確保されるメモリは大差ないとか。C言語などでは大量の配列を使ってループを作るなんてメモリの無駄以外の何物でもないですが、JSではそもそも仕組みが違うので問題にならないという。)
なので、その辺りまで含めて「条件分岐やループのために新しく関数を定義するのは一般的ではない」としているのかな?と、思いました。
// let
let result;
if (conditions) {
result = "TRUE";
} else {
result = "FALSE";
}
// const #1
const check = conditions => {
if (conditions) {
return "TRUE";
} else {
return "FALSE";
}
};
const result = check(conditions);
// let
let sum = 0;
for (let i = 0; i < xs.length; i++) {
sum += xs[i];
}
// const #1
const rec = (xs, i, acc) => {
if (i < xs.length) {
return rec(xs, i + 1, acc + xs[i]);
} else {
return acc;
}
};
const sum = rec(xs, 0, 0);
結構、メソッドチェーンで毎回無名関数を使うのも、空の配列を作ってループを回すのも、GitHubで高スターを得ているJS/TSのOSSプロジェクトではよく見るんですけどね。
最近のWEBフロントエンド開発ではむしろJSだけでなく、パッケージマネージャーを用いた開発が一般化していますし、それを否定してしまうと時代に逆行してしまうのでは・・・?と僕は思いますけどね。
MZではプラグイン設定でリンクを貼れるようなので、そこにGitHubのリンクを貼っておけばよさそうです。
まあこのあたりも、「エディターが悪い」論ですね。
コードが短いことと簡潔であることは同じではないと思います。
JavaScript:console.log( $dataActors .slice(1) // または .filter(Boolean) .filter(({ classId }) => classId === 3) .map(({ nickname }) => nickname) );
sprite.x = 8 * Math.sin(2 * Math.PI * (Graphics.frameCount % 120) / 120);
sprite.y = 8 * Math.sin(4 * Math.PI * (Graphics.frameCount % 120) / 120);
まあこの場でJSの話で白熱してしまうと、いろんな人を置いてけぼりにしてしまうので ;^^)ただ、個人的には議論して考えることに意味があると思っていて、意見が合わずとも考えを述べることが重要かなと。もちろん、無理やり付き合わせることは本意ではありませんので、面倒であれば打ち切ってもらっても結構です。
極論を言ってしまえば、字が読めない人が文章を読んでも読めないとも言えます。下を見ればさらに下もいるし、上を見ればさらに上もいるわけです。加えて、簡潔であるかどうかは読み手の知識や技量にも依存する、と伝えておきたい。
あくまでここで示されているのは「読みやすいソースコードの指標」ですから、義務感を感じる必要はないと思います。そこからようやく世界を広げようと一歩踏み出してみたのに
ループといえば for だろう、と思って書いたらお前の書き方は稚拙だと馬鹿にされ
コアスクリプトにもそう書いてあるし、おまじないだと思って真似して var って書いたら邪悪だと罵られ
いやそこまでは言ってない、と思われるかもしれませんが
この手の議論を見かけるたびにそれに近い間口の狭さを感じなくもない。
「新しい事を学んだほうが、より楽ができるようになる」という考え方をするといいと思いますよ。もっとも、私にわからないからレガシーな書き方にしろとは言えないんでただの愚痴なんですけども。
「ただ一つだけの正解」っていうのは無いと思いますが、いろいろなやり方があると思います。ところで、ここで聞いていいものか微妙な気はするんですが
Graphics.frameCount の話、実はコレ違うんじゃないかとうすうす感じながらも
書いたらそれっぽく動いちゃったんで使ってるん箇所があるんですけど何を使うのが正解なんでしょう。
標準的な書き方、という基準そのものが進化する概念なのが難しいですね。そんななかで、「こうして書かれたものが標準的な書き方である」という基準が定まっていれば、読み手にどのような知識や技量が必要なのかをはっきりさせることが出来るんじゃないですかね。
スプライトの更新に使うなら強ち間違いではない、ということなんですかね。Graphics.frameCount を「使ってはいけない」のではなく、「誤用に気を付けるべき」というだけなので