Architecture – Is Poor Man’s Dependency Injection a good way to introduce testability to a legacy application

Architecturedependency-injectioninversion-of-controllegacy

In the past year, I created a new system using Dependency Injection and an IOC container. This taught me a lot about DI!

However, even after learning the concepts and proper patterns, I consider it a challenge to decouple code and introduce an IOC container into a legacy application. The application is large enough to the point that a true implementation would be overwhelming. Even if the value was understood and the time was granted. Who's granted time for something like this??

The goal of course is to bring unit tests to the business logic!
Business logic that is intertwined with test-preventing database calls.

I've read the articles and I understand the dangers of Poor Man's Dependency Injection as described in this Los Techies article. I understand it does not truly decouple anything.
I understand that it can involve much system wide refactoring as implementations require new dependencies. I would not consider using it on a new project with any amount of size.

Question: Is it okay to use Poor Man's DI to introduce testability to a legacy application and start the ball rolling?

In addition, is using Poor Man's DI as a grass roots approach to true Dependency Injection a valuable way to educate on the need and benefits of the principle?

Can you refactor a method that has a database call dependency and abstract that call to behind an interface? Simply having that abstraction would make that that method testable since a mock implementation could be passed in via a constructor overload.

Down the road, once the effort gains supporters, the project could be updated to implement an IOC container and the constructors would be out there that take in the abstractions.

Best Answer

The critique about Poor Man's Injection in NerdDinner has less to do with whether or not you use a DI Container than it does about setting up your classes correctly.

In the article, they state that

public class SearchController : Controller {

    IDinnerRepository dinnerRepository;

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

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

is incorrect because, while the first constructor does provide a convenient fallback mechanism for constructing the class, it also creates a tightly-bound dependency to DinnerRepository.

The correct remedy of course is not, as Los Techies suggests, to add a DI container, but rather to remove the offending constructor.

public class SearchController : Controller 
{
    IDinnerRepository dinnerRepository;

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

The remaining class now has its dependencies properly inverted. You're now free to inject those dependencies however you like.

Related Topic