Sunday, December 23, 2007

Copy/Paste Considered Harmful

When I first started coding years ago, it was in a very early version of Basic that ran on the timesharing computer at Dartmouth. I had no formal training and committed many of the sins of self-taught programmers, including programming by copy/paste. After a few times of having to fix bugs in multiple places I started learning about functions in Basic so I could stop that nonsense. I also became aware of how messy it was to add new features in copied code.

At this point in my career I am more aware of this problem, and tend (when I see it in existing code) to refactor before going on with my planned task(s). If there are automated QA tests with the appropriate coverage I assume they will catch problems. If not, I construct a few automated tests of my own to increase my confidence that the refactoring didn't change any existing behavior.

I was talking with a co-worker a few weeks ago about coding practices, and the topic of copy/paste came up. I went into my usual rant/sermon about it, only to find out that he actually had a professor who promoted copy/paste as a method of "code reuse." I don't know where my co-worker went to school, or what this professor had a degree in, but it took me aback to hear this.

Now there are a few times where copy/paste is appropriate. For example, if we are late in the QA cycle and about to release a product and find a real show-stopper of a bug. After analyzing the bug and determing the cause and the fix, we realize that it is deep in some code that is called from many other places. Given the time frame, we're not able to test all those places to the level of quality that we would like. In this case, I have occasionally done some copy/paste to make sure that the side effects of my change are as minimal as possible. I always, however, put a TODO (or TBD, or other cleanup marker, depending on the coding standards of the company I'm at) into the copied code with a reference back to the source of the copied code. This then goes as a task at the top of my cleanup list for the beginning of the next development cycle.

I don't see how to produce long-lasting quality code without doing this.

[Minor pop quiz: where does the title of this post come from?]