依存関係の注入により、UIの膨大な数のインターフェイスを回避する方法


9

問題
私は最近、シングルトンが悪いことと、依存性注入(「インターフェースを使用する」と理解しています)がどのように優れているかについて、多くのことを読みました。コールバック/インターフェース/ DIを使用してこの一部を実装し、インターフェース分離の原則に準拠した場合、結局は混乱しました。

基本的にそのすべての子の依存関係を組み合わせたUI親の依存関係。したがって、UI要素が階層の上位にあるほど、そのコンストラクターは肥大化していました。

UI階層の最上位にあるのはApplicationクラスで、現在の選択に関する情報と、変更を反映する必要のある3Dモデルへの参照を保持していました。アプリケーションクラスは8つのインターフェイスを実装していましたが、これは製品(/インターフェイス)の5分の1に過ぎません。

私は現在、現在の選択を保持するシングルトンと、自分自身を更新する機能を持つUI要素を使用しています。この関数は、UIツリーとUI要素を細流化し、必要に応じて現在の選択シングルトンにアクセスします。コードはこのように私にはきれいに見えます。

質問
このプロジェクトにはシングルトンが適切でしょうか?
そうでない場合、私の考えやDIの実装に根本的な欠陥があり、それが非常に煩雑になりますか?

プロジェクトに関する追加情報
タイプ:ベルとホイッスル付きのアパートメントのショッピングバスケット
サイズ:コードとUIに2か月/月
メンテナンス:実行中の更新はありませんが、後で「バージョン2.0」になる可能性があります
環境:エンティティを使用するUnityでC#を使用コンポーネントシステム

ほとんどすべての場合、ユーザーの操作によっていくつかのアクションがトリガーされます。たとえば、ユーザーがアイテムを選択したとき

  • そのアイテムとその説明を表示するUIパーツを更新する必要があります。このため、価格を計算するために、3Dモデルから情報を取得する必要もあります。
  • UIをさらに上に行くと、全体の合計価格を更新する必要があります
  • 3dモデルのクラスの対応する関数を呼び出して、そこに変更を表示する必要があります

DIは、単にインターフェイスの使用について、それは...球を試験ユニットに特に有用である結石アウトスワップする能力であるれていない
ロビーディー

1
また、シングルトンが望ましい解決策であるという問題はまだ見ていません。人々が常に述べるように見える標準的な例はログライターですが、ここでもいくつかの異なるログ(エラー、デバッグなど)に書き込みたい場合があります。
ロビーディー

@RobbieDeeはい、DIはそれ以上のものですが、インターフェイスの使用がDIではない状況はわかりません。そして、シングルトンが好ましい解決策ではない場合-私もこれを想定しています-なぜ好ましい解決策がそれほど厄介なのですか?それが私の主な質問ですが、時々一般的なルールが適用されないので、私はそれを開いたままにしたかったです。
R.シュミッツ

インターフェース-コンクリーションの配置は、モックフレームワークの機能でもあります。彼らはオブジェクト指向の言語で数十年も過ごしてきました...
ロビーディー

あなたの言い分はわかりません。
R.シュミッツ

回答:


4

問題は症状ではなく、解決策だと思います。

私は最近、シングルトンが悪いこと、および依存性注入(「インターフェースを使用する」と理解している)がどのように優れているかについて、多くのことを読みました。コールバック/インターフェース/ DIを使用してこの一部を実装し、インターフェース分離の原則に準拠した場合、結局は混乱しました。

問題を探す解決策。それと誤解はおそらくあなたのデザインを壊しています。DIとシングルトンの異なる概念かどうかについて、このSOの質問を読みましたか?私はそれを単にシングルトンをラップするものとして読んだので、クライアントはシングルトンを扱う必要がありません。それはちょうど良い古いカプセル化です。それはその場だと思います。


UI要素の階層が上に行くほど、そのコンストラクターは肥大化しました。

最初に小さいビットを構築してから、それらを所属するもののコンストラクターに渡し、その大きいものを次の大きいもののコンストラクターに渡します...

複雑な構造の問題がある場合は、ファクトリまたはビルダーパターンを使用してください。結論としては、他のクラスをきちんと、きれいに、理解しやすくするために、独自のクラスに組み込まれた複雑な構造があります。


アプリケーションクラスは8つのインターフェイスを実装していましたが、これは製品(/インターフェイス)の5分の1に過ぎません。

これは拡張性がないように聞こえます。コアデザインが欠けており、すべてが上から詰め込まれています。さらにボトムアップな構造、構成、継承が行われているはずです。

あなたのデザインは「トップヘビー」かしら。1つのクラスをすべて、またはそれが可能なものにしようとしているようです。また、ビジネスドメインクラスではなくUIクラスであるため、懸念の分離について本当に不思議に思います。

デザインを最初から見直して、より複雑な、または異なるカテゴリーの制作を行うために構築できる、堅固で基本的な製品の抽象化があることを確認してください。次に、これらのもののカスタムコレクションを用意して、「コレクションレベル」機能をどこかに置くことができるようにします。


