Modularity is a feature

Stop me if you know this one. You find a library/framework that does something useful to you. You start using it and then realise it doesn’t work the way you want it in certain scenario or has a missing feature.

What do you do then?

  • Abandon the library and look for alternative that is more “feature rich”?
  • Ask the author to support your scenario/submit a pull request with the feature?

Those two, from my experience, are by far the most common approaches people take when faced with this situation.

There is another way

Surprisingly not many people take the third, most beneficial way, that is swapping part of the library for custom one, that is tailored for your needs.

Now, to be honest this has a prerequisite, that is, the library you’re using must be designed in a modular fashion, so that there are swappable parts. Most popular open source libraries however do a fairly good job at this. What this allows you to do, is to make specific assumptions and optimisations for your specific needs, ones that author of a generic library can never make, therefore having much more robust and targeted solution for your problems. Also being able to simply extend and/or swap parts of the library/framework means you don’t have to wait for a new version or waste time looking for and learning a different one (only to discover at some later point that it also doesn’t support some scenario you’ve got.

I did just that today with RavenDB (or more specifically Json.NET library it uses internally). The application I’m working on needs to store object graphs from a third party vendor. Objects that weren’t designed with NoSQL storage in mind (or any storage in mind) and this was causing Json.NET some troubles. Not to bore you with the details, I was able to resolve the problem by swapping DefaultContractResolver with my own implementation that catered for quirks of the model we’re using, and in less than 20 lines of code I achieved something remarkable – I was able to store in RavenDB, with no issues, objects that were never meant to be stored in such a way. And all of that without authors of RavenDB or Json.NET having to do anything.

Consider the alternatives

This brings us to the main point of this post – modularity is a feature. It is one of most important features of any reusable piece of code. Consider the alternatives. If you don’t allow for swapping parts of your code from generic one-size-fits-most solution to scenario specific variants you’re painting yourself into a corner, in one of two ways.

You are writing a very rigid piece of software, that unless used exactly in the way you anticipated, will be unfit for the task.

Alternatively as you discover new scenarios you can try to stretch your default implementation to support them all, adding more and more configuration flags to the API. In the end you will find that for every new scenario you add support for, two new get reported that you don’t support, all while metrics of your code complexity go through the roof and maintainability plummets.

giant-swiss-army-knife-thumb-400x316

 

So be smart. Whether you’re creating a library or using one, remember about modularity.

lego2

  • Gilly Barr

    Great post – and it is all so true…
    Thanks!

  • Good point. That’s one the reasons I love Castle Windsor.

  • Gavin van der Merwe

    You know what, you hit the nail on the head except I think people are ahead of you in terms of design here. If you look at the IoC container extensions in the new WebApi and SignalR stuff you will see they allow for hosting IoC container dependency implementations (*resolvers*) which you inject via the self hosting configs at startup. What this means is they provide default resolvers with default implementations. Except if you override the resolver via service configuration at startup it will request all sorts of interface implementaions from you *if you provide one*. Null equals default ultimately fallback. This is a beautiful design because it creates IoC seams exposing all your extension points within even the same compiled library. Something as trivial as recompiling source to replace a JSON serialiser is hardly what I would expect you to blog about mate … I have done it heaps … 🙂  

    Get on some proper No-SQL like couch, mongo or redis. Had heaps of joy using mongo …

  • You damm right. Modularity is everything: that’s why windsor rocks!