マスク
コロナ禍が一旦落ち着いてやっとマスクから解放されたと思っていたらインフルエンザと花粉症で再びマスク生活に戻った皆さんこんにちは。ここ最近外を歩くとマスクをしている人の方が多い気がします。電車とかノーマスクで乗っていたらちょと視線を感じるし。
SOLID原則
個人でゲームを開発している分には開発した本人がメンテナンスを出来さえすればどんなコードでも構わないのでしょうが、チーム開発だったり、私みたいに作っている最中に仕様変更を繰り返すような人間には出来るだけSOLID原則に沿った設計で開発を進める方が、後々の作業のし易さに直結すると思います。
SOLID原則とはソフトウェアの拡張性や保守性を高めるために設計時に考慮すべき開発原則で、ネットで調べれば解説記事が数多く上がっていますし、私もこのブログで記事にしています。
SOLID原則の中では基本的に各クラスは一つの役割を担うべき(複数の機能を持たない)なので、設計時に機能を細分化して各クラスに実装しますが、とはいえメイン処理に該当するクラスでは各機能を担うクラスへ処理依頼を出したり、処理結果を取得したりする必要があり、どうしても各クラスを参照する密結合な実装になりがちです。
密結合な例
そうするとメイン処理側は参照している各機能クラスが全て実装された後でないと実装できないし、各機能クラスが更新される度に影響を考慮する必要となります。
この為、それらの問題点の回避策として各機能クラスへの参照は共通的なInterfaceを介して行うようにする、といったデザイン設計がとられる事が多いです。
そうすることでメイン処理側も各機能の実装を待たなくても良いですし、各機能クラスの更新や入れ替えといった作業にも耐えうることが出来ます。
Interfaceを利用した疎結合モデル
上の図のようにメイン処理側が参照する各機能クラスのInterfaceは外部から渡される形式とすればメイン処理と各機能クラスは完全な疎結合な状態になることができます。では、各機能クラスのインスタンスは誰が生成してメイン処理に渡してくれるのか?
そういった役目を担ってくれるのが「DIコンテナ」と呼ばれるフレームワークになります。
DIコンテナの利用
VContainer
DIコンテナはクラス間の密な依存関係を外部で一元管理して疎結合な関係を実現し、問題を解決します。
Unityでは「Extenject(旧 Zenject)」といったアセットが有名ですが、今回は「VContainer」というアセットを取り上げます。
VContainerはExtenjectと比較して軽量で、シンプル形式のAPIを使用するため実装がわかりやすく、且つ無料です。
GitHubにunitypackageがリリースされているので、そちらをダウンロードしてUnityのプロジェクト内に取り入れる事ができます。
Unityでは基本的にGameObjectにMonoBehaviourを継承したクラスをアタッチして処理の起点としますが、VContainerを使用することで、純粋なC# クラスのエントリポイントをつくることができます。
これによりMonoBehaviourとは切り離して純粋なロジックのみのクラスを実装でき、より依存性が低い設計モデルを構築する事ができます。
概要
VCointanerは以下の流れで使用します。
- ContainerBuilderを生成
- ContainerBuilderに使いたいクラスを登録
- ContainerBuilderからIObjectResolverを生成
- IObjectResolverを通して使いたいクラスを取得
これを先ほどの図を使って表すとこんな感じ
VContainerを使用した関係図
手順だけを見ると少し複雑でコードの量が増える気さえしますが、上の1~3の部分はそれを担うコンポーネントがシーン内に一つあればよく、IObjectResolverから受け取るクラス(上の図ならMainService)はContainerBuilder内で一様(Singleton)に保持されているのでどこから取得されても同じものを使用する事ができます。
これよりクラス間のデータの引き渡しもコンテナ内のクラス(上の図ならMainService)を介して行う事ができるので利便性が向上します。
Hello Worldは次回
概要の説明だけで記事が長くなってしまったので、具体的な使用例は次回紹介したいと思います。