Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding the need for a DI framework

This might be a naive question. I'm currently learning the Spring framework and dependency injection. While the basic principle of DI is rather easy to grasp, it's not immediately obvious why you need an elaborate framework to implement it.

Consider the following:

public abstract class Saw {     public abstract void cut(String wood); }  public class HandSaw extends Saw {     public void cut(String wood)     {         // chop it up     } }  public class ChainSaw extends Saw {     public void cut(String wood)     {         // chop it a lot faster     } }  public class SawMill {     private Saw saw;      public void setSaw(Saw saw)     {         this.saw = saw;     }      public void run(String wood)     {         saw.cut("some wood");     } } 

Then you could simply do:

Saw saw = new HandSaw(); SawMill sawMill = new SawMill(); sawMill.setSaw(saw); sawMill.run(); 

Which would be equivalent to:

<bean id="saw" class="HandSaw"/>  <bean id="sawMill" class="SawMill">    <property name="saw" ref="saw"/> </bean> 

plus:

ApplicationContext context = new ClassPathXmlApplicationContext("sawmill.xml"); SawMill springSawMill = (SawMill)context.getBean("sawMill"); springSawMill.run(); 

Granted, this is a contrieved example, and with more complex object relationships it might be more efficient to stash up an XML file than writing it programmatically, but surely there must be more to it than that?

(I know the Spring framework is more than that, but I'm thinking of the need for a DI container.)

In the first example it would also be trivial to change dependencies midstream:

// gotta chop it faster saw = new ChainSaw(); sawMill.setSaw(saw); sawMill.run(); 
like image 888
Knut Arne Vedaa Avatar asked Feb 01 '09 11:02

Knut Arne Vedaa


People also ask

Do you need a DI framework?

You dont have to have a DI framework, but at some point in your codebase a concrete implementation is going to need to be instantiated and injected into your constructors/properties.

What is a DI framework?

A DI framework can reduce the boilerplate of creating factories and wiring the objects together, but at the same time it can also make it harder to find out that where each dependency is coming from - the DI framework's configuration is one more layer of abstraction to dig through, and your IDE might not be able to ...

What is the need of DI?

Dependency Injection (DI) is a design pattern used to implement IoC. It allows the creation of dependent objects outside of a class and provides those objects to a class through different ways. Using DI, we move the creation and binding of the dependent objects outside of the class that depends on them.

What is DI and why is it important?

A form of inversion of control, dependency injection aims to separate the concerns of constructing objects and using them, leading to loosely coupled programs. The pattern ensures that an object or function which wants to use a given service should not have to know how to construct those services.


1 Answers

I've had the exact same question, and it was answered by this:
Granted, you could do what you've described in "Then you could simply do:..." (let's call that "class A"). However, that would couple class A to HandSaw, or to all dependencies needed from class SawMill. Why should A be coupled to HandSaw - or, if you take a more realistic scenario, why should my business logic be coupled to the JDBC connection implementation needed for the DAO layer?
The solution I proposed then was "then move the dependencies one step further" - ok, so now I've got my view coupled to JDBC connection, where I should only deal with HTML (or Swing, pick your flavor).

The DI framework, configured by an XML (or JavaConfig) solves this by letting you just "get the needed service". You don't care how it's initialized, what it needs to work - you just get the service object and activate it.

Also, you have a misconception there regarding the "plus:" (where you do SawMill springSawMill = (SawMill)context.getBean("sawMill"); springSawMill.run();) - you don't need to get the sawMill bean from the context - the sawMill bean should've been injected into your object (class A) by the DI framework. so instead of ...getBean(...), you'd just go "sawMill.run()", not caring where it came from, who initialized it and how. For all you care, it could go straight to /dev/null, or test output, or real CnC engine... The point is - you don't care. All you care is your tiny little class A which should do what it's contracted to do - activate a saw mill.

like image 104
Ran Biron Avatar answered Sep 23 '22 11:09

Ran Biron