5

私の同僚と私は、ここ数週間論争が続いています。そして、これについてコミュニティの意見を聞きたかったのです。

アプリケーションではguiceを使用します。このアプリケーションの UI 部分では、すべてのフィールドとコンポーネントを DI とカスタム アノテーション (ファクトリの配置としても知られています) を介してインスタンス化し、それらを buildUI メソッドに接続することを好みます。

それは次のようになります。

私のアプローチ:

@Inject
@PreConfigured(caption="foo", width="100%")
Label field;

private void buildUI() {
   this.addComponent(field);
}

データ バインディングと i18n の注釈もいくつか書きました。

私の同僚はこのようにしています:

彼のアプローチ:

private Label field;

private void buildUI() {
   field = new Label();
   field.setCaption("foo");
   field.setWidth("100%");
   this.addComponent(field);
}

ここのコードは非常に長くなる可能性があります。データ バインディングやその他のトピックを考慮すると、2 番目のコードはさらに長くなる可能性がありますが、私のアプローチは別の注釈にすぎません。

私の理由は次のとおりです。

  1. すべてのコンポーネントの動作と外観を構成する中心的な場所
  2. コードの再利用
  3. パフォーマンス - 長時間実行されるアプリケーションでは、コンポーネントの初期化コードが「ホット」になり、jit がさらに最適化を行います。
  4. より読みやすく。

彼の理由は次のとおりです。

  1. 可読性
  2. ビュー コードがあちこちに散らばっているわけではありません。
  3. クラスはDIなしで機能します
  4. 特に具象クラスが注入される場合、依存性注入の柔軟性は過大評価されています。
  5. DI を使用する唯一の有効な方法は、コンストラクター インジェクションです。

しかし、Fowler の記事もいくつか読みました。彼は、セッター インジェクション (フィールド インジェクションによる代用) は設計上の決定として不適切であると述べています。しかし、他のプロジェクトで再利用されないビューはどうでしょうか?

フィールド注入は悪い設計ですか? それとも、上記の他の方法はよりエレガントですか?

敬具クリスチャン

PS: 議論が単に意見に基づいて始まったことは知っていますが、それは長い間進行中の議論 (セッター対コンストラクター注入) であり、おそらく手放す価値があります。

4

3 に答える 3

3

免責事項:これは一種の主観的な質問であるため、個人的な好みに基づいて、この回答で主観的な主張も行います。ここに私の2セントがあります:

どちらのアプローチも私には悪く見えます。

あなたのは悪いです:

  • モジュールにすべてのバインディングがあります。特に多くの画面がある場合、このモジュールがどれだけ大きくなるかを考えてください。これの保守性への影響について考えてみてください。単一の画面を変更したいプログラマーは、

    1- Know the DI framework
    2- Find the module where the bindings for this screen are defined.
    3- Scroll down to find the binding.
    4- Make the change in the module, maybe also in the screen.
    5- Commit changes for the module class, maybe also for the screen class.
    
  • DI を使用するということは、リフレクションを使用することを意味し、使用しない場合よりも遅くなります。

  • コードをサードパーティ コード (DI フレームワーク) に依存させる
  • レイアウトの一部はまだ画面にハードコーディングされており (コンテナー ビューとは何か、それらには何が含まれているか)、一部は別のモジュールにあります。単一責任の原則は破られています。
  • 注釈が「汚い」: 現在、ソース ファイルは 2 つの異なる言語で書かれています。可読性が低く、自動コード分析ツールを使用するときに問題が発生する可能性もあります。
  • 単体テストを書くのは難しいです (そして、テストは DI フレームワークを使用して実行する必要がありますが、これは悪いことであり、多くのテストがある場合は特に遅くなります)。

あなたの同僚のアプローチには、ハードな依存関係が含まれているため、もちろん欠陥があります。ただし、これは画面には許容される場合があります。DI は大きなもの (パーサー実装を含むサービスの注入、コントローラー、daos、ロガーの注入など) には問題ないと思いますが、ビューには使用せず、むしろコンストラクター注入に固執したいと思います。したがって、(Android では) xml でビューを定義し、Activity クラスでビュー コントローラーの部分をコーディングするだけです。これが本来の方法です。

于 2013-09-18T14:08:56.560 に答える
1

あなたの質問は StackOverflow にはあまり適していないと思いますが (FAQ を参照してください)、それについての私の考えを紹介できます。

このプロジェクトですでに DI を使用しているように見えるので、この問題であなたの考えを支持します。それが提供する機能を使用しないのはなぜですか?

あなたの理由に対する私の発言:

  1. 可能であれば、すべての構成に Java コードを使用することを好みます (簡単にリファクタリングできるため)。Javaコードが冗長すぎる場合は、注釈を好みます(これはあなたの場合です)。xml/yaml/その他のマークアップ言語構成を避けるために何でもします。
  2. 多くの定型コードを簡潔で読みやすい注釈に単純化する注釈を実際に再利用できます。ハードコーディングされた値は再利用できませんが、再利用性はここでは適用できません
  3. コードのベンチマークは行いませんでしたが (コードベースがないため)、注釈を使用するとリフレクションが発生することが多く、単にセッターを呼び出すよりも明らかに遅くなります。なのでこれが性能のボトルネックになったら反射が関係する部分をどうするか頭を悩ませると思います
  4. 絶対。あなたの例を彼の例と比較してください。正気な人は、構文でいっぱいの 4 行のコードを読むほうが読みやすいとは言いません。@PreConfigured(caption="foo", width="100%")

彼のポイント:

  1. で説明しました4.
  2. 彼は「あちこちに散らばっている」とはどういう意味ですか? あなたの場合、注釈は常にフィールドにありますが、プログラムで初期化すると、コードはどこにでもあります。それが散らかっています。
  3. すでに Guice を使用している場合、DI を使用しないことには意味がありません。彼は DI に問題がありますか?
  4. これは「名指し」のようなものです。意味がありません。ポール・グラハムが書いたこのエッセイを彼に見せてください。
  5. 次に、20 個のフィールドを持つオブジェクトを考えてみましょう。もちろん、20 個のフィールドを持つことはすでにコードの臭いですが、4 ~ 5 個のパラメーターを超えるものは醜いです。private個人的には、リフレクションでフィールドを改ざんする必要がなく、8 ~ 10 個のパラメーターを持つコンストラクターも必要ないため、セッター インジェクションを好みます。不変オブジェクトが必要な場合はBuilderパターンを使用でき、シングルトンが必要な場合は、Spring (Guice にも同じ概念があると思います) のシングルトン スコープで十分です。ところで、これは常識です。それが唯一の有効な方法である場合、他に方法はありませんよね?
于 2013-09-18T12:37:01.157 に答える