From IRC: “What’s Inversion of Control?”
First off: Oh, my.
Here’s a quick summary: traditionally, Java resources acquired whatever resources they need, when they need them. So if your DAO needed a JDBC connection, it would create one, which meant the more DAOs you created, for whatever reason, the more JDBC connections you used. It also meant that the DAO was responsible for its own lifecycle; mess it up, and you had problems.
This isn’t really a bad thing, honestly; lifecycle isn’t impossible to figure out. However, it means that the mechanism by which you acquired resources became really important – and if the mechanism wasn’t readily available, things got a lot more difficult to test.
Imagine a J2EE DAO, for example, where it used JNDI to get the JDBC DataSource. All good, until it’s time to do unit testing, and you don’t want to create a JNDI container just for testing – that’s slow and involves a lot of work that isn’t actually crucial to testing your DAO.
It’d be simpler for the DAO to not get its own resources, but accept the resources it needs. That means it no longer cares about JNDI (or how to get a JDBC connection) but it only says “I need to have a JDBC DataSource in order to work. If you want me to work properly, give me a DataSource.”
That’s inversion of control: instead of the control being in the DAO, the control is in what uses the DAO.
The implications are in many areas.
In production code, it means you want to have an easily repeated mechanism to create resources and provide them. A DAO is a resource; a DataSource is a resource; you want something to build both of them and manage giving the DAO the DataSource without you having to be involved much.
In testing, it means you have fine-grained control over what happens. You usually want to limit the scope of testing, honestly; testing a service that uses a DAO that uses a DataSource (that uses a database, of course) means: starting the database, establishing the connection to the database (the DataSource) and then creating the DAO and providing the Service with that DAO.
That’s lots of work. Too much work, really, and it means a lot of moving parts you don’t want.
With inversion of control, you create a DAO that has very limited functionality, just enough to fulfill the Service’ test. It might always return the same object, for example, no matter what data is requested. That means you’re not testing the DAO any more, nor are you establishing a database connection. This makes the test much lighter, and gives you a lot more control over what happens.
Need to test exception handling? Provide the service with a DAO that always throws an exception at a given point.
Need to test an exception that occurs later in the process? Provide a DAO that throws an exception at that later point (perhaps the fourth time you request data? – Whatever fulfills the need.)
Without Inversion of Control, this is much harder.
Author’s Note: Reposted. This post predated CDI by quite a bit, unfortunately, so it’s badly dated; preserved for posterity.