Wednesday, October 2, 2013

The Lesser Evil, avoiding Copy and Paste

I'm a great supporter of clean code. My own take on this can be found in an earlier post. The most common issue that I find is Copy and Paste-programming, and the most common explanation is lack of time. The problem is that it seldom saves time, even in the short run.

Copy and Paste-programming is a time thief. Every time. Even that deadline you have in 2 weeks, 2 days or 2 hours is endangered.

I'm hoping this post may inspire some hard-pressed-for-time developers to find the resolve to tackle the demon that is Copy and Paste, and come out feeling a little bit better and actually delivering more in less time.

The rationale

You probably know that Copy and Paste is a bad thing. Unfortunately most focus is on long-term maintenance aspects when explaining why it's bad. This makes for a perfect rationale when you're in a hurry. "I'll Copy and Paste this now, just to get the functionality done in time. I know I'll have to pay for this later during maintenance, but I don't see any other choice.".

I'd like to point out that the problems wíth Copy and Paste are much more severe than this, and that there really are other choices! Remember that evils are seldom equal, and if you have two evils to choose from, go for the lesser evil!

The maintenance argument

The main problem with the maintenance argument is that maintenance is not strictly separated from development. If you're lucky enough to work in a really agile environment, there's really no such thing as maintenance anyway, just a continuous number of releases. So which release/sprint/deploy should pay the cost of later, in favor of now?

It's seldom old code that you're Copying and Pasting. It's typically relatively new code, which means that it's still in rapid movement. Chances are, that within those 2 weeks/days/hours to release or end of the sprint, you'll have revisited that Copy and Pasted code more than once. In which case you'll have to propagate the changes to both copies, or forget one, and then have to bugfix it during acceptance testing - or worse hotfix it after deployment.

In either case, you're paying the cost for the Copy and Paste, not in that magical later slow phase of maintenance, but right now, when time's most at a premium. You're not saving time. You're losing time, and the reason you have so little time to lose is partially because of many small decisions like this.

Why is it likely that it's new code you're Copying and Pasting? Because otherwise it's unlikely that you know that the code is there to Copy! The other reason is that the most stressed-for-time releases are the major ones, especially the first. These are times where there is lots and lots of new code, also increasing the chances that it's new code. Finally, if the code is really old and stable, there's at least a chance that the functionality in question really has been factored out to common ground and there's no need any longer to Copy and Paste.

So, the "we'll gain time now, and pay for it later but that's ok"-argument is simply wrong. You're not gaining time now. You're losing time now.

The lesser evil

There are however options. Copy and Paste is the greater evil, but what are the lesser evils? For example:
  • Extract the code snippet to a general miscellanenous utility type. So, now you have a type with various disconnected pieces of code. A bucket full of... That's a lesser evil.
  • Move it to a common base class. So, now you're putting support code in a base class, and using inheritence to extend rather than specialize. That's a lesser evil.
  • Make the code snippet in question a public method just where it happens to be. So, now you have an unholy dependency between two types that probably should not have the dependency. That's a lesser evil.
All of these lesser evils are explicitly known to the compiler and fairly easy to safely refactor later, and it might even be good strategy since usually a pattern emerges after a while and it becomes clearer just where the common code should reside. There's only one copy of the code in either of these lesser evil alternatives, and that has to be a good thing!

Even if you never get to the refactoring stage, these are still lesser evils than the alternative - Copy and Paste.

Hopefully some readers will here find some supporting arguments and useful techniques reducing the amount of Copy and Paste.