web-dev-qa-db-ja.com

Poor ManのDependency Injectionは、レガシーアプリケーションにテスト容易性を導入する良い方法ですか?

昨年、Dependency InjectionとIOCコンテナーを使用して新しいシステムを作成しました。これにより、DIについて多くのことを学びました!

ただし、概念と適切なパターンを学習した後でも、コードを分離し、IOCコンテナをレガシーアプリケーションに導入することは難しいと思います。アプリケーションは、実際の実装ができるほど十分に大きい価値が理解され、時間が与えられたとしても、このようなことのために時間を与えられたのは誰ですか??

もちろん、目標はユニットテストをビジネスロジックにもたらすことです!
テスト防止データベースコールと絡み合うビジネスロジック。

私は記事を読み、 このLos Techies記事 で説明されているように、Poor ManのDependency Injectionの危険性を理解しています。私はそれが本当に何も切り離さないことを理解しています。
実装には新しい依存関係が必要であるため、システム全体のリファクタリングが多く発生する可能性があることを理解しています。サイズの大きな新しいプロジェクトでは使用しないでください。

質問:Poor ManのDIを使用して、レガシーアプリケーションにテスト容易性を導入して、ボールローリング?

さらに、Poor ManのDIを真の依存性注入への草の根アプローチとして使用することは、原則の必要性と利点を教育するための貴重な方法ですか?

データベース呼び出しの依存関係を持つメソッドをリファクタリングし、インターフェイスの呼び出しを抽象化できますか?モック実装がコンストラクタオーバーロードを介して渡される可能性があるので、単にその抽象化があれば、そのメソッドはテスト可能になります。

今後、取り組みが支持者を獲得したら、プロジェクトを更新してIOCコンテナを実装すると、抽象化を取り入れたコンストラクタがそこに登場します。

14
Airn5475

NerdDinnerにおけるPoor Man's Injectionに対する批判は、DIコンテナーを使用するかどうかに関係なく、クラスを正しく設定することに関係しています

記事では、彼らはそれを述べています

public class SearchController : Controller {

    IDinnerRepository dinnerRepository;

    public SearchController() : this(new DinnerRepository()) { }

    public SearchController(IDinnerRepository repository) {
        dinnerRepository = repository;
    }
}

最初のコンストラクタはクラスを構築するための便利なフォールバックメカニズムを提供しますが、DinnerRepositoryへの緊密にバインドされた依存関係も作成するため、これは正しくありません。

もちろん、Los Techiesが示唆しているように、DIコンテナーを追加するのが正しい方法ではなく、問題のあるコンストラクターを削除することです

public class SearchController : Controller 
{
    IDinnerRepository dinnerRepository;

    public SearchController(IDinnerRepository repository) {
        dinnerRepository = repository;
    }
}

残りのクラスの依存関係が適切に反転されました。これで、これらの依存関係を自由に挿入できます。

25
Robert Harvey

ここでは、「貧しい人のDI」とは何かについて誤った仮定をしています。

まだカップリングを作成する「ショートカット」コンストラクタを持つクラスを作成することはできません貧乏人のDI。

コンテナを使用せず、すべてのインジェクションとマッピングを手動で作成すると、is貧乏人のDI。

「貧乏人のDI」という言葉は、悪いことのように聞こえます。そのため、- 最近は「純粋なDI」という用語が推奨されます これはより肯定的に聞こえ、実際にはプロセスをより正確に説明します。

貧しい人の純粋なDIを使用して既存のアプリにDIを導入することは絶対に問題がないだけでなく、多くの新しいアプリケーションでDIを使用する有効な方法でもあります。そして、あなたが言うように、IoCコンテナーの「魔法」に責任を負う前に、誰もが少なくとも1つのプロジェクトで純粋なDIを使用して、DIの仕組みを本当に理解する必要があります。

15
David Arno

レガシーチーム/コードベースのParagidmシフトは非常に危険です。

「改善」をレガシーコードに提案し、「レガシー」チームのプログラマーあなた「彼らはそれを間違った」とあなたにあなたの/会社との残りの時間の敵

DIフレームワークをハンマーとして使用してすべての爪を粉砕すると、すべての場合において、レガシーコードがより良くなるだけではありません。個人的にも非常に危険です。

テストケースで使用できるような非常に限られたケースでも、これらのテストケースは「非標準」および「外部」のコードになり、せいぜい@Ignoreそれらが壊れるか悪化すると、管理に最も強い影響力を持つレガシープログラマーから絶えず不満を感じ、この「ユニットテストの無駄な時間」のすべてがあなただけに非難されて「正しく」書き直されます。

DIフレームワーク、または「純粋なDI」の概念を基幹業務アプリに導入すると、管理者、チーム、および主な開発者のスポンサーがいなければ、巨大なレガシーコードベースははるかに少なくなります。チーム/会社で社会的および政治的にあなたのために。このようなことを行うことは非常に危険であり、最悪の場合、政治的自殺につながる可能性があります。

依存性注入は、問題を探すソリューションです。

コンストラクターが定義されている言語はすべて、慣習に従って依存性注入を使用します。何をしているのかを理解し、コンストラクターを適切に使用する方法を理解している場合、これは優れた設計です。

依存性注入は、非常に狭い範囲で少量の場合にのみ役立ちます。

  • 大きく変化するもの、または静的にバインドされた代替実装が多数あるもの。

    • JDBCドライバーは完璧な例です。
    • プラットフォームごとに異なるHTTPクライアント。
    • プラットフォームごとに異なるロギングシステム。
  • フレームワークの構成コードで定義でき、起動時に自動的に検出され、プログラムの実行中に動的にロード/再ロードされる構成可能なプラグインを持つプラグインシステム。

1
user7519