依存性注入法、デメタ法とグローバル状態(シングルトンはグローバルとみなされます)について2つの素晴らしいビデオ(thisとthis)を見ました。依存関係注入法+デメテルの法則+ロガー/アサート
私は基本的な考え方があると思いますが、私のライブラリにはすでにシングルトンクラスがいくつかあります。しかし、私がテスト可能で「うまく設計された」コードや「あまり結合されていない」コードが必要な場合は、DIとLoDを使用する必要があります。これはもちろん、呼び出し側が実装ではなく、少なくともテストの観点からはグローバルなものへの依存性が悪いため、(設計パターンとしての)シングルトンは悪いことです。
もっと具体的には、サードパーティの大きなライブラリを使用せずに単純なゲームエンジンを構築しています。つまり、プラットフォーム固有の低レベルのコードでも作業する必要があります。
もっと具体的にしましょう。私はライブラリのVector2クラスを持っている数学のセクションを持っています。その機能の1つに対して無効なデータが入力された場合、「アサートをスローする」ことができます。または、エラーとしてログに記録することができます。または両方。今まではSingleton<Logger>
を使用していたので、どこにでもアクセスできました。
しかし、私はこれらのことを使用すべきではなく、DIがこれらの問題を解決することに同意します。例えば。ロガーがまだ初期化されていない場合はどうなりますか?テスト用のダミーロガーが必要な場合はどうすればよいですか?そういうわけで...(LoggerクラスやAssertクラスのような)これらのケースでは何をお勧めしますか?
また、LoDにはオブジェクトのアクセサ(getObjectA()->getObjectB()->doSomething()
など)を使用しないでください。代わりに、それらを関数/コンストラクタのパラメータとして渡します。すべてのテスト(デバッグ)を簡単にすることはできますが、これらの機能をスキップするのは苦労かもしれません。
Unityエンジンの例を考えてみましょう。 GameObjectには、そのオブジェクトからコンポーネントを取得するメソッドがあります。例えば。私は手動で私のオブジェクトを変換したい場合、私は、「オブジェクトゲッター」、このような何かを呼び出すために選択の余地がない:
this.GetComponent<Transform>().SetPosition(...);
これはのLoDに反しているが、それはないですか?
ありがとうございました。私は既にあなたが上記の "コレクションクラス"を作成しました。また、私は十分に具体的ではありませんでした。もちろん、低レベルのプラットフォームコードを直接使用するのではなく、代わりに抽象クラス/インタフェースを使用しています。 – csisy