I once took advantage of the published source code of the Microsoft Enterprise Library Data Access Block to make some firm-specific modifications. One of those changes that only really makes sense in the target environment, nothing particularly general. The Data Access Block, for those of you who aren’t familiar with it, is basically an improved version of the ADO.NET API, with some pretty useful support for stored procedures. It’s not NHibernate, but it’s better than coding the API in the raw.
While I was there, I decided to rip out the stuff we didn’t use. That turned out to be nearly all of it. This was quite shocking to me, because I thought we used a fair chunk of the functionality. I reckon that when it came down to it, two thirds of the library was non-functional. The vast majority of the code, which I had no interest in, was there to support ObjectBuilder.
For those of you who aren’t familiar with it, ObjectBuilder is Enterprise Library’s configuration system. It was created to solve the some of the same sort of problems as IoC containers, but it also addresses some interesting concerns such as providing a UI for configuration. Enterprise Library is also the original source of my ideas on environmental deltas.
So, how did I get rid of all of this code? Well, I junked DatabaseFactory and used constructor injection again. It took a bit of time, but I deleted two thirds of the code without an appreciable loss of functionality.
How Much is Too Much?
Before you think this is just an exercise in ragging the Pattern & Practices group, who are a pretty easy target, I want you to ask how much code your internal and open source libraries should be devoting to configuration. Now, I doubt you’ll find many people arguing that two thirds is the right amount. However, I bet you’re thinking that five percent is acceptable. I’m going to argue the correct figure here is zero.
Let’s take a look at a successful open source library: log4net. In some ways, log4net is even worse than the Data Access Block. At least Enterprise Library didn’t require me to use ObjectBuilder. The code was dead and irrelevant in our applications. log4net, on the other hand, isn’t even usable without digging into its configuration system. Because it’s so prescriptive on this point, it then proceeds to provide several alternative approaches to how to use its configuration system.
But I don’t want to use it at all. I’ve got Castle Windsor already, why would I want two configuration systems? If I develop a large application with a lot of libraries, I could end up with four of five configuration files. And pretty much all of them aren’t exactly well thought out or powerful. Want a variable to be consistent across the files? You’d better get coding.
And this is where it gets really ugly. APIs defining their own configuration system doesn’t save time, it makes work for the application developer. Configuration is right on the outside of the Onion model and should be in one place, not dotted around your system. The choice of how to configure the system should be up to the application developer. Look at Retlang, it has no configuration at all. Does it make it harder to get running? Actually no, a small program can hard code everything in the Main method, a large program can use an IoC container.
The whole philosophy of constructor injection and IoC containers is that classes shouldn’t take on externalities they don’t need. The same applies to libraries. Be ruthless in applying the single responsibility principle and get configuration out of your code.