...変更を反映する必要がある3Dモデル。

これの多くはカスタムコレクションクラスに適合します。深さと複雑さのために、それ自体が独立したクラス構造になることもあります。これら2つは相互に排他的ではありません。

ビジターパターンについてお読みください。これは、機能のチャック全体をさまざまなタイプに抽象的に配線するという考えです。


設計とDI

これまでに行う依存性注入の90%は、コンストラクターのパラメーターの受け渡しです。だから本を書いたクィーは言う。クラスを適切に設計し、DIコンテナーを使用する必要があるという漠然とした概念で思考プロセスを汚染しないようにします。あなたがそれを必要とするなら、あなたのデザインはいわばそれをあなたに提案します。


アパートショッピングドメインのモデリングに焦点を当てます。

ジェシカシンプソンのデザインへのアプローチは避けてください

以下は間違っています:

  • インターフェイスを使用することになっています
  • シングルトンを使うつもりはない
  • DIが必要です(それが何であれ)
  • 継承ではなく構成を使用することになっています
  • 相続を避けることになっている
  • パターンを使用する必要があります

私は使用したすべてのシングルトンを削除しようとしましたが、あなたが言ったことのいくつかは多かれ少なかれ自動的に起こりました。残りの部分も非常に理にかなっているので、アドバイスを読んでビジターパターンなどを読み上げます。
R.シュミッツ2016年

ただ一点、私はここに助け吸血鬼になろうとしないんだけど、それがあったの一種元の質問の一部:一般的なコンセンサスは、(それが正当な理由に基づいている)あなたが実際に想定していないということのようですシングルトンを使用します。あなたは「シングルトンを使うつもりはない」は間違っていると書いています-どのような状況でそれを使うのが適切でしょうか?
R.シュミッツ2016年

私が言っているのは、「状況次第」です。格言が文字通りかなり取られているのをよく目にします。
レーダーボブ2016年

3

「階級制」は少々赤旗です。仮説:5つのウィジェットがあるWebページ。このページはウィジェットの祖先ではありません。これらのウィジェットへの参照を保持する場合があります。しかし、それは祖先ではありません。クラス階層の代わりに、コンポジションの使用を検討してください。5つのウィジェットはそれぞれ、他のウィジェットやトップページを参照することなく、独自に構築することができます。トップページは、基本的なページを作成し、それに渡されるウィジェットオブジェクト(コレクション)をレイアウトするのに十分な情報を使用して作成されます。ページはレイアウトなどを担当しますが、ウィジェットの構築とロジックは担当しません。

コンポジションを使用すると、DIはあなたの親友です。DIを使用すると、DIで定義したバージョンまたはウィジェットタイプに各ウィジェットを交換できます。ウィジェットの構築はDIに取り込まれ、トップページとは別です。おそらく、コレクションの構成もDIで定義できます。トップページは、渡されたウィジェットに基づいて、必要に応じてレイアウトを実行します。トップページのコンストラクタを変更する必要はありません。トップページは、ウィジェットのレイアウトを実行し、定義されたインターフェースに基づいてウィジェットとの間で情報を渡すためのロジックのみを必要とします。

構成のチェーンを上下にリスナーを渡す代わりに、それを必要とするウィジェットにリスナーのコレクションを注入します。コレクションをパブリッシャーに挿入して、コレクションにパブリッシュできるようにします。コレクションにリスナーを追加できるように、コレクションをリスナーに注入します。コレクションは、構成のチェーン内のすべてのオブジェクトを横断します。


申し訳ありませんが、「クラス階層」はここでは不適切な表現です。実際にはクラス階層ではなく、UI階層でした。「ウィジェット」はアプリケーションクラスのサブクラスではありませんが、「ページ」はUI更新を公開するためにそれらへの参照を保持します。この構造で非常にテスト可能でしたが、特にコンストラクターに多くのオーバーヘッドがあり、(UI)子の多くのリスナーを渡しただけでした。
R.シュミッツ

@ R.Schmitz:オーバーヘッドは問題でしたか?UIが遅く、説明したデザインのせいでしたか?
ロバートハーベイ

@ R.Schmitz「たくさんのリスナーを引き継ぐ」について詳しく説明していただけますか?たぶん、C#でのDIの経験は少ないかもしれませんが、適切な設計では(少なくともコンストラクターでは)不要であることがわかります。
Katana314

@RobertHarveyパフォーマンスの低下はまったくありません。読みやすさだけが重要です。
R.シュミッツ

@ Katana314たとえば、アイテムが追加された場合、3dmodelは更新する必要があり、どの製品カテゴリにも属していないため、追加/削除/変更されているアイテムをリッスンするアプリケーションクラスで参照されます。結局のところ、それはすべての製品カテゴリでほぼ同じです。他のUIパーツも反応(およびリッスン)しますが、3dmodel参照と実際のデータ(これも更新されます)があるため、メッセージは先頭に移動する必要があります。
R.シュミッツ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.