Sunday, April 5, 2009

Don't Try To Write Reusable Software

First a story

Early in my first job, another fresh out of school co-worker and I decided that we were going to rewrite this one library we used to make it more reusable for all of the upcoming projects.  When we asked for advice from a more experienced developer, he basically told us not to bother, because we were going to fail.  We scoffed at his cynicism, knowing that our design skills and knowledge of the requirements were going to result in this awesome library.

Fast forward a year and the "reusable" library that we spent so much time and effort on still had to go through considerable customizations to handle cases that we hadn't even envisioned when we started.

Did we fail because of incompetence?  While our skills probably weren't quite as good as we thought at the time, no.  We failed because it required the unknowable - knowing what the future would bring.  The Agile premise of YAGNI summarizes this.

The Moral

I summarize this experience with the title to this post, don't try to write reusable software.

I can hear your CS hearts shudder at this. 
How can this be?  Isn't writing reusable software what is taught in our programming classes?  You can't really be saying that we should be cutting and pasting code all over the place.  Besides there are plenty of successful reusable libraries out there, like printf or java.util.*.  This must be a false premise!
Again, I say, "Don't try to write reusable software!"
But...but...that goes against everything I learned.

The Real Moral - Discover Reusable Software

Don't try to write reusable software, discover it instead.
Obviously you shouldn't be cutting and pasting code.  Obviously you should still be using methods and classes.  The DRY principle is a good one and it implies reusable code.  However, reusable code is the means, not the goal.  

Let me repeat that, because it is important.  Writing code that is reusable (methods, classes, etc.) is the means to achieving the goal of a clean design.  But your goal isn't the reusability, your goal is to only specify everything once.  Only write your algorithm once.  Only specify a value once.  Only put your business logic on one place.  If you strive to achieve those goals, you will end up with reusable components.  

Even better, you will end up with code that is maintainable and written in a timely manner.


Jerry said...

Well stated.

Trevor said...

I find the idea of discovering reusable software vs. building reusable software intriguing. I had not really thought about the subject in that way before. I, too, have had a number of experiences similar to yours.

However, I do think that reusability needs to be factored into the design process. Designing code to be reusable helps enforce good practices such as proper encapsulation and defining a sane API. Too many times I have worked with code where components have been unnecessarily coupled together. Normally, the excuse is that this design was more expedient, "simpler," or simply addressed an edge case. In the end, though, it almost always complicates things down the road such as adding features, performing maintenance, or debugging some problem.

To your point, perhaps reusability is a better metric than a goal. In other words, a good design is one in which its components could be reused. If you find that it would be difficult to reuse many of the components in your software, then perhaps that is an indicator that those components' design should be reevaluated.

Michael Haddox-Schatz said...

I suspect the thesis of my post isn't completely accurate.

Proper encapsulation, good APIs, and decoupled software components are all good practices. But why are they good practices? Is it just because it makes it easier to maintain and extend the software, and reusability is just a by-product? Or is reusability really one of the purposes of these practices?

I think I'll have to revisit this at some point... Definitely an interesting topic.