The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

IOC - A lightweight IOC (Inversion of Control) framework

SYNOPSIS

  use IOC;
  
  my $container = IOC::Container->new();
  $container->register(IOC::Service->new('log_file' => sub { "logfile.log" }));
  $container->register(IOC::Service->new('logger' => sub { 
      my $c = shift; 
      return FileLogger->new($c->get('log_file'));
  }));
  $container->register(IOC::Service->new('application' => sub {
      my $c = shift; 
      my $app = Application->new();
      $app->logger($c->get('logger'));
      return $app;
  }));

  $container->get('application')->run();   

DESCRIPTION

This module provide a lightweight IOC or Inversion of Control framework. Inversion of Control, sometimes called Dependency Injection, is a component management style which aims to clean up component configuration and provide a cleaner, more flexible means of configuring a large application.

A similar style of component management is the Service Locator, in which a global Service Locator object holds instances of components which can be retrieved by key. The common style is to create and configure each component instance and add it into the Service Locator. The main drawback to this approach is the aligning of the dependencies of each component prior to inserting the component into the Service Locator. If your dependency requirements change, then your initialization code must change to accomidate. This can get quite complex when you need to re-arrange initialization ordering and such. The Inversion of Control style alleviates this problem by taking a different approach.

With Inversion of Control, you configure a set of individual Service objects, which know how to initialize their particular components. If these components have dependencies, the will resolve them through the IOC framework itself. This results in a loosly coupled configuration which places no expectation upon initialization order. If your dependency requirements change, you need only adjust your Service's initialization routine, the ordering will adapt on it's own.

For links to how other people have explained Inversion of Control, see the "SEE ALSO" section.

Why Do I Need This?

Inversion of Control is not for everyone and really is most useful in larger applications. But if you are still wondering if this is for you, then here are a few questions you can ask yourself.

Do you have more than a few Singletons in your code?

If so, you are a likely canidate for IOC. Singletons can be very useful tools, but when they are overused, they quickly start to take on all the same problems of global variables that they were meant to solve. With the IOC framework, you can reduce several singletons down to one, the IOC::Registry singleton, and allow for more fine grained control over their lifecycles.

Is your initialization code overly complex?

One of the great parts about IOC is that all initialzation of dependencies will get resolved through the IOC framework itself. This allows your application to dynamically reconfigure it load order without you having to recode anything but the actual dependency change.

Are you using some kind of Service Locator?

My whole reasoning for creating this module was that I was using a Service Locator object from which I dispensed all my components. This created a lot of delicate initialization code which would frequently be caused issues, and since the Service Locator was initialized after all the services were, it was nessecary to resolve dependencies between components manually.

Diagrams

Here is a quick class relationship diagram, to help illustrate how the peices of this system fit together.

 +------------------+                  +--------------+                 +-------------------------+
 |  IOC::Container  |---(*services)--->| IOC::Service |---(instance)--->| <Your Component/Object> |
 +------------------+                  +--------------+                 +-------------------------+
           |
   (*sub-containers)
           | 
           V    
 +------------------+
 |  IOC::Container  |
 +------------------+   
       

TO DO

Work on the documentation

BUGS

None that I am aware of. Of course, if you find a bug, let me know, and I will be sure to fix it.

CODE COVERAGE

I use Devel::Cover to test the code coverage of my tests, below is the Devel::Cover report on this module test suite.

 ----------------------------------- ------ ------ ------ ------ ------ ------ ------
 File                                  stmt branch   cond    sub    pod   time  total
 ----------------------------------- ------ ------ ------ ------ ------ ------ ------
 IOC.pm                               100.0    n/a    n/a  100.0    n/a    4.0  100.0
 IOC/Exceptions.pm                    100.0    n/a    n/a  100.0    n/a    6.6  100.0
 IOC/Interfaces.pm                    100.0    n/a    n/a  100.0    n/a    6.3  100.0
 IOC/Registry.pm                      100.0  100.0   77.8  100.0  100.0   14.5   97.6
 IOC/Container.pm                     100.0   97.4   93.1  100.0  100.0   33.8   98.6
 IOC/Container/MethodResolution.pm    100.0  100.0    n/a  100.0    n/a    1.4  100.0
 IOC/Service.pm                       100.0  100.0   83.3  100.0  100.0   15.3   97.5
 IOC/Service/ConstructorInjection.pm  100.0  100.0   77.8  100.0  100.0    4.4   97.3
 IOC/Service/SetterInjection.pm       100.0  100.0   77.8  100.0  100.0    4.5   97.2
 IOC/Visitor/SearchForContainer.pm    100.0   90.0   77.8  100.0  100.0    2.8   95.1
 IOC/Visitor/SearchForService.pm      100.0  100.0   77.8  100.0  100.0    2.9   96.7
 IOC/Visitor/ServiceLocator.pm        100.0  100.0   77.8  100.0  100.0    3.5   97.0
 ----------------------------------- ------ ------ ------ ------ ------ ------ ------
 Total                                100.0   98.4   83.2  100.0  100.0  100.0   97.7
 ----------------------------------- ------ ------ ------ ------ ------ ------ ------

SEE ALSO

Some IoC Article links

The code here was originally inspired by the code found in this article.

http://onestepback.org/index.cgi/Tech/Ruby/DependencyInjectionInRuby.rdoc

Dependency Injection is the Inverse of Garbage Collection

http://howardlewisship.com/blog/2004/08/dependency-injection-mirror-of-garbage.html

This is a decent article on IoC with Java.

http://today.java.net/pub/a//today/2004/02/10/ioc.html

An article by Martin Fowler about IoC

http://martinfowler.com/articles/injection.html

This is also sometimes called the Hollywood Principle

http://c2.com/cgi/wiki?HollywoodPrinciple

Here is a list of some Java frameworks which use the IoC technique.

Avalon

http://avalon.apache.org/products/runtime/index.html

Spring Framework

http://www.springframework.org/

PicoContainer

http://www.picocontainer.org

AUTHOR

stevan little, <stevan@iinteractive.com>

COPYRIGHT AND LICENSE

Copyright 2004 by Infinity Interactive, Inc.

http://www.iinteractive.com

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.