Chris Donnan : Programming - Brooklyn Style
software, trading, family, fun
Posted programming on Sunday, May 20th, 2007.
Â
Lately I have been trying to help some folks understand the need for extreme composition + glue. One way I have been trying to describe classes to people is that they have 2 sides… draw a line down the middle and there are the behaviors, and the stuff you need to carry out those behaviors.
Â
 The Dependency Inversion Principle asks us to depend upon abstractions and allow them to be passed in. This means you are effectively cutting off the “dependency members”. You are explicitly NOT depending on whatever your dependents need to do their work. This is a key element.
Â
Â
Â
Having dependencies all over the place is a bad thing in case we have not figured this out yet. They make our code complex and very hard to understand because of the noise. They also drive what I call “the pass through problem”. Whenever you are “newing” your dependencies, you need to know how to build them, how to give them what they need to survive. This is quite a burden sometimes.
To illustrate - assume that we have classes A,B,C. They are happy and fine classes - they are simple - yet we need to add a new feature. In order to do this - we see that our happy simply C instance needs an X. How do we get it to him?
Ultimately we do not want to have to do this! This is the mess we were talking about above - knowing about what our dependencies need to do their work.
The Dependency Inversion Principle again here - it means that we cut of the dependency interface. This all sounds very good. Whenever you need something, simply declare a settable property or constructor argument for one of those, and move on. Do not try to get one or create one, expect that “it will be given to you”. This is the sentiment of The Dependency Inversion Principle .
I spent some time on friday moving around some code from a smart team member that I think quite well of. This code had stuff all over that checked to see if something was alive, if not, got it or newed it. In some cases, it tried to get it 1st, then if it could not, it newed it. This code accounted for some ~60 lines of code in a ~500 line of code area of code…
 This was something like:
…
if (null == applicationThingy)
    ISomeType servicex = GetService(typeof(ISomeType));
    if(null == servicex)
       servicex = new SomeTypeImpl(null, someArgument);
servicex.DoSomething();
…
The only meaningful but in the “value chain” of that code was the very last line - the DoSomething() call to the service. What I did was to go through the whole class and simply cut out all that stuff, and create a public settable property for the ISomeType service. What I found was that I got rid of > 1/2 the ~500 lines of code, as a lot of it was stuff for the dependenicies of dependencies. In short - whenever you need something to implement your behavioral interface, you do not want to care about how to create it. If you DO create it - you will have a concrete class dependency anyhow and it will be difficult to vary the behavior of your program without editing your code.
So - once you start doing this - you are left with a class that is much smaller - yet it has a number of settable properties and/ or constructor arguments that you can be given your dependency properties. Again, a user of your class should know NOTHING of your dependency properties. A user of you should be doing the same thing!!! They should be relying on whatever behavioral abstraction you represent -and allowing you to be passed in - given - by someone. The effect of this cascades. Nobody knows anything about how their parts work…. this is the extreme composition I am refering to. Systems should be assembled in this way. Systems assembled in this way really follow The Open-Closed Principle. Your code does not have to change, but - if you are given a different dependency set - your behavior can vary greatly.
This entire pattern, relying on abstractions that can be given to you - cascaded through a system is extremely powerful. You now have all the “seams” you need to substitute behaviors. You have an abstracted system of bits that can be tested in isolation. What you DO get at this point is something way up high in your application that looks like this:
Application x = new Application(new Foo(new ThingFooNeeds(new ThingFooNeedsNeeds(new ThingINeed(1,”yeah”)))));
.. only X around a zillion times bigger if your app is non-trivial. This is how things are “given” ala inversion of control/ DIP. So - once you really really do the dependency inversion thingy - you earn yourself another problem - the need for some “programmatic glue” to stick it all together. You could hard code all sort of factories all over of course. These are often static and always need changes frequently. They are also usually a switch statement
We would prefer a stronger solution.
Spring solves this problem, Pico Container solves this, Object builder solves this, structure map solves this, nanocontainer solves this, copeland in ruby solves this.. There are many many many solutions for solving this problem - dependency injection frameworks/ containers.
I have spent the better part of the past few years using spring.net for this particular set of goals. That being said, there are plenty of valid concerns for using spring (I am specifically refering to spring.net in my particular case).
XML is not that great. Yet another config language. Problematic to debug, reflection based, etc, etc. Type obsessed programming model. The list goes on. Moreover - I AM a spring fan to be clear, but - in order to sort out these specific concerns, and inspired by Rod Johnson’s “Pure Java Configuration” ideas, and in order to satisfy some co-worker’s concerns I have come up with a mind-numbingly simple and easy to use alternative implementation for .net. “Glue”…. So in part 3 I will introduce glue…
-Chris
Comment on this post below
You must be logged in to post a comment.
You can leave a response, or trackback from your own site.















