Imaginantia

思ったことを書きます

雑記 良い設計

お久しぶりです。まぁアレ書いたし最近の近況は Twitter に ワイワイ 書いてるのであまり珍しさはない気もしますが。

某がやっと着地できたので安心しております。が、その過程で色々と思うことがあったので (昔から思うことではありますが) 言語化しておきます。

「良い設計」とは何か。ここでは基本的にプログラムのインターフェースの話をしますが、まぁユーザーインターフェースとかも含みます。

 

結論から言うと、設計の良さというのは「目的の空間をまるごと綺麗に反映していること」だと思っています。一対一対応、過不足の無さ、そこに余計なものがないこと。

つまり「やりたいことに対し、丁度綺麗にそれが収まる枠があること」「できないことに対し、それが自ずとできない仕組みになっていること」です。

で、まぁ抽象的なことを言うよりは具体的な話をしたほうがいいと思うので、します。

よくわからない PlayMaker

PlayMaker くんの Set Material Float アクションには「GameObject」「Material Index」「Material」を指定することができます。

この時点でおかしいはずなのです

  • (MeshRenderer がついた) GameObject と Material Index があれば、Material 指定が一応行えるはず。
  • 単体で Material を渡すことでも、Material 指定が行えるはず。

何故か2通りの方法で Material を指定できることになっていますが、ではどちらが使われるのか?というと判断が付きません。

実際にはどうやら「Material」の方はほぼ無視されているっぽい (リファレンスには名前すら乗っていない) んですが、微妙に挙動が変わるという点もあってよくわかりません。

インターフェースから挙動がわからないのは悪いことです。

 

さらに言えば GameObject / Material Index の組で Material を指定するのも難しいところです。これは Unity が諸条件で Material の instancing を行う為、うっかり Material を直接指定すると死ぬのを防ぐ為なのでしょう。

でもそのせいで過剰な複雑性が取り入れられているわけです。Material に値を入れたいという気持ちに GameObject は一切関係ありません。シーン上にまだ配置していないオブジェクトの Material を弄りたいこともあります。

本当に欲しいものは「m = gameObject.GetComponent<MeshRenderer>().materials[index]; m.SetFloat(name, value);」で、それ以上でもそれ以下でもないはずです。

そしてここに書いてあるとおり、行うべき適切な分離は「マテリアルの取得」「マテリアルへの値設定」です。コードのありがたみがわかりますね。

人々が愚かだからと言って勝手によくわからない仕組みをつけちゃうのは人の愚かさを加速させるだけです。

PlayMaker はマジで無駄な「隠蔽」をしようとしてよくわからない仕様を大量に埋め込んでいる気がします…。Every Frame もよくわからん。

 

誰も複雑なシステムなんて求めていません。

なのでこういう機能は便利だからつけよう!でつけると死にます

必要なのは「システムの立ち位置や設計思想が明らかな状態で、その通りにシステムが動くこと」です。

即ちまず「動作モデル」というものが明らかであり、それに則って「その通りの実装を置いておく」だけでいいのです。

PlayMaker はほんとよくわかりません。未だに実行順を理解していません。

あれは実際難しい (興味深い難しさではなく、人類は愚かタイプの難しさ) ので、わからないという人は一切気負う必要ないと思います。

コード書いてるほうがよっぽどマシです。VRChat も言ってるし。

エンジニアリングとは

そんな中どうしてもそれを使わなきゃいけないシチュエーションがあります。ありました。

わけのわからないものに立ち向かうにはどうすれば良いか。

観察 (observation, 観測) です。

観察と言っても当然「インターフェースを見るだけ」じゃないですよ。観るべきは挙動です。

つまり1機能が、具体的にどう動いているかを観る。そしてそれに沿って動作を表すモデルを立てる。

複数機能をつなげたときにどう動くかを観る。それに沿ってモデルを立てる。

仮説と検証です。未知のものにはこれがもっとも有効です。

「これを如何にうまくやるか」がエンジニアリング能力だと私は思っています。ちなみにデバッグも同じような話です。

なので例えば、エンジニアリングがちゃんとできるなら、触ったことのない言語であってもある程度すぐ触れるようになるんです。

 

