(This went to ruby-talk, too.)
Although it took a bit longer than I thought at first, I’m proud to announce the first public release of Dissident, a Ruby dependency injection container written by me.
What does Dissident do?
Dissident tries to make the best of different kinds of dependency injection:
It is as unobtrusive as Setter Injection (aka Type II), but done magically. It should feel exactly the same as just using the class if used properly.
It is as easy as Constructor Injection (aka Type III) with, say, PicoContainer (or what it would look like in an dynamically typed language), but not as clumsy if used without DI.
It is lazy, like Getter Injection (aka Type “IV”), and exactly as nice to use. The laziness also solves the problem of circular instantiations in a clever way.
Dissident can provide real Constructor Injection too, making the classes truly independent of Dissident.
Dissident provides per-container “singletons” (multitons, actually, if you make use of parameterized services), that are not globally unique and visible everywhere to the program, but only for the scope of the container used.
Dissident can do easy customization and “forking” of container implementations using standard Ruby inheritance and overriding. You can, for example, inherit from your default container to add stubs for testing.
Dissident provides multitons and multimethods for complete configurability of your applications. A prototypish instantiation style exists too.
Dissident includes an extensive test suite and is implemented using test-driven development.
The Dissident core is just a single and rather short file, ready to be included in your application. It has no external dependencies.
An example of using Dissident:
require 'dissident' class Apple def peel; end end class Peeler inject :peelable def start peelable.peel end def stop; end end class Juicer inject :peeler inject :peelable end class MyContainer < Dissident::Container provide :peeler, Peeler provide :peelable, Apple end Dissident.with MyContainer do juicer = Juicer.new end
This release is meant to be thread-safe, but testing in this area has not been very extensive. Users of threaded applications beware and please report bugs.
Copyright (C) 2005 Christian Neukirchen
Dissident is available under the same liberal terms as Ruby itself.
Where can I get it?
You can get Dissident 0.1 at: http://chneukirchen.org/releases/dissident-0.1.0.tar.gz
Alternatively, you can checkout from the development repository with:
darcs get http://chneukirchen.org/repos/dissident
(Patches using “darcs send” are most welcome.)
For more information on Dissident, please also see Mark IV Coffee Maker on Dissident and Design and Evolution of a Dependency Injection Framework.
Quoting from the latter:
But why write a new DI framework at all? There are some prejudices in the Ruby community with respect to that. People say “they make things complicated” and “there are more frameworks than users”. Of course, that may be true—but it shouldn’t be for all of them. Therefore, I decided to make one that’s not complicated, because you barely notice using it, one that’s easy to pickup, because you can learn it in an afternoon and only need to write a few additional lines of Ruby—no XML or YAML needed, one that actually helps coding, because else it’s a hobble and therefore no fun, one that eases testing, because you can mock the services easily (don’t use a container at all, or simply inject mocks), one that feels like Ruby, because you should never tangle in bad ports of Java libraries; in the end, I decided to make one that I personally like and want to use, because there is no point in making libraries you don’t use on your own.
NP: Silver Jews—The poor, the fair and the good