5

ドキュメントで見逃したのかもしれませんが、「ヘルパーオブジェクト」をどのように処理すればよいのでしょうか?

コード例:

public Path dijkstra(Node startNode, Node endNode) {
    Set<Node> nodesToInspect = new HashSet<Node>();  // should this Object be injected?
    Path path = new Path();  // and this one?

    while (!nodesToInspect.isEmpty()) {
        // some logic like:
        path.add(currentNode);

    }

    return path;
}

すべてを注入する必要がありますか、それともアルゴリズムが必要なものを最もよく「知っている」とある時点で言う必要がありますか? すべての「新しい」を排除しようとする必要がありますか? または、HashSet、ArrayList などの API クラスなど、いくつかのオブジェクトの作成に問題はありませんか。

4

3 に答える 3

2

単純なものを依存性注入に置き換える前に、 「なぜ私はこれをしているのだろうか?」newと自問する必要があります。...「それにはどのような本当の利点がありますか?」. 答えが「わからない」または「何もない」である場合は、そうすべきではありません。

この場合、サンプル コードの最初のケースで DI を使用しても、実際の利点はわかりません。内部セットがどのように表現されているかを知るために、そのメソッドの外に何も必要はありません...またはそれが存在することさえ知る必要はありません。

あなたが尋ねるべきもう一つの質問は、目標を達成するためのより簡単で明白な方法があるかどうかです. たとえば、path変数に DI を使用する (最も可能性の高い) 目的は、アプリケーションが別のPathクラスを使用できるようにすることです。ただし、これを行う簡単な方法は、明示的なパラメーターとしてPathインスタンスをメソッドに渡すことです。dijkstraオーバーロードを使用して、これをより美味しくすることもできます。例えば

public Path dijkstra(Node startNode, Node endNode) {
    return dijkstra(startNode, endNode, new Path());
}

public Path dijkstra(Node startNode, Node endNode, Path path) {
    ...
}

最後に考慮すべきことは、DI (Java の場合) にはある程度のリフレクションが含まれており、newファクトリ オブジェクト/メソッドを使用する従来のアプローチよりもコストがかかることは避けられないということです。DI の追加の柔軟性が必要ない場合は、料金を支払うべきではありません。


あなたが参照している 2 つの変数がローカル変数であることに気付きました。ローカル変数を挿入できるDIフレームワークを知りません...

于 2012-12-19T02:19:03.410 に答える
1

「頻繁に変更されるものをカプセル化する」または「変化するものをカプセル化する」という設計原則を思い出してください。エンジニアとして、何が変更される可能性があるかを最もよく知っているのはあなたです。2012 年を次の 10 年まで存続するコードにハードコーディングしたくないでしょうが、「Math.PI」を構成設定にしたくないでしょう。触れる必要はありません。

その原則は、依存性注入によって変わりません。

Dijkstra の例のように、1 つのアルゴリズムを作成していて、必要な Set の実装を知っていますか? オブジェクトを自分で作成します。しかし、あなたの同僚があなたのユースケースに最適化された Set の素晴らしい新しい実装を間もなく提供する場合、またはベンチマーク用にさまざまなコレクションの実装を試している場合はどうなるでしょうか? 粉塵が落ち着くまでプロバイダーを注入したくなるかもしれません。コレクションの場合はそうではありませんが、「ヘルパー オブジェクト」と考えられる同様の使い捨てオブジェクトの場合はより可能性が高くなります。

実行時に異なる可能性があるさまざまなタイプの CreditCardAuthService から選択するとします。インジェクションに最適なケースです。しかし、5 年間の契約に署名していて、それよりずっと前にコードが交換されることがわかっている場合はどうでしょうか? おそらく、1 つのサービスにハードコーディングする方が理にかなっています。しかし、いくつかの単体テストまたは統合テストを作成する必要があり、実際のクレジット カード バックエンドを使用したくありません。依存性注入に戻ります。

覚えておいてください: コードは順応性があります。いつか、ハードコードされた HashSet を取り除いて別のものに置き換える必要があると判断するかもしれませんが、それは問題ありません。または、Guice で制御できるようにサービスを頻繁に変更する必要があることがわかり、コンストラクターのパラメーターとバインディングを追加して、1 日で終了することもあるでしょう。あまり気にしないでください。ハンマーを持っているからといって、すべての問題がProvider<WoodFasteningService>.

于 2012-12-19T06:33:01.057 に答える
0

DIを使用するときは、可能な限り「新しい」ものを避けたいと思います。コンテナの外部で作成するすべてのインスタンス(たとえば、guiceインジェクター)は、インジェクションを使用するようにリファクタリングできません(「Path」インスタンスが構成によってインジェクションされた文字列「root」を取得する必要がある場合はどうなりますか...また、これらのオブジェクトでインターセプターを使用することもできません。したがって、純粋なEntity-Pojoでない限り、私は常にプロバイド/インジェクトを使用します。これは、制御(ハリウッド)パターンとテスト容易性の反転の一部でもあります...パスをモックするか、Junitで設定する必要がある場合はどうなりますか?それら(この場合はプロバイダー)を注入すると、後で具体的な実装を簡単に切り替えることができます。

于 2012-12-19T15:12:21.210 に答える