完璧に相手を理解する必要がない、というのがポイントです。大体の人は C++ をわかっていませんし、それをみんな公言しています。

わかってなくとも、わかる領域があり (= 自分の中にモデルがあり)、それで目的を果たせるのなら、それでいいのです。

だから私は PlayMaker のアクションの動作順はぶっちゃけよくわかっていませんが、怖そうなら State を増やして強制的に順序実行させることで解決したりしています。

PlayMaker 的には美しくないかもしれませんが、よくわからん動作モデルの PlayMaker が悪いし、まぁそれで誰も困らないのでそれでいいのです。

 

「必要なときに学ぶ」 という姿勢はいわゆる「本を読んで勉強する」と相反するようなところがある気がします。実際私は本を読まなくなりました。

しかしこれだと必要になったときにしか知識が増えなくて、大抵の場合、それでは遅いのです。

だから、知識を増やすフェーズというのはエンジニアリングとは別として、ある意味で「楽しみ」として、色々触っていくのが良いのだと思います。

ぱらぱらっとめくってこんなのあるんだ、こんなことできるんだーを知っておくだけでも後々役立つものです。かなり

ノードとコード

話を戻しますが、「コード書いたほうがマシ」と言う点に対し、「ではノードはどうなのか?」という意見を仮想的に想定しました。

で、じゃあこれをどう評価するか?というと、当然「設計として妥当かどうか」を考えることになります。つまり「やりたいことを直接的に表現できているのはどちらか?」です。

コードは、文字という媒体を頼った表現です。文字として記されていることを読む必要があります。しかし、その分情報を圧縮することができています。それはテキストエディタによる編集が容易であることにも繋がります。

ノードは値や制御の流れが可視化されているのでそれをわざわざ「読む」必要がありません。でも複雑なことをやろうとすると「無駄に可視化された領域」が出てきてしまいます。コードだと複数の紐を束ねたり、「テレポート」させることは容易なのに、そういう「整理」などがノードには難しいイメージです。

ぶっちゃけどっちも完璧には遠いです。だけど後者は根本的に操作速度がボトルネックになってしまう分、前者で慣れてしまって超速で編集できたほうが色々と効率は良いんじゃないかな、と思います。

私はコードがわからないという人の気持ちが多分正直わかっていませんが、多分それは「モデル形成」という中間形式を置いてないからではないか、と推測しています…。

昔は「文法」という概念がわからないからなのかな?と思っていたけど、さすがにそれは人類を舐めすぎかな?

完璧な目的空間

表現したい空間というのは様々ですが、じゃあそれを「ぴったり表現する方法があるか」というと結構難しいです。

例えば、「足して5を越えない自然数の組」っていう空間が欲しいとします (実際そういうときはよくあります)。よくあるプログラミング言語だとまず int x, y を置くことはできるけど「足して5を越えない」という制約が表現できません。

変数の値に関する制約を型と言いますが (?) (まぁ int は x が整数だよっていう制約として捉えられる)、実際に「x + y < 5 は正しいよ」っていう制約を表現できる言語もあります。そういうものが望ましいはずです。

が、現実の多くの言語はそこまでちゃんとしてはいません。もうこれはしょうがないです。

だけど、できるだけ制約をうまくインターフェースとして表現するという努力は当然怠るべきではありません。

「X か Y のどちらかを指定できる」というときに f(int X, int Y) (使わないやつには -1 を指定する) みたいにするのはよくありません。何故ならどちらも指定できるため、制約を表現できていないからです。

f_X(int X), f_Y(int Y) のほうが正しいです。ね?

C# はオブジェクトに null が渡せるのでちょっとその辺も厄介ですよね。「値が絶対に入っていることを保証したい」ようなことがちょっとだけやりにくい。

しょうがないからみんな assert とか exception を書くんですが、本当に欲しかったものは「制約を表現する方法」なはず。それがインターフェースとして現れていたら尚良い。

なんかあまりにも普遍的な話すぎて書くの飽きてきましたけど、世の中の人類マジで設計できんのやなあという気持ちでした。

もっと聞きたい人は直接聞いてください。これの話は文字通り無限にできるので。

まとめ

プログラム書きたくない~