Monday, August 01, 2005

Light Weight Containers - Inversion Of Control (IoC) or Dependency Injection (DI) Frameworks

Last few years have seen a huge interest in lightweight frameworks in enterprise Java world to counter the complexity of heavyweight containers such as EJB. I have been reading a lot of people rave about IoC and how it makes life of a developer easier. While reading EJB3 first public draft spec, I saw references to dependency injection, this thing has arrived and I had no clue as to what it is. So I decided to get a feel for IoC. These are my findings so far.

IoC Defined

Objects in a system are associated with each other and they collaborate to provide a piece of business functionality. The objects depend on each other. Traditionally the task of resolving object dependency and setting up object collaborators is required programmatically before executing the business logic. A lot of code is required to wire up all the dependent objects. In J2EE world this often translates to performing JNDI lookup via a service locator to find the objects and instantiating them and setting up appropriate attribute in the business object. IoC frameworks invert the control with respect to resolution, creation and setting up of collaborators when performing a task or piece of business functionality or use case. For example in a customer relationship management system, the act of creating a customer may involve creating the customer object itself, creating customer contacts and creating products the customer has purchased. A customer service implemented as a session façade will need collaborator objects: Customer Business Object (Customer BO), Contact BO and Product BO. These business objects can be POJOs or EJBs (stateless that use DAO or entity EJBs for persistence). In a non IoC environment the customer service façade will need to find/locate the collaborators (Customer BO, Contact BO and Product BO), create them and setup the appropriate attributes before implementing business function. In an IoC environment, on the other hand , one simply declares the dependency (using a mechanism provided by the IoC framework) on the collaborators of customer service façade. At runtime the IoC framework ensures that these collaborators are wired up (again via an IoC framework specific mechanism) and ready to use before a customer business operation is called on it (say create). Its obvious from the description that instead of customer service façade controlling the collaborators, something else is controlling it - the IoC framework - hence the name Inversion of Control.

Any IoC framework has following characteristics (from Mike Spille's Blog):
An important aspect of programming with IoC is extensive use of interfaces. The dependencies are usually expressed using well-defined interfaces. Implementations are defined in a configuration file. The IoC container resolves the dependencies, creates an implementation for the interfaces and wires up the objects behind the scenes before business method on target object is invoked. Programming to interfaces and driving the implementation via configuration provides tremendous flexibility – a feature rarely seen in non IoC based systems.

Types of DI

There are 3 types of IoC frameworks. These are known, rather unimaginatively, as type 1, type 2 and type 3 based on how collaborators are setup i.e. dependency is injected. Martin Fowler gave them a more meaningful name:
Interface injection is not very popular. Constructor based and setter based injection dominate the field. Some frameworks prefer one over the other. For example PicoContainer guys prefer setter-based injection whereas Spring team prefers setter-based injection. Both of these popular frameworks/containers support both forms of dependency injection.

Essential Tensions

Constructor Vs Setter

Constructor-based injection wires up the dependencies at object construction time. This gives a valid object at creation. However if there are many dependencies, the constructor arguments can become large and cumbersome. The setter based construction is simpler, more intuitive and provides flexibility that might not be available with constructors.

Configuration file vs Java Code wiring

Configuration file gives more flexibility and the advantages are obvious. The dependencies can be modified just by modifying the config files without requiring a compile or build. The Java code wiring is useful in situations where component assembly is complex and requires logic (if then else) – in those scenarios expressing dependencies using config files becomes difficult. Only logical choice is a programming language with rich sematics for complex logic. Java code wiring is going to be simpler and easier. A dynamic language like Groovy can be really useful here since being dynamic it won’t require compilation whereas Java would.

Advantages
More info:
Popular DI/IoC Frameworks

This page is powered by Blogger. Isn't yours?