Well, it's a new year and I have several crazy projects planned for 2009. Crazy Project #1 is well underway and I hope to be able to say more about it soon. Watch this space.
With the new year, the project that I have been working on is winding down a little and I thought it was about time to talk about some of the things I've learned. Firstly though I want to have a quick rant about Clipboard Inheritance. The practice of finding a bit of useful code, copying it into your own module and then calling it is not re-use. It's abuse. And we are only hurting ourselves.
There a few issues with copying and pasting code. Any bugs or mistakes in the original code get duplicated and efforts to fix them may not be universally applied. Any changes to the duplicated behaviour (not just defects) need to be applied at several locations and they may not all get handled. Basically you end up with an echo-chamber effect where small issues get magnified out and cause much more damage than they might otherwise have done.
The desire to copy and paste a chunk of code is a sure sign that it is in the wrong place. When next you get the urge to hit Ctrl+C step back and ask yourself "Where should this code go?". Sometimes it belongs in a base-class. Sometimes it belongs in a helper class of some kind. Sometimes you need to use the Template Method design pattern and push half of it into a base class and keep half of it local.
Wherever it belongs, take the time to find out where it should go and move it. Once the code is in it's rightful place you'll find that you can re-use it simply and efficiently by inheriting from the base-class or creating an instance of the helper class (or whatever the mechanism). If the effort to re-use a piece of code is approximately equal to the number of lines of code being reused, it isn't reusable enough.
This same issue goes for parts of the code that are not straight copy and paste cases as well. Places where you frequently need to paste in a bit of code and then make a few modifications are just as guilty. Find the parts you need to tweak each time and parameterise the reusable code. If it's a control id that is changing, put in a string parameter called controlId. If a type is changing, try and solve the problem with generics. The hard work you put in now will pay off later.
After coming across a lot of Clipboard Inheritance in the project I have been working on I seriously considered writing a plug-in for Visual Studio that disabled the Paste command. Visual Studio 2008 has a set of refactoring tools that you can use to try and extract common code into it's common place but it doesn't go far enough. Several 3rd party tools exist to add a great deal to this refactoring capability as well, such as ReSharper and Refactor Pro! It is worth getting a trial of these tools just to see the kinds of transformations that your code might undergo.
Another type of tool which is of use in the battle against Clipboard Inheritance is a Similarity Analyzer. A similarity analyzer is a tool that will examine your code base and find things that are "similar". I have yet to use one but I am going to try and lever one into the Continuous Integration build of my next project. If done correctly it should warn you when someone checks in code that appears to have the "Ctrl+V smell".
Some SA tools that are out there include:
- Clone Detective for Visual Studio - An Open Source VS plugin that gives you a graphical representation of "clone" code. From the videos this looks like it might work a bit like the code coverage tools in Visual Studio
- CCFinder - Standalone tool with a visualization engine. It's free, but requires registration.
- Simian - The first one of these I ever saw. The original implementation is in Java and from I can gather is lightning fast. It's free for Open Source / Non-commercial use.
I'm going to have a look at Clone Detective over the next week.
No new comments are allowed on this post.