It was with some interest I spotted a positive mention of something called Context IoC (a new type of IoC apparently) on Dion Hinchcliffe’s Blog. The while topic really bores me right now as IoC stopped being something fancy a long time ago, and to me it’s now nothing more than “calling a proper constructor”. I investigated further as Dion normally writes very sensibly, does some very nice diagrams and has impeccable taste.
Contextual IoC is outlined in a ServerSide piece by Sony Mathew. It’s not surprising I missed it the first time round as I stopped reading the ServerSide a while back. It turned out I really wasn’t missing much. He starts off on shaky ground:
IOC seems to be at odds with the fundamental paradigm of object encapsulation. The concept of upstream propagation of dependencies is indeed a contradiction to encapsulation. Encapsulation would dictate that a caller should know nothing of its helper objects and how it functions. What the helper objects do and need is their business as long as they adhere to their interface – they can grab what they need directly whether it be looking up EJBs, database connections, queue connections or opening sockets, files etc..
He almost makes a point here, but ends up saying “Objects should interface with things with interfaces”. To those of us who create interfaces to reflect the role a concrete class has in a system, this is nothing new. Quite who this is “at odds with the fundamental paradigm of object encapsulation” I’m not quote sure.
Things then look up a bit:
The benefits of IOC are that objects become highly focused in its functionality, highly reusable, and most of all highly unit testable.
That I agree with. Then we’re off again:
The problem with exposing dependencies via constructors or Java bean properties in general is that it clutters an object and overwhelms the real functional purposes of the constructor and Java bean properties.
I agree with exposing setters purely to provide dependencies – but constructors? At this point it’s clear that Sony and I disagree on what a constructor is – apparently creating an object with the tools it needs to do its job is not what a constructor is for. At this point we’re waiting for Sony’s solution – and the solution is Contextual IoC.
Let’s look at Sony’s example of this:
public class PoolGame {
public interface Context {
public String getApplicationProperty(String key);
public void draw(Point point, Drawable drawable);
public void savePoolGame(String name,
PoolGameState poolGameState);
public PoolGameState findPoolGame(String name);
}
public PoolGame(Context cxt) {
this.context = cxt;
}
...
}
Right, so what’s happened here is that we’ve taken dependencies (in the form of method calls – the PoolGame
requires and folded them into an inner interface. Question 1 – how is this different from passing in the roles as separate interfaces? It seems to me with have the need for 3 distinct roles, something along the lines of PoolRepository
(for savePoolGame()
and findPoolGame()
), Display
(for draw()
) and ApplicationConfig
(for getApplicationProperty()
). My version of the code would be:
public class PoolGame {
public PoolGame(
PoolRepository rep,
Display display,
ApplicationConfig config) {
...
}
}
So Sony’s code is dependent on having implementations of four methods, my code as a dependency on a implementations of three roles in the system. Lets look at the “benefits” of this approach:
The Context interface removes the clutter of exposing dependencies via constructors or Java bean properties
Does my constructor look any more cluttered than Sony’s inner Context
interface? I know my object is going to be easy to create too – how easy is it to create Sony’s? Will it look as simple as constructing my version? So I dispute that benefit. Next:
It provides better clarity by organizing an object’s dependencies into a single personalized interface unique to that class. The PoolGame.Context interface is unique to the PoolGame class.
And that’s a benefit how? It’s a simple matter to see where my roles are used in the system – with contextual IoC you have to look for Context
implementations that use things like PoolRepository
, which would still need to exist. You’d still need to create things that perform storage and queries of games, things that display the games, or access application properties. But with contextual IoC you also have to create context objects to wrap them up.
4 Responses to “Looking at Context IoC”
Also his Context interface mixes concerns – the whole point of interfaces is that an interface encapsulates a single responsibility. The ‘getApplicationProperty’, ‘draw’ and ‘savePoolGame’ have no business being in the same interface.
If he’s trying to make it more convenient to use mocks, then that is even worse – it just hides the smell “Too many dependencies”.
It appears he wanted to have the ‘next’ big thing…instead he just has ‘another’ bad idea.
It’s truly a problem in search of a solution. In other words, typical fare for denizens of the (once useful) serverside.com
The primary point of Context IOC is that it propogates dependencies up to the “top-object” to provide a single configuration point.
If you’re happy to unit test with hard-coded dependencies and you don’t need to change those dependencies then – yes – this pattern just adds more complexity. On the other hand, if you’re already using dependency injection, Context IOC is an interesting and arguably simpler option.
It’s always good to question anything that adds more lines of code, but I think your comparisons to plain object aggregation are missing the point.
You mention that with Context IOC we still have to actually create objects. The point is that those objects will be created in only one place and propogated down rather than being created on the fly in various places. Dependencies are still passed via the constructor, so Sony is not advocating some kind of paradigm shift.
Having said all that, this pattern certainly could be a “solution in search of a problem” (I assume that’s what Michael intended to say) in a lot of cases. But the same could be said about dependency injection and IOC in general, so I don’t think that fact invalidates the pattern. If you’re struggling with unit testing due to heavyweight dependencies, then that’s a problem for which Context IOC provides an effective and framework-free solution.