Off On a Tangent

A web of tangents that somehow unify.

Tuesday, March 29, 2005

Context IoC

Sony Mathew posted an article about IoC at TSS a while back that caught my imagination. It seemed so similar to the direction of my own thoughts on the matter that I decided to try to put together a framework that would make such a thing manageable. In a nutshell, Sony's idea was that a class could define everything it needs to function in an inner interface, and code that instantiates the class could provide implementations of that interface. This would provide a very simple mechanism for dependency injection.

It also creates a whole lot of indirection, and it doesn't tackle the problem of how one creates the implementations of all those interfaces, which people rightly pointed out in the comments for the article. But then, Sony did make the point that part of his argument is that IoC/DI is a design pattern, not a framework, and, being a design pattern, it wasn't the point to provide a nice API for achieving IoC.

I, on the other hand, do want a framework that makes this idea for IoC workable. And so I set off to learn AspectJ to help me do that. Part of my goal is to make an IoC container that is invisible to the developer. You use it, and you know you use it, but it doesn't show up in your code. For instance, if I create a new object:

MyObject obj = new MyObject();
Then that should be all I need to do, and (with the help of AspectJ), the new object will be injected with everything it needs to function.

One of the primary uses of such dependency injection is to ease the delivery of highly changeable configuration information to the code that uses it. And so, of course, this framework must provide a mechanism for reading/creating that config info. I suppose XML is the standard for such info, but since I dislike XML for config info, I've gone another route. I've used a simplified format for basic text information, and supplemented it with Groovy for more complex info. In other words, your new object could essentially be provided it's context by a groovy script or groovy class file, either of which can be easily modified after the system has been compiled and deployed.

Not to be confused with the idea of Context interfaces describing a class's dependencies, I realized I would need the concept of different contexts to allow multiple sets of configuration data and flexibility. I'm using a tree structure to organize such contexts, using file-path type naming (ie "root/childContext/grandChildContext") and allowing children contexts to inherit configuration information from their parents. I use AspectJ to keep track of what the context is of the current code, so that when you call new MyObject(), it will be configured with the same context as the currently executing code. If you want to change contexts, you use new MyObject(String contextName).

Ok, so what's the result of this experiment? Interestingly, my configuration information does not need to specify a list of services to be created and stored in some sort of service locator. Nor do I need to use singletons - though a Context implementation can be defined in such a way that it will end up being a shared object for all classes that declare themselves dependent on it. However, this shared behavior is hidden away in the aspect and framework code. All the developer ever writes is new ObjectIWantToUse().

At first, I did write code to handle the loading and startup of such services, but I am finding that I don't actually need it. I wasn't out to remove the use of Singletons or service locators (I'm pragmatic enough to make use of both), but I'm happy with this unexpected result. My goal was to make it easy and simple to write code that is highly configurable, and effortless to write. To remove a lot of boring code that we often have to write wherein we are essentially just passing around information to classes - instead, I wanted the information to get to those classes transparently. And by doing so, encourage greater use of dynamic config-file-type info.

On the downside, using AspectJ to intercept calls to constructors means creating objects is more costly performance-wise. Fortunately, my aspects don't intercept calls to every constructor - only those of classes that implement a ContextOriented interface. Still, the difference is drastic - being about 100x slower than normal object creation (not counting whatever code you might write to pass needed info to that new object, so it's not an entirely fair comparison). I'm hopeful, however, that this performance blip won't be too disabling, as it's fairly specific to object creation, and not a universal slowdown (in other words, I'm hoping the penalty in terms of absolute performance isn't that great).

Monday, March 28, 2005

Making a Family Blog

My family lives all over the place. Keeping up-to-date with each other
is tough, and so I thought it might be fun to make a family blog, where
we could all do the blog thing and keep better track of what's going on
in each of our lives.

I think this could be especially fun for the younger ones. I know some
people are skittish about how un-private a blog is, but that too is part
of what blogging is. It's not direct communication amongst family
members, but the indirectness adds a certain value, a quality to the
communication that we don't get over the phone or email, or even in
person. Call it a blending of public and private persona, a blurring of
the divisions we create for ourselves.

Friday, March 25, 2005

Intelligent code

Most developers I know, usually myself included, loathe working with software code that tries to be intelligent on your behalf. Most especially if that code was written by someone else. Inevitably, the "intelligent" code gets in the way more than it helps you, due to it making all kinds of hidden assumptions you are unaware of. You, as the developer, are forced to adapt your normal coding habits to work with these assumptions that originated in a foreign mind.

The problem of hidden assumptions in "intelligent" code is similar to the problem of hidden assumptions in crappy code. Maybe not similar, maybe they are the same.

But, who of us hasn't written our own intelligent code, and then gone on to use it happily, patting ourselves on the back for making our own lives so much easier. When we're aware of the assumptions (after all, we put them there) and work with them, suddenly they start working for us.

I dream of using intelligent code that makes my life easier, and that others find equally useful. In my job, I try stick to writing dumb code that doesn't outsmart you. At home though, and in open source, I strive to create that perfect beast - intelligent code that helps you more than it annoys.

And that's one reason why I like open source so much - we don't have to fear failure. Our jobs aren't at stake. We can make miserable code 9 times out of 10, but on that tenth, maybe we've created something startling and eye-opening.