Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
IOC(3)		      User Contributed Perl Documentation		IOC(3)

NAME
       IOC - A lightweight IOC (Inversion of Control) framework

SYNOPSIS
	 use 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();

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.

   What	is Inversion of	Control
       My 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.

       Do you have more	than a few Singletons in your code?
	   If so, you are a likely candidate 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	life-cycles.

       Is your initialization code overly complex?
	   One of the great parts about	IOC is that all	initialization 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 necessary to
	   resolve dependencies	between	components manually.

   Inversion of	Control	in detail
       The 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.

       Constructor Injection
	   Constructor injection tends to encourages what are called Good
	   Citizen Objects, which are objects who are fully initialized	once
	   they	are constructed. It is also easy to analyze dependency
	   relationships since the components are stored in the	constructor
	   parameters.

	   One drawback	to this	approach is that it requires the component to
	   be a	class, as well as requires the class to	be a Good Citizen.
	   Which is okay if you	are writing the	class, but maybe not when it
	   is a	3rd party class.

       Setter Injection
	   Setter injection has	its benefits as	well. Since all	object
	   initialization is done through setter methods, it allows for	a
	   cleaner object design when there are	a lot of dependencies. Where
	   in a	constructor injection, it would	cause an explosion of
	   parameters in the constructor. Setter injection dependencies	can
	   also	be easily analyzed programmatically, since the dependencies
	   are stored in the setter parameters.

	   However, as with constructor	injection, some	of the the benefits
	   can also be drawbacks. Sometimes having public setters for
	   initialization is not what you would	want normally in your class.

       IOC-style Block Injection
	   This	style is, in my	opinion	the most perl-ish approach. It is
	   also, arguably, the simplest	approach since it requires very	little
	   on the part of the component	class, and easily allows for non-
	   object services. It can be used to mix both constructor and setter
	   injection in	the same service object.

	   One major drawback is that since the	initialization is "hidden"
	   within the anonymous	subroutine, it is very difficult to
	   programatically analyze the dependency relationships.

	   To give credit where	credit is due, this style is not my own
	   invention, but instead was derived from an IoC Ruby implementation
	   in the article mentioned in the "SEE	ALSO" section.

   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.

CLASSES
       This 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.

       IOC This	package	mostly serves as a namespace placeholder and to	load
	   the base framework. This will load IOC::Registry, IOC::Container
	   and IOC::Service.

       IOC::Registry
	   This	is a singleton registry	which can be used to store and search
	   IOC::Container objects/hierarchies.

       IOC::Proxy
	   This	package	can be used alone or as	a base class and be used to
	   proxy service instances.

       IOC::Proxy::Interfaces
	   This	IOC::Proxy subclass which proxies an object, but only
	   implements a	specified interface.

   Configuration Classes
       IOC::Config::XML
	   This	module allows you to configure an IOC::Registry	object using
	   XML.

   Container Classes
       Containers 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.

       IOC::Container
	   This	is the base Container object. In most cases, this class	will
	   be all you need.

       IOC::Container::MethodResolution
	   This	is a subclass of IOC::Container, and adds the ability to
	   retrieve services and sub-containers	with a method call syntax,
	   instead of passing a	string key to a	retrieval method.

   Service Classes
       Service 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.

       IOC::Service
	   This	is the base Service object. In most cases, this	class will be
	   all you need.

       IOC::Service::ConstructorInjection
	   This	extends	the IOC::Service object	to allow for a constructor
	   injection style.

       IOC::Service::SetterInjection
	   This	extends	the IOC::Service object	to allow for a setter
	   injection style.

       IOC::Service::Parameterized
	   This	extends	the IOC::Service object	to allow for additional
	   parameters to be passed during service creation. Since there	is an
	   unbound parameter, these services will work like the	prototyped
	   services and	return a new instance each time.

   Prototyped Services
       Most 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.

       IOC::Service::Prototype
	   A basic prototype-style Service class.

       IOC::Service::Prototype::ConstructorInjection
	   This	extends	the IOC::Service::Prototype object to allow for	a
	   constructor injection style.

       IOC::Service::Prototype::SetterInjection
	   This	extends	the IOC::Service::Prototype object to allow for	a
	   setter injection style.

   Visitor Classes
       IOC::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.

       IOC::Visitor::ServiceLocator
	   Given a path, this will attempt to locate a service within a
	   IOC::Container hierarchy.

       IOC::Visitor::SearchForService
	   Given a service name, this will attempt to locate a service within
	   a IOC::Container hierarchy by doing a depth first pre-order search.

       IOC::Visitor::SearchForContainer
	   Given a container name, this	will attempt to	locate a service
	   within a IOC::Container hierarchy by	doing a	depth first pre-order
	   search.

   Utility Classes
       These classes are really	just support classes for the framework.

       IOC::Exceptions
	   Defines a number of exceptions (with	Class::Throwable) used in the
	   system.

       IOC::Interfaces
	   Defines a number of interfaces (with	Class::Interfaces) used	in the
	   system.

CAVEATS
       Cyclical	and Graph Dependencies
	   Cyclical dependencies now work correctly (for the most part,	there
	   are still ways to produce infinite recursion, but most of them
	   could be considered programmer error) but should still be
	   considered an experimental feature.	This will need to be
	   documented in more detail to	explain	the gotchas and	edge cases.

	   Currently proxys and	cyclical dependencies are not working
	   together. In	order to resolve the cyclical dependency issue I need
	   to create a IOC::Service::Deferred instance to defer	the service
	   creation with. A proxy should not wrap the deferred instance, but
	   should only wrap the	final created instance.	Currently this does
	   not happen, so I need to work on it.

TO DO
       Work on the documentation
	   The docs are	still very rough in many places	and I will be filling
	   in details as I go. Of course any suggestions or criticisms of the
	   docs	are very welcome and will be gladly received. Help writing
	   them	will also be gladly received as	well.

       Create some more	integration tests
	   I have plenty of unit tests,	and the	code is	pretty well covered
	   (see	"CODE COVERAGE"	below).	However, what is lacking is some more
	   complex integration tests to	really test how	all the	modules	work
	   together. I expect a	few such tests to come out my using the	module
	   in my projects, and I will include them when	they do.

	   And of course, I am always open to contributions. If	you are	just
	   experimenting with this module to see if it would work for you,
	   chances are you will	create some code which would be	great as an
	   integration test. Please before you throw it	away, send it to me, I
	   might be able to use	it.

   Wishlist
       These 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.

       Dependency Analyzer
	   I would like	to create some kind of Visitor object which would
	   traverse a IOC::Container hierarchy and analyze the dependencies in
	   it. This is somewhat	simple for the ::ConstructorInjection and
	   ::SetterInjection Services since they store the keys	to their
	   dependencies	inside the object. However it is more complex with
	   regular IOC::Service	objects	which utilize the Block	Injection
	   pseudo-type.	For those the initialization block would need to
	   probably be run through B::Deparse and the dependency code parsed
	   out.

       Dependency Visualization
	   I hacked out	a quick	script which created a GraphViz	.dot file
	   which visualized the	dependency tree. It left much to be desired,
	   but it served as a proof of concept.	I would	like to	expand that
	   idea	into a more useful and flexible	tool. If anyone	is interested
	   in doing this one, contact me and I will send you the proof of
	   concept script.

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    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 ALSO
       Inversion 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.

       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>

       An interesting comparison of differnet IoC frameworks
	   <http://www.pyrasun.com/mike/mt/archives/2004/11/06/15.46.14/index.html>

       Here is a list of some Java IoC frameworks.

       HiveMind
	   <http://jakarta.apache.org/hivemind/>

       Spring Framework
	   <http://www.springframework.org/>

	   Spring also has a .NET version as well.

       PicoContainer
	   <http://www.picocontainer.org>

       Avalon
	   <http://avalon.apache.org/products/runtime/index.html>

       Here is a list of Ruby IoC Frameworks

       Copland
	   <http://copland.rubyforge.org/>

	   I have only skimmed this site, but it seems that Copland is
	   inspired by HiveMind.

       Needle
	   <http://needle.rubyforge.org/>

	   I have only skimmed this site, but it seems that Needle is a
	   lightweight version of Copland.

       Rico
	   <http://www.picocontainer.org/Rico>

	   Rico	is a Ruby port of the Java Pico	Framework.

AUTHOR
       stevan little, <stevan@iinteractive.com>

COPYRIGHT AND LICENSE
       Copyright 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.

perl v5.32.1			  2007-04-27				IOC(3)

NAME | SYNOPSIS | DESCRIPTION | CLASSES | CAVEATS | TO DO | BUGS | CODE COVERAGE | SEE ALSO | AUTHOR | COPYRIGHT AND LICENSE

Want to link to this manual page? Use this URL:
<https://www.freebsd.org/cgi/man.cgi?query=IOC&sektion=3&manpath=FreeBSD+13.0-RELEASE+and+Ports>

home | help