Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is coupling to dependencies with the new keyword considered bad?

I've been using Dependency Injection for a while, and now I want to give a talk about IoC and DI to a group of new developers. I remember explaining it to one guy personally and he asked me:

"Why not just use:

private IMyInterface _instance = new MyImplementaion();

instead of going through all the DI trouble. "

My answer was: "Unit testing requires mocks and stubs." - but we do not write unit tests in my company so it did not convince him. I told him that concrete implementation is bad since you are tightly coupled to one implementation. Changing one component will cause change in another.

Can you give an example for such code? Can you give me more reasons why this code is bad?

It seem so obvious to me that I have trouble explaining it :-)

like image 827
user4098933 Avatar asked Dec 14 '14 08:12

user4098933


People also ask

Why new keyword is bad in Java?

In short, whenever you use "new", you are tightly coupling the class containing this code to the object being created; in order to instantiate one of these objects, the class doing the instantiating must know about the concrete class being instantiated.

Why dependency injection is loosely coupled?

Dependency Injection is a form of a software design pattern that enables us to write loosely coupled code and reduces tight coupling among components. The tight coupling has strong dependencies that restrict code reuse. Dependency Injection enables us to reduce the coupling and helps us to write well maintainable code.

What problem does dependency injection solve?

The goal of the dependency injection technique is to remove this dependency by separating the usage from the creation of the object. This reduces the amount of required boilerplate code and improves flexibility.

Is coupling a type of dependency?

The level of dependency between software units is called coupling.


1 Answers

The problem with the following coupling

public class MyClass
{
    private IMyInterface _instance = new MyImplementation();
    ...

Means that any time MyClass is created (whether directly, or by an IoC container) is that it will always immediately create a concrete MyImplementation and bind its dependency _instance to this concrete implementation. In turn, it is likely that MyImplementation has other dependencies, which are also coupled this way.

Benefits of decoupling of classes such that MyClass is only dependent on interfaces to its dependencies, and not concrete implementations of the dependencies (i.e. the D of SOLID principles) include:

  1. for Unit Testing - As you've mentioned, in order to test MyClass in isolation, with new'ed dependencies, you would need to resort to nasty things like Moles / Fakes in order to mock out the the hard wired MyImplementation dependency.

  2. for Substitution - by coupling only to an interface, you can now swap out different concrete implementations of IMyInterface (e.g. via configuring your IoC bootstrapping) without changing any code in MyClass.

  3. for making dependencies explicit and obvious in your system, as the IMyInterface dependency may have further dependencies, which need to be resolved (and may need configuration considerations as well). If MyClass hides the IMyInterface dependency internally, it is not visible to the caller as to what the dependencies of MyClass are. Although in classic 1990's OO this was commonplace (i.e. encapsulation + composition), this can obscure the implementation as deployment of all dependencies still needs to be done. However, with coupling done on interface level (i.e. consumers of MyClass will do so only via IMyClass), the coupling-visible interface is IMyClass which will again hide the dependency on IMyInterface, since constructors are not visible on the interface).

  4. for configurable dependency lifespan control. By injecting IMyInterface, instead of newing MyImplementation, you are allowing additional configuration options with respect to the lifespan management of the MyImplementation object. When the original hardwired creation of MyImplementation was done on MyClass, it was effectively taking ownership of MyImplementation's lifespan with a 1:1 relationship between the two class instances. By leaving this to the IoC container, you can now play with other options of MyImplementation's lifespan, which might be more efficient, e.g. if MyImplementation instances are thread-safe, you may elect to share an instance across multiple instances of MyClass, for instance.

In summary, here's how I believe the refactoring should look suitable for IoC constructor dependency injection:

public class MyClass
{
    // Coupled onto the the interface. Dependency can be mocked, and substituted
    private readonly IMyInterface _instance;

    public MyClass(IMyInterface instance)
    {
       _instance = instance;
    }
    ...

The IoC container bootstrapping will define WHICH implementation of IMyInterface needs to be bound, and will also define the lifespan of the dependency, e.g. in Ninject:

 Bind<IMyInterface>()
     .To<SomeConcreteDependency>() // Which implements IMyInterface
     .InSingletonScope();
like image 199
StuartLC Avatar answered Sep 30 '22 15:09

StuartLC