Monday, August 6, 2007

Dependency Injection

I read an article focused mainly on Dependency Injection. However, what interested me even more was it's discussion around Service Locator as an alternative to DI. In my opinion, Service Locator should only be considered as an alternative in some scenarios. However, before I blog my opinions about Service Locator and Dependency Injection, I'm going to start by talking about each one individually. I don't want to assume everyone reading this knows what both patterns are and really don't want to write one giant post. So, read below for a summary of dependency injection or visit the article mentioned above for more detail.

Quick Explanation
First of all, you may have been doing DI without knowing what it was. But, to explain, Dependency Injection is exactly what it sounds like. A class's dependencies are injected into the class rather than created inside it. Probably best explained with an example.

Instead of:


class RequestHandler {
private ResponseGenerator responseGenerator;

public RequestHandler() {
this.responseGenerator = new ResponseGeneratorImpl();
}
}

Do this:

class RequestHandler {
private ResponseGenerator responseGenerator;

public RequestHandler(ResponseGenerator responseGenerator) {
this.responseGenerator = responseGenerator;
}
}

So, what does this do? We've accomplished two things. First we've created loose coupling between RequestHandler and ResponseGenerator. The first method uses a specific implementation while the second doesn't. Second, we've given control to the entity instantiating RequestHandler. This says, "I don't want to limit you to a specific implementation of ResponseGenerator, so i'll give you control and allow you to provide me with the ResponseGenerator you'd like me to use."

Types
There are three (3) types of Dependency Injection: Constructor Injection, Setter Injection, and Interface Injection. You've just seen an example of Constructor Injection. I'm not going to talk about or show Interface Injection for several reasons. (I've never used it and the other two are much more common.) Setter Injection I'm sure you can picture, but just in case, see the example below.

public class RequestHandler {
private ResponseGenerator responseGenerator;

public void setResponseGenerator(ResponseGenerator responseGenerator) {
this.responseGenerator = responseGenerator;
}
}

Constructor vs Setter Injection
The primary distinction is that Constructor Injection provides a usable object (presumably) immediately after construction. This means no worries of running into exceptions because you instantiated an object but forgot to set one of its dependencies. So what about when you're dealing with quite a few dependencies? Either your constructor gets long, or you're forcing many setter method calls to create a usable object. Unless you have a good reason to use Setter Injection, I'd stick to Constructor Injection as a rule of thumb. (And stay away from using a combination if at all possible !!! My pet peeve.)

Pros
Other than enabling loose coupling and increasing usability through inversion of control, the remaining major benefit is ease of testing. DI allows you to simply inject mock objects to unit test the class under test.

Cons
When your class has lots of dependencies, it can get messy. Even though this could be an indication your class should be separated out into multiple classes (cohesion), it doesn't necessarily. So, from time to time, you will run into this.

More to Come
There are more DI pros and cons, but nothing really worth talking about unless you're comparing against an alternative. Stay tuned and I'll be doing just that when I look at the idea of Service Locator as an alternative to Dependency Injection.

Other DI Links:
Wikipedia
James Lorenzen's Blog

3 comments:

jlorenzen said...

Here is the Spring Frameworks comment on setter vs constructor injection. Spring is one of the most popular DoI frameworks available.

"Constructor- or Setter-based DI?

The Spring team generally advocates the usage of setter injection, since a large number of constructor arguments can get unwieldy, especially when some properties are optional. The presence of setter methods also makes objects of that class amenable to being re-configured (or re-injected) at some later time (for management via JMX MBeans is a particularly compelling use case).

Constructor-injection is favored by some purists though (and with good reason). Supplying all of an object's dependencies means that that object is never returned to client (calling) code in a less than totally initialized state. The flipside is that the object becomes less amenable to re-configuration (or re-injection).

There is no hard and fast rule here. Use whatever type of DI makes the most sense for a particular class; sometimes, when dealing with third party classes to which you do not have the source, the choice will already have been made for you - a legacy class may not expose any setter methods, and so constructor injection will be the only type of DI available to you."


I got this information from springs documentation.

I think it is all about preference and what fits for your class. I don't think you can say, setter or construtor injection works all the time. My preference is to use setter injection purely because it makes writing unit test that much easier. When you have attempted to write unit tests for inherited java code, it is infinitely difficult to write unit tests that take N constructor arguments.

Also I understand your distaste for combining them; which I agree. But there is good reason to apply both, and that is when you might have required objects (constructor) and optional objects (setter).

Finally a third option would be Method-Injection. Similar to constructor injection but is not global to the class but rather the method. I actually practice this quite often. Here is an example:

public class RequestHandler {

public void sendRequest(RequestGenerator requestGenerator) {
// so some fancy stuff
requestGenerator.send();
}
}

A familiar example of method-injection is when creating a Servlet and overriding the doPost() or doGet() methods and receiving the objects HttpServletRequest and HttpServletResponse.

Anonymous said...

[url=http://community.bsu.edu/members/buy+online+Viagra.aspx]prescription Viagra online[/url]

[url=http://ceklansi.ru/frazy-dlya-znakomstva-v-internete.php]фразы для знакомства в интернете[/url]
[url=http://ceklansi.ru/luchshiy-sayt-znakomstv-kazahstan.php]лучший сайт знакомств казахстан[/url]
[url=http://ceklansi.ru/shluhi-bishkek.php]шлюхи бишкек[/url]
[url=http://ceklansi.ru/intim-vakansii.php]интим вакансии[/url]
[url=http://ceklansi.ru/shluhi-vzroslye.php]шлюхи взрослые[/url][url=http://celuyou.ru/index.php]высокие проститутки[/url]
[url=http://celuyou.ru/seks-chat-n-novgoroda.php]секс чат н новгорода[/url]
[url=http://celuyou.ru/prostitutki-almaty-sayt.php]проститутки алматы сайт[/url]
[url=http://celuyou.ru/prostitutki-babushkinskaya.php]проститутки бабушкинская[/url]
[url=http://celuyou.ru/seks-v-gorode-omske.php]секс в городе омске[/url]
[url=http://deperovero.ru/poznakomlus-s-armyankoy.php]познакомлюсь с армянкой[/url]
[url=http://deperovero.ru/botanicheskiy-sad-intim.php]ботанический сад интим[/url]
[url=http://mx.deperovero.ru/forum-sayt-znakomstv.php]форум сайт знакомств[/url]
[url=http://mx.deperovero.ru/ischu-partnera-po-seksu.php]ищу партнера по сексу[/url]
[url=http://rp.deperovero.ru/deshevye-shluhi-moskvy-vyezd.php]дешевые шлюхи москвы выезд[/url]
[url=http://rp.deperovero.ru/intim-internet-znakomstva.php]интим интернет знакомства[/url]
[url=http://ss.deperovero.ru/poznakomitsya-s-tatarkoy.php]познакомиться с татаркой[/url]
[url=http://ss.deperovero.ru/znakomstva-sochi.php]знакомства сочи[/url]
[url=http://tt.deperovero.ru/seks-izmena-blog.php]секс измена blog[/url]
[url=http://tt.deperovero.ru/znakomstva-monamur.php]знакомства монамур[/url]

iSilver Labs said...

We just developed a open source Light Weight Ioc / Dependency Injection framework.

http://blog.isilverlabs.com/2010/08/lightweight-ioc-dependency-injection-framework/