Understanding Ioc Containers and Dependency Injection

Understanding IoC Containers and Dependency Injection

Put simply (because it's not a problem limited to OOP world only), a dependency is a situation where component A needs (depends on) component B to do the stuff it's supposed to do. The word is also used to describe the depended-on component in this scenario. To put this in OOP/PHP terms, consider the following example with the obligatory car analogy:

class Car {

public function start() {
$engine = new Engine();
$engine->vroom();
}

}

Car depends on Engine. Engine is Car's dependency. This piece of code is pretty bad though, because:

  • the dependency is implicit; you don't know it's there until you inspect the Car's code
  • the classes are tightly coupled; you can't substitute the Engine with MockEngine for testing purposes or TurboEngine that extends the original one without modifying the Car.
  • It looks kind of silly for a car to be able to build an engine for itself, doesn't it?

Dependency injection is a way of solving all these problems by making the fact that Car needs Engine explicit and explicitly providing it with one:

class Car {

protected $engine;

public function __construct(Engine $engine) {
$this->engine = $engine;
}

public function start() {
$this->engine->vroom();
}

}

$engine = new SuperDuperTurboEnginePlus(); // a subclass of Engine
$car = new Car($engine);

The above is an example of constructor injection, in which the dependency (the depended-on object) is provided to the dependent (consumer) through the class constructor. Another way would be exposing a setEngine method in the Car class and using it to inject an instance of Engine. This is known as setter injection and is useful mostly for dependencies that are supposed to be swapped at run-time.

Any non-trivial project consists of a bunch of interdependent components and it gets easy to lose track on what gets injected where pretty quickly. A dependency injection container is an object that knows how to instantiate and configure other objects, knows what their relationship with other objects in the project are and does the dependency injection for you. This lets you centralize the management of all your project's (inter)dependencies and, more importantly, makes it possible to change/mock one or more of them without having to edit a bunch of places in your code.

Let's ditch the car analogy and look at what OP's trying to achieve as an example. Let's say we have a Database object depending on mysqli object. Let's say we want to use a really primitive dependency indection container class DIC that exposes two methods: register($name, $callback) to register a way of creating an object under the given name and resolve($name) to get the object from that name. Our container setup would look something like this:

$dic = new DIC();
$dic->register('mysqli', function() {
return new mysqli('somehost','username','password');
});
$dic->register('database', function() use($dic) {
return new Database($dic->resolve('mysqli'));
});

Notice we're telling our container to grab an instance of mysqli from itself to assemble an instance of Database. Then to get a Database instance with its dependency automatically injected, we would simply:

$database = $dic->resolve('database');

That's the gist of it. A somewhat more sophisticated but still relatively simple and easy to grasp PHP DI/IoC container is Pimple. Check its documentation for more examples.


Regarding OP's code and questions:

  • Don't use static class or a singleton for your container (or for anything else for that matter); they're both evil. Check out Pimple instead.
  • Decide whether you want your mysqliWrapper class extend mysql or depend on it.
  • By calling IoC from within mysqliWrapper you're swapping one dependency for another. Your objects shouldn't be aware of or use the container; otherwise it's not DIC anymore it's Service Locator (anti)pattern.
  • You don't need to require a class file before registering it in the container since you don't know if you're going to use an object of that class at all. Do all your container setup in one place. If you don't use an autoloader, you can require inside the anonymous function you register with the container.

Additional resources:

  • Inversion of Control Containers and the Dependency Injection pattern by Martin Fowler
  • Don't look for things -- a Clean Code Talk about IoC/DI

Inversion of Control vs Dependency Injection

The Inversion-of-Control (IoC) pattern, is about providing any kind of callback (which "implements" and/or controls reaction), instead of acting ourselves directly (in other words, inversion and/or redirecting control to the external handler/controller).

For example, rather than having the application call the implementations provided by a library (also known as toolkit), a framework calls the implementations provided by the application.

The Dependency-Injection (DI) pattern is a more specific version of IoC pattern, where implementations are passed into an object through constructors/setters/service lookups, which the object will 'depend' on in order to behave correctly.

Every DI implementation can be considered IoC, but one should not call it IoC, because implementing Dependency-Injection is harder than callback (Don't lower your product's worth by using the general term "IoC" instead).

IoC without using DI, for example, would be the Template pattern because the implementation can only be changed through sub-classing.

DI frameworks are designed to make use of DI and can define interfaces (or Annotations in Java) to make it easy to pass in the implementations.

IoC containers are DI frameworks that can work outside of the programming language. In some you can configure which implementations to use in metadata files (e.g. XML) which are less invasive. With some you can do IoC that would normally be impossible like inject an implementation at pointcuts.

See also this Martin Fowler's article.

Why do I need an IoC container as opposed to straightforward DI code?

Wow, can't believe that Joel would favor this:

var svc = new ShippingService(new ProductLocator(), 
new PricingService(), new InventoryService(),
new TrackingRepository(new ConfigProvider()),
new Logger(new EmailLogger(new ConfigProvider())));

over this:

var svc = IoC.Resolve<IShippingService>();

Many folks don't realize that your dependencies chain can become nested, and it quickly becomes unwieldy to wire them up manually. Even with factories, the duplication of your code is just not worth it.

IoC containers can be complex, yes. But for this simple case I've shown it's incredibly easy.


Okay, let's justify this even more. Let's say you have some entities or model objects that you want to bind to a smart UI. This smart UI (we'll call it Shindows Morms) wants you to implement INotifyPropertyChanged so that it can do change tracking & update the UI accordingly.

"OK, that doesn't sound so hard" so you start writing.

You start with this:

public class Customer
{
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime CustomerSince { get; set; }
public string Status { get; set; }
}

..and end up with this:

public class UglyCustomer : INotifyPropertyChanged
{
private string _firstName;
public string FirstName
{
get { return _firstName; }
set
{
string oldValue = _firstName;
_firstName = value;
if(oldValue != value)
OnPropertyChanged("FirstName");
}
}

private string _lastName;
public string LastName
{
get { return _lastName; }
set
{
string oldValue = _lastName;
_lastName = value;
if(oldValue != value)
OnPropertyChanged("LastName");
}
}

private DateTime _customerSince;
public DateTime CustomerSince
{
get { return _customerSince; }
set
{
DateTime oldValue = _customerSince;
_customerSince = value;
if(oldValue != value)
OnPropertyChanged("CustomerSince");
}
}

private string _status;
public string Status
{
get { return _status; }
set
{
string oldValue = _status;
_status = value;
if(oldValue != value)
OnPropertyChanged("Status");
}
}

protected virtual void OnPropertyChanged(string property)
{
var propertyChanged = PropertyChanged;

if(propertyChanged != null)
propertyChanged(this, new PropertyChangedEventArgs(property));
}

public event PropertyChangedEventHandler PropertyChanged;
}

That's disgusting plumbing code, and I maintain that if you're writing code like that by hand you're stealing from your client. There are better, smarter way of working.

Ever hear that term, work smarter, not harder?

Well imagine some smart guy on your team came up and said: "Here's an easier way"

If you make your properties virtual (calm down, it's not that big of a deal) then we can weave in that property behavior automatically. (This is called AOP, but don't worry about the name, focus on what it's going to do for you)

Depending on which IoC tool you're using, you could do something that looks like this:

var bindingFriendlyInstance = IoC.Resolve<Customer>(new NotifyPropertyChangedWrapper());

Poof! All of that manual INotifyPropertyChanged BS is now automatically generated for you, on every virtual property setter of the object in question.

Is this magic? YES! If you can trust the fact that this code does its job, then you can safely skip all of that property wrapping mumbo-jumbo. You've got business problems to solve.

Some other interesting uses of an IoC tool to do AOP:

  • Declarative & nested database transactions
  • Declarative & nested Unit of work
  • Logging
  • Pre/Post conditions (Design by Contract)

What makes an IoC container an IoC container?

A DI Container is a library that you can use in various ways:

  • The simplest (pseudo) DI Container you can write is basically juts a glorified dictionary. You can build one in 15 lines of code. However, it doesn't do Auto-Wiring, which means that it doesn't do composition, so at this point you can only use it as a Service Locator, but since Service Locator is an anti-pattern, there's not much benefit from that.
  • A better DI Container also does Auto-Wiring. As soon as it can do Auto-Wiring, you can also use it as a Composition Engine. This means that you can design your own code exclusively on container-agnostic patterns like Constructor Injection, and then in the Composition Root ask the Composition Engine (DI Container) to compose everything together.

As soon as a DI Container supports Auto-Wiring, you can use it in both ways, but you should only use it as a Composition Engine.

Since Service Locator is an anti-pattern, the glorified dictionary has no value. As a bare minimum then, I'd say that a library must support Auto-Wiring in order to be a DI Container. However, that still doesn't make it a valuable component. To derive value from a DI Container, it must support sophisticated convention-based heuristics; if it doesn't, you're better off writing the composition by hand (AKA Poor Man's DI).

Inversion of Control Dependency Injection

If you accept Fowler's definition, Inversion of Control is a much broader term than DI that covers all framework usage where you plug into a framework, but the framework is still in control.

For example, in .NET, frameworks such as ASP.NET or Windows Presentation Foundation are ultimately in control, but provide various events and Seams you can use to build an application. The same is true on other platforms.

Dependency Injection is a specialization of IoC that applies IoC specifically to manage dependencies.

Understanding IoC, DI and reference methods

Disclaimer: I'm just learning DI myself. Take the answer with a grain of salt.

Dependency injection is only about injecting dependencies. If your object oriented design results in Family object having the responsibility to create instances of Member, then by all means, have the Family object create the Member, because in that case, Member is no longer considered a dependency of Family, but a responsibility. Therefore:

class Family
{
/**
* Constructor.
*
* Since you have decided in your OO design phase that this
* object should have the responsibility of creating members,
* Member is no longer a dependency. MySQLi is, since you need
* it to get the information to create the member. Inject it.
*
*/
public function __construct($id, MySQLi $mysqli)
{
$this->id = $id;
$this->mysqli = $mysqli;
}

/**
* Query the database for members data, instantiates them and
* return them.
*
*/
public function getMembers()
{
// Do work using MySQLi
}
}

But if you think about it, does Family really should have the responsibility of creating Member? A better design is to have another object, such as FamilyMapper create Family along with its members. Like this:

class FamilyMapper
{
/**
* Constructor.
*
* A better OO design, imho is using the DataMapper pattern.
* The mapper's responsibility is instantiating Family,
* which means it's going to have to connect to the database,
* which makes MySQLi its dependency. So we inject it.
*
*/
public function __construct(MySQLi $mysqli)
{
$this->mysqli = $mysqli;
}

public function findByID($familyID)
{
// Query database for family and members data
// Instantiate and return them
}

}

class Family
{
/**
* Constructor.
*
* Family is an object representing a Family and its members,
* along with methods that *operate* on the data, so Member
* in this OO design is a dependency. Inject it.
*
*/
public function __construct($id, MemberCollection $members)
{
$this->id;
$this->members;
}

public function getMembers()
{
return $this->members;
}
}

Using this pattern, your domain objects, along with their methods (which may contain business logic) will be decoupled from your data access code. That's the good thing about dependency injection - it forces you to rethink your OO design, so that you end up with cleaner code.

Many people think that using dependency injection means not using factories and such. This is wrong! Dependency injection is only about injecting dependencies. You can use dependency injection with factory objects too, by injecting dependencies to the factory instead of having the factory instantiating its own dependency.

Useful links:

  1. http://martinfowler.com/articles/injection.html
  2. Does anyone have a good analogy for dependency injection?
  3. How to explain dependency injection to a 5-year-old?

Additions

Again, take the stuff below here with a grain of salt.

Please also note that there is a difference between dependency injection and dependency injection container. The first one is a simple concept of injecting dependencies instead of having objects creating it themselves (which results in very high coupling). We see this from the example above.

The latter is a term for frameworks/libraries that deal with dependency injection so you don't have to do manual injection. The container's responsibility is wiring dependencies so you don't have to do the dirty work. The idea is you define a dependency injection configuration, which tells the container what dependencies Foo object has, and how to inject them. The container reads the documentation and performs the injection for you. This is what DIC libraries like Pimple, SimpleDIC do.

You can compare dependency injection containers with factories, since both are a creational objects, whose sole responsibility is to create objects. While factories are often specialized (i.e. FamilyMemberFactory creating instances of MemberInterface), dependency injection container is more general. Some people say using dependency injection container relieves you of the need for factories, but you should remember that it means you have to create and maintain dependency injection configuration files, which could be thousands of XML/PHP lines.

I hope this helps.

What is Dependency Injection and Inversion of Control in Spring Framework?

  • Spring helps in the creation of loosely coupled applications because of Dependency Injection.
  • In Spring, objects define their associations (dependencies) and do not worry about how they will get those dependencies. It is the responsibility of Spring to provide the required dependencies for creating objects.

For example: Suppose we have an object Employee and it has a dependency on object Address. We would define a bean corresponding to Employee that will define its dependency on object Address.

When Spring tries to create an Employee object, it will see that Employee has a dependency on Address, so it will first create the Address object (dependent object) and then inject it into the Employee object.

  • Inversion of Control (IoC) and Dependency Injection (DI) are used interchangeably. IoC is achieved through DI. DI is the process of providing the dependencies and IoC is the end result of DI. (Note: DI is not the only way to achieve IoC. There are other ways as well.)

  • By DI, the responsibility of creating objects is shifted from our application code to the Spring container; this phenomenon is called IoC.

  • Dependency Injection can be done by setter injection or constructor injection.

What is Inversion of Control?

The Inversion-of-Control (IoC) pattern, is about providing any kind of callback (which controls reaction), instead of acting ourself directly (in other words, inversion and/or redirecting control to external handler/controller). The Dependency-Injection (DI) pattern is a more specific version of IoC pattern, and is all about removing dependencies from your code.

Every DI implementation can be considered IoC, but one should not call it IoC, because implementing Dependency-Injection is harder than callback (Don't lower your product's worth by using general term "IoC" instead).

For DI example, say your application has a text-editor component, and you want to provide spell checking. Your standard code would look something like this:

public class TextEditor {

private SpellChecker checker;

public TextEditor() {
this.checker = new SpellChecker();
}
}

What we've done here creates a dependency between the TextEditor and the SpellChecker.
In an IoC scenario we would instead do something like this:

public class TextEditor {

private IocSpellChecker checker;

public TextEditor(IocSpellChecker checker) {
this.checker = checker;
}
}

In the first code example we are instantiating SpellChecker (this.checker = new SpellChecker();), which means the TextEditor class directly depends on the SpellChecker class.

In the second code example we are creating an abstraction by having the SpellChecker dependency class in TextEditor's constructor signature (not initializing dependency in class). This allows us to call the dependency then pass it to the TextEditor class like so:

SpellChecker sc = new SpellChecker(); // dependency
TextEditor textEditor = new TextEditor(sc);

Now the client creating the TextEditor class has control over which SpellChecker implementation to use because we're injecting the dependency into the TextEditor signature.

How IoC Container implements Dependency Injection compared to how I would implement it

I suppose a container does a lot of the boiler-plate code for you. For example, it does exactly what you said, instantiating a class based on the reflected behavior. Many containers also allow you to explicitly configure your system based on config files.

IOC or DI are only concepts. IOC/DI concepts give you the "indenpendency" that you favor. The actual implementation can vary. You can do it without using a third-party container -- or write your own. Or you can leverage the features provided by a well-tested third-party container.

If you just want to inject different types of db connections, they you have a very small need for IOC/DI. In general IOC/DI (beware, not the container, which is just an implementation of IOC/DI) gives you totally configurable software, aids in unit testing (by injecting stubs), self-configuration, etc.

Typically IOC/DI is necessary when:

  1. your software is so large and complex that no single person has it all in his head, or
  2. has so many different configurations that you don't want customized builds, or
  3. is so inter-dependent among the pieces that you find it difficult to test each piece alone


Related Topics



Leave a reply



Submit