27

私は依存性注入の目的を理解していると思いますが、それを行うために Guice のようなものが必要な理由がわかりません (もちろん、 Guice は必要ありませんが、それを使用することが有益である理由を意味します)。 )。次のような既存の (非 Guice) コードがあるとします。

public SomeBarFooerImplementation(Foo foo, Bar bar) {
    this.foo = foo;
    this.bar = bar;
}

public void fooThatBar() {
    foo.fooify(bar);
}

そして、おそらく私のmain()のどこかより高いレベルで、私は持っています:

public static void main(String[] args) {
    Foo foo = new SomeFooImplementation();
    Bar bar = new SomeBarImplementation();
    BarFooer barFooer = new SomeBarFooerImplementation(foo, bar);

    barFooer.fooThatBar();
}

これで、基本的に依存性注入の利点が得られましたね。より簡単なテスト可能性など? もちろん、必要に応じて main() を簡単に変更して、ハードコーディングする代わりに構成から実装クラス名を取得することもできます。

私が理解しているように、Guice で同じことを行うには、次のようにします。

public SomeModule extends AbstractModule {
    @Override
    protected void configure() {
        bind(Foo.class).to(SomeFooImplementation.class);
        bind(Bar.class).to(SomeBarImplementation.class);
        bind(BarFooer.class).to(SomeBarFooerImplementation.class);
    }
}

@Inject
public SomeBarFooerImplementation(Foo foo, Bar, bar) {
    this.foo = foo;
    this.bar = bar;
}

public static void main(String[] args) {
    Injector injector = Guice.createInjector(new SomeModule());
    Foo foo = injector.getInstance(Foo.class);

    barFooer.fooThatBar();
}

あれですか?私には、構文糖衣のように思えますが、特に有用な構文糖衣ではありません。また、「new XxxImplementation()」を main() で直接実行するのではなく、別のモジュールに分割することに何らかの利点がある場合は、とにかく Guice なしで簡単に実行できます。

そのため、非常に基本的なものが欠けているように感じます。Guice 方式の利点を教えてください。

前もって感謝します。

4

2 に答える 2

20

実際のアプリケーションや大規模なアプリケーションでは、コンポーネントのレベルは2つだけではありません(例のように)。10以上の場合があります。また、要件と依存関係は気まぐれに変わる可能性があります。

「手動でDI」を実行する場合、これは、すべてのコンポーネントへのすべてのパスとそれらの推移的な依存関係を手動で変更する必要があることを意味します。それはかなりの作業かもしれません。

「実際のDI」(つまり、Guice、Spring、CDI)を使用すると、影響を受ける1つまたは2つのコンポーネントと配線(ModuleGuice上)を変更するだけで済みます。

また、深くネストされたコンポーネントの一部が、他のコンポーネントによって呼び出される必要があるファクトリにあると想像してください。Guiceでは、を注入するだけで、Provider<Foo>それだけです。手作業で行う場合は、ファクトリの依存関係とそのインスタンス化をコード全体にドラッグする必要があります。

それはさらにいらいらします。

編集最後のポイントを明確にするために:画像あなたはいくつかの深くネストされたロジック(10以上のレベル)を持っています。下部にあるロジックは、実際の温度などの値に基づいてファクトリを作成します。「暖かい」場合はaCoolerが必要であり、「冷たい」場合はaが必要Heaterです。どちらにもインターフェースがありますTemperatureAdjustor。両方ともCoolerHeater仕事を成し遂げるために多くの異なる依存関係が必要です。

mainファクターのインスタンスタイプなので、作成して必要な場所に渡すことはできません。したがって、両方のファクトリの依存関係を必要な場所に渡すことになります。(「多くの依存関係」と「多くの依存関係」は「正気を保つには多すぎる」です)

Guiceのような「実際のDI」を使用AssistedInjectすると、依存関係の乱雑さを回避し、実際のビジネス価値(ここでは温度)のみを工場に提供して実行できます。工場の配線はモジュール内で行われます。

于 2012-10-19T16:45:46.647 に答える
2

手書きの DI は実際の DI です。

IOC コンテナの複雑さを考えるとき、それを使用する理由を正当化するために、より深く調べる必要があります。私は長い間アンチ IOC であり、クリーンで高速、きちんとハンドコーディングされた本物の DI を設計して実装することができました。しかし、コンテナは実装の標準化に役立ち、依存関係の式に新しい決定を追加するためのより構成ベースのメカニズムを提供するため、コンテナのアイデアには同意しませんでした。そして、他の誰かがすでにあなたのためにそれらを書いているので、手作業でコーディングするのに時間を費やす必要はありません.

多くの人は、大きなアプリではコンテナーを使用し、小さなアプリではハンド コードを使用すると言います。私は反対のことを言います。小さなアプリは、パフォーマンスがそれほど制限されていません。パッケージ化されたコンテナーを使用する実装速度を求めてください。最適化に多くの時間を費やす大規模なアプリでは、DI を手作業でコーディングすることを検討してください。

編集:ただし、IOCコンテナまたはハンドコーディングで追加させてください。作業中のアプリがどれほど単純であっても、インターフェースには常にDIとコードを使用してください。小さなアプリでも優れたコードを記述します。

于 2013-07-16T18:28:31.993 に答える