ノートの端の書き残し

UnityやらC#やら。設計が得意かもしれない。

DIContainerとMessagePipeでできる設計の話

まだ全然調査しきれてないので、ちょっと触った感じ、こういう認識でいいのかなぁ、というお話です。

VContainerについて

github.com light11.hatenadiary.com - VContainerとは、導入しやすい、わかりやすいDIコンテナです。
- DIコンテナとは、色んなとこから参照されうるクラス/インスタンスをまとめて管理して、ちょっと[Inject]とか書くだけでそこに入れてもらえる(わざわざsetメソッド的なものを書く必要が無い)仕組みです。
- DIコンテナという神がいるので、クラスの依存関係をこいつに任せることができます。
- 結果、MonoBehaviourはViewとしてのみ働き、ロジックは(物理演算とかは例外になっちゃうかもしれんけど……)非MonoBehaviourなクラスに書けて嬉しいです。

という認識。

DIコンテナを使用すると、Unityで qiita.com この記事で言うところのレベル4を実現することができます。
設計レベルは高ければいいというものでもない、というのは賛成ですが、
(「絶対的な答えなど無く、各々の状況に応じた最善を常に考えよ」という話なので、これは「設計レベルは高ければ高いほどいい」と言い切るよりもある意味厳しい結論と言えます)
ただ、個人的な感覚で言うと「MonoBehaviourはViewだけやってろ!」という思考は、一度に考えることを減らせて嬉しいことがほとんどじゃないかなと思います。
それを綺麗に実現できるならば、学習コストを考えても、多くのプロジェクトで導入を検討する価値は高いと思います。
まぁ「学習コスト」の中身は、ツールの使い方というよりも、それで何が嬉しいのかの理解の方が重いので、使い方がわかればOKという話では全然ないのが罠ですが……

MessagePipeについて

github.com qiita.com (↑わかりやすい!)
さて、Viewとその他(例えばPresenterとModel)の関係性はDIコンテナの導入で解決できたとします。
が、実際にコードを書いていくと全てを疎結合というのは無理だよな~という現実にブチ当たります。実体験では。
まぁ何でもかんでも疎結合にする必要も無いとは思いますが(めっちゃ自然な親子関係とか)、ただ、他クラスを参照するようなケースはできるだけ避けたいものです。数が多くなったり階層が深くなると見づらくて嫌でもありますしね。
これまでは例えばUniRxでIObservableだけ公開してイベントの通知のみを行うなどして、比較的緩やかな繋がりを実現していたと思われますが、そうは言ってもクラスやインターフェースのプロパティとしては参照しちゃってます。
私も、

public IObservable<T> OnClick => m_fooClass.OnClick;

こんなんで深いところのIObservableがViewとかModelの一番親のクラスまで伝って行く景色をよく見ました。
クソでかシーンになるとViewもModelも結構大きくなり、この作り方では参照の矢印がねずみ講のように伸びてしまいそう。
じゃあ各クラスに関して、「何を外に伝えうるのか」「何が外から伝わりうるのか」も切り分けて、それもDIしちゃおうぜ! という。
UniRxにもMessageBrokerという、シングルトンなSubjectを使ってイベントの通知ができるみたいな仕組みはあったので、それでいいことも多いとは思いますが。
でも、VContainerやZenjectを既に使っているならばとりあえず利用できそうなところで利用していいんじゃないかなぁと思います。
特に、AsyncなPub/Sub(特に特にAsyncなRequestHandler)がいいですね。なんかもう何でもできそうって感じ(雑)。

正直設計まだまだ甘ちゃんなので、全然違うわボケ! っていう可能性も大いにある気がしますが、そのときは教えてください!