Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 272 Vote(s) - 3.45 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Understanding the need for a DI framework

#1
This might be a naive question. I'm currently learning the Spring framework and <i>dependency injection</i>. 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();
Reply

#2
It's important to understand that Spring is fundamentally two things, one built on top of the other:

1. A lightweight DI/IoC framework and the classes to implement that (eg XML application contexts, etc); and
2. It is a **lightweight container**.

(2) is the bulk of the Spring code. Basically pick a Java technology and you'll probably find Spring has helper classes for it. This is so you can use ActiveMQ, Sun One MQ or whatever and abstract them being a Spring JmsTemplate and the same goes for data access technologies, Web services, etc.

All of these helpers use (1) to wire them together.
Reply

#3
One thing that most (if not all) DI containers/libraries bring you in addition is the possibility to intercept methods for all instances created through DI.
Reply

#4
Spring helps you understand and even encourages DI models. However, I don't believe you have to have Spring.

You can have configuration files in Java which you can debug, refactor and perform code analysis on.

I suggest you put these java configuration files in another package, but they are otherwise equivalent to XML configuration files. You can even load these file dynamically if that's important.
Reply

#5
I generally don't care about XML or Reflection based DI because, in my use cases, it adds unnecessary complexity. Instead, I usually go for some form of manual DI that, to me, seems more natural and has most of the benefits.

public class SawDI{
public Saw CreateSaw(){
return new HandSaw();
}

public SawMill CreateSawMill(){
SawMill mill = new SawMill();
mill.SetSaw(CreateSaw());
return mill;
}
}

// later on

SawDI di = new SawDI();
SawMill mill = di.CreateSawMill();

This means I still centralize the coupling and have all the advantages of that, without the dependency on more complex DI framework or the XML configuration files.
Reply

#6
>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 think it makes more sense to put the "wiring up" in a configuration file rather than doing it manually in code for several reasons:

1. The configuration is external to your code.
2. Changes to the wiring up (to tell your `sawmill` to use a different instance of `Saw`) can simply be made to the external (XML) file and do not require changing code, re-compiling, re-deploying, etc.
3. When you have dozens of classes, and several layers of injection (for example: you have a web `Controller` class which gets a `Service` class which contains your business logic, which uses a `DAO` to obtain `Saw`s from the database, which gets a `DataSource` injected into it, etc.), manually wiring up the collaborators is tedious and requires a few dozen lines of code that do nothing but wiring up.
4. This is somewhat less of a clear-cut "benefit", but by having all of the 'wiring up' external to the code, I think it helps reenforce to developers the ideas that are at the core of dependency injection, specifically the idea of coding to the interface, not the implementation. With manual wiring up, it can be easy to slip back into old ways.
Reply

#7
Spring has three features that are equally important:

1. dependency injection
2. aspect oriented programming
3. library of framework classes to help with persistence, remoting, web mvc, etc.

I'll agree that it's hard to see an advantage to dependency injection when you compare that to a single call to new. In that case, the latter will certainly look simpler, because it's a single line of code. Spring's configuration will always increase the lines of code, so it's not a winning argument.

It starts looking a lot better when you can take a cross-cutting concern like transactions out of your classes and use aspects to set them up in a declarative way. The comparison to a single "new" call isn't what Spring was created for.

Perhaps the best outcome from using Spring is the way its recommended idiom uses interfaces, layering, and good principles like DRY. It's really just the distillation of object-oriented best practices that Rod Johnson used in his consulting gigs. He found that the code he built up over time helped him make a buck delivering better software for his clients. He summarized his experience in "Expert 1:1 J2EE" and ended up open sourcing the code as Spring.

I'd say buy into the framework to the degree that you think his experience can help you write better code, too.

I don't think you can get the full value of Spring until you combine all three of those features.

Reply

#8
If you hard-code the inserted class, you need that class be available at compile-time. With a configuration-file you could change the used saw (in your case) at runtime without recompiling and even use a saw taken from a new jar you just placed in the classpath. If it is worth the extra complexity is dependent on the task you have to solve.
Reply

#9
One of the biggest benefits of using Dependency Injection is that it makes it much easier to provide mocks or stubs of a class's dependencies when creating a unit test for that class. This allows you to test the class in isolation without depending on its collaborators.

In your example, there is no way to mock or stub out Saw or SawMill in the class that where those are being instantiated. If Saw and SawMill were set via setters or the constructor, then you could pass in your own mock Saw and mock SawMill when running the unit test.
Reply

#10
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.
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through