Re-Use is hard
Well, at least it seems to be. So why?
We're better off than most at work. We hire really smart people, we've got good tools and we keep our working practices under review so we can get better all the time. We've solved many of the problems that seem to plague software companies (and have a whole new set all of our own ;-)
So why, with a whole bunch of really smart people working close together on similar projects using the same technologies do we not have near perfect re-use?
By re-use I mean proper re-use - of packaged libraries of code - not simply copying and pasting code someone else wrote already. Copying and pasting is easy, you don't have to think about dependancies, or clashes or what they might change about it in future. You can alter it in subtle ways that make it 'neater' and 'more understandable'. I put those in quotes because they're subjective measures, what's more understandable for you may not be for me.
And there lies the nub of the problem. If we're writing code that others can take and re-use we have to write in a way that matches the problems they're trying to solve as well as the one we're solving. And that's the hard bit.
The reason it's so hard is that we have to put all the modeling we have in mind for the current problem to one side and start modeling from scratch in a different, more abstract and generic way.
Thinking about it from an OO perspective, books such as Domain-Driven Design by Eric Evans and Object Thinking by David West lead us down the path of using nouns from the domain to name our classes, but when we do that we have to decide which domain we're currently in. If you want to build re-usable UI controls then your domain is the UI, so nouns like 'TextBox' make sense while nouns like 'Author' do not - if you want the components to be reusable that is.
In essence that's where the hard bit lies; in identifying the different domains and how they should be cut so that they can then be recombined in different ways.
So how to get better at that? The obvious thing to do is go look for places where people already solved the problem - that turns out to be class libraries like MFC, the .Net libraries and the swathes of small, open-source libraries that do just one thing well.
When we look at these we find they're broken into modules, components, namespaces or some other unit of packaging. Within each module the vocabulary is consistent, complete and, to a great extent, independent. This means that a library for parsing RSS may depend on one for parsing XML, but is unlikely to require other packages. This sounds obvious when written down, or as you read a book on it, but when writing the code itself it's hard.
So, knowing it's hard, the next most important thing is to support the evolution of the components, otherwise we have to get them right first-time which seems unlikely. This requires forgiveness and respect. The thing you want to re-use won't have been written as you would have written it yourself; and at that realization you have a choice of two paths.
The first and most common route would be to get a bit ranty, copy & paste the code into your own world (where you have absolute control, so don't need to be considerate) and start hacking it into the shape you want for the problem you're solving. The second is to take a deep-breath, put on your reading glasses and start to try and make your head think the way the original author was thinking - if you can achieve that then you can go on to improve the code, extend it sympathetically and contribute that work back. The second route is harder, much harder, than the first.
But even knowing that, it still looks hard to me.
Technorati Tags: code reuse, software engineering
Nice article. We've hit this issue also, but slightly less hard as reuse is happening amongst the same team, writing side-by-side applications. The approach we've taken is to make an assembly "reusable" only when a second application requires the same functionality. So far the only challenge we hit here was dependancies - two apps were using different log4net versions, with differing strong names, so both apps and the component had to be rebuilt to take the lowest denominator. Components that are small and focussed have worked well so far, e.g. EmailNotifier, FileConverter (strange how they're more verb like than nouns eh - probably still too procedural :-)
Lyndsay, Interesting that you rebuilt to the lowest version. .Net, unlike pretty much any other environment, has the ability to load different versions of strong-named assemblies side-by-side at runtime. They have to be registered in the GAC (Global Assembly Cache) for that to happen, but it works extremely well. 'Notification' may make a better class than EmailNotifier... rob