Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implementing Dependency injection static methods

In this old code I am trying to update , they implemented dependency injection like this:

public class Program
{
    private IProgramRepository programRepository;

     public Program(IProgramRepository repository)
        {
             this.programRepository = repository;
        }

     public Program() : this(new EN_Program()) { }

now in this program class all methods are static, so all of the static methods all actually have 2 methods like this:

    public static List<Program> GetProgramsByUser(int userId)
    {
        return GetProgramsByUser(userId, GetDefaultRepository());
    }
    private static List<Program> GetProgramsByUser(int userId, IProgramRepository repo)
    {
        return repo.GetProgramsByUser(userId);
    }

Now I've read this among other things about implementing DI:

This is not dependency injection at all. This actually clearly violate the dependency inversion principle. The principle say that "High level module should not depend upon the low level module, both should depend on abstraction. Details should depends upon abstraction". In above code Product.cs itself create EN_Program object. So it directly depends on IProgramRepository implementation (EN_Program). If in future another implementation comes of IProgramRepository interface then Product.cs code itself need to change. So it is probed that it is not proper way to do.

It looks like the old developers wanted to implement DI just starting with the helper classes (Program.cs) with nothing injected into the controllers.

Am I correct in assuming that this old code was not written correctly ? Is it necessary when implementing DI that everything from the controller to the back end have injections?

ex. The controller would need to be injected with an Interface that the helper class uses (Program.cs) - then Program.cs is injected with an interface that the repository uses

like image 261
Scott Selby Avatar asked Apr 29 '13 15:04

Scott Selby


1 Answers

The comment is incorrect. It talks about Dependency Injection pattern, but it quotes the Dependency Inversion Principle. The overloaded constructor is an implementation of the Dependency Injection pattern, and the default constructor is an implementation of the Poor Man's Dependency Injection anti-pattern.

Although the overloaded constructor practices the Dependency Injection pattern, the default constructor does not and does in fact violates the Dependency Inversion Principle. Because of the reasons quoted.

So you're absolutely practicing Dependency Injection, but you are also practicing Poor Man's Dependency Injection which is bad for a lot of reasons. For instance:

  • Your code takes a direct dependency on a low level component disallowing you to ship them separately.
  • The direct dependency makes it harder to swap implementations, which is something that is very common to do when you add cross-cutting concerns (using decorators or interceptors) . You don't want to go through the whole application to change all constructors just to wrap EN_Program instances with a decorator or interceptor.
like image 77
Steven Avatar answered Sep 22 '22 19:09

Steven