![]() |
![]()
| ![]() |
![]()
NAMEIOC - A lightweight IOC (Inversion of Control) framework SYNOPSISuse IOC; my $container = IOC::Container->new(); $container->register(IOC::Service::Literal->new('log_file' => "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(); DESCRIPTIONThis 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. What is Inversion of ControlMy favorite 10 second description of Inversion of Control is, "Inversion of Control is the inverse of Garbage Collection". This comes from Howard Lewis Ship, the creator of the HiveMind IoC Java framework. His point is that the way garbage collection takes care of the destruction of your objects, Inversion of Control takes care of the creation of your objects. However, this does not really explain why IoC is useful, for that you will have to read on. You may be familiar with a similar style of component management called a 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 accommodate. 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 loosely 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.
Inversion of Control in detailThe authors of the PicoContainer IoC framework defined 3 types of Dependency Injection; Constructor Injection, Setter Injection and Interface Injection. This framework provides the the ability to do all three types within the default classes using a pseudo-type, which I call Block Injection (for lack of a better term). This framework allows a service to be defined by an anonymous subroutine, which gives a large degree of flexibility. However, we also directly support both constructor injection and setter injection as well. Interface injection support is on the to-do list, but I feel that interface injection is better suited to more 'type-strict' languages like Java or C# and is really not appropriate to perl. There are a number of benefits and drawbacks to each approach, I will now attempt to list them.
Is this module ready to use?Yes, I have been using this actively in production for a couple years now, and it has worked without issue. CLASSESThis section will provide a short description of each of the classes in the framework and how they fit within the framework. For more information about each class, please go to the individual classes documentation.
Configuration Classes
Container ClassesContainers classes can hold references to both IOC::Service objects as well as other IOC::Containers. Containers are central to the framework as they provide the means of managing, storing and retrieving IOC::Service objects.
Service ClassesService classes are the even more central to the framework since they are what hold and dispense the dependency objects. There are a number of types of service class, all of which are derived at some point from the base IOC::Service class.
Prototyped ServicesMost services are singletons, meaning there is only one instance of each service in the system. However, sometimes this is not what you would want, and sometimes you want to set up a prototypical instance of a component and get a new instance each time. This set of Service classes provide just such functionality. NOTE: This is not really the same as prototype-based OO programming, we do not actually create a prototypical instance, but instead we just call the creation routine each time the component is requested.
Visitor ClassesIOC::Visitor classes are used by other classes in the system to perform various search and traversal functions over a IOC::Container hierarchy. They are mostly for internal use.
Utility ClassesThese classes are really just support classes for the framework.
CAVEATS
TO DO
WishlistThese are things which I have in the back of my head and would someday like to create, but just don't have the time right now.
BUGSNone that I am aware of. Of course, if you find a bug, let me know, and I will be sure to fix it. CODE COVERAGEI 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 1.4 100.0 IOC/Exceptions.pm 100.0 n/a n/a 100.0 n/a 7.6 100.0 IOC/Interfaces.pm 100.0 n/a n/a 100.0 n/a 2.5 100.0 IOC/Registry.pm 100.0 97.6 66.7 100.0 100.0 12.3 97.4 IOC/Config/XML.pm 100.0 100.0 66.7 100.0 100.0 6.1 96.0 IOC/Config/XML/SAX/Handler.pm 100.0 92.0 70.0 100.0 100.0 16.7 94.2 IOC/Proxy.pm 100.0 92.3 60.0 100.0 100.0 3.2 97.4 IOC/Proxy/Interfaces.pm 100.0 100.0 n/a 100.0 n/a 0.7 100.0 IOC/Container.pm 100.0 98.3 91.3 100.0 100.0 23.0 98.9 IOC/Container/MethodResolution.pm 100.0 100.0 n/a 100.0 n/a 5.6 100.0 IOC/Service.pm 89.4 78.6 66.7 88.5 100.0 7.0 85.7 IOC/Service/Literal.pm 100.0 100.0 33.3 100.0 100.0 0.7 96.2 IOC/Service/Prototype.pm 100.0 100.0 n/a 100.0 100.0 5.8 100.0 IOC/Service/ConstructorInjection.pm 100.0 100.0 66.7 100.0 100.0 2.2 93.9 IOC/Service/SetterInjection.pm 100.0 100.0 66.7 100.0 100.0 1.5 94.3 IOC/Service/Prototype/ConstructorInjection.pm 100.0 n/a n/a 100.0 n/a 0.5 100.0 IOC/Service/Prototype/SetterInjection.pm 100.0 n/a n/a 100.0 n/a 0.3 100.0 IOC/Visitor/SearchForContainer.pm 100.0 100.0 66.7 100.0 100.0 0.5 96.6 IOC/Visitor/SearchForService.pm 100.0 100.0 66.7 100.0 100.0 0.6 96.8 IOC/Visitor/ServiceLocator.pm 100.0 100.0 66.7 100.0 100.0 1.8 97.3 --------------------------------------------- ------ ------ ------ ------ ------ ------ ------ Total 99.1 94.8 70.3 98.7 100.0 100.0 95.9 --------------------------------------------- ------ ------ ------ ------ ------ ------ ------ SEE ALSOInversion of Control (or Dependency Injection) is one of the current hot buzzwords in the Java/Design patterns/C# community right now. However, just because a lot of people are talking about it insufferably does not mean it is still not a good idea. Below some links I have collected regarding IoC which you might find useful.
Here is a list of some Java IoC frameworks.
Here is a list of Ruby IoC Frameworks
AUTHORstevan little, <stevan@iinteractive.com> COPYRIGHT AND LICENSECopyright 2004-2007 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.
|