Written By: Steve Zagieboylo, Senior Architect at Calavista


This is the sixth part in the series, “Technical Debt Patterns.”

There are two (or more!) copies of the same bit of code, because some lazy (or unknowing) programmer copied a whole block and just edited a few of the lines.  Sure, it’s a lot easier than figuring out the right refactoring, and it gets the job done.


Why is it a problem?

I had another developer ask me that question in all seriousness, and I had to pause to answer without just referring to the obvious inelegance of it.  (He and I had debated before over the value of elegance; he didn’t think it was important.)  Fortunately, I knew of a specific example of his own code in which I had fixed a bug recently.  The bug was not an egregious error, just a weird situation not handled correctly, and was in my own code.

The problem was that after I fixed it, the bug didn’t go away!  I was so sure this was causing it, because it fit the symptoms so perfectly.  I finally figured out that actual bug I was trying to fix was in a parallel bit of code, the exact same error for the same reason, because the code where it was actually occurring had been copied and pasted from the place where I assumed it was happening.  In searching the code, I found yet another instance of the same problem, in a nearly identical stretch of code.  The other developer had copied and pasted the block I had originally written, and copied my bug.  It was fortunate that the copy I originally fixed hadn’t triggered the case I was focussed on, or I never would have realized that there were two more copies of the bug.


Cost Comparison

The cost of leaving these copies in place is clear, you can end up deploying code that has bugs in it which you have already found and believe you have fixed.  It is especially embarrassing when you inform your users that a particular bug has been fixed, and then have it show up again in a slightly different incarnation.  At the very least, the cost is that with every bug you fix, you have to double check whether or not that same bit of code appears elsewhere, and possibly make the same fix there, too.

The cost of fixing this particular issue used to be a lot higher, but with modern IDE’s and their powerful refactoring tools, it has become much easier.


How do I fix it?

The modern IDE’s have terrific refactoring tools to fix and to avoid this problem.  They will even point it out to you in many cases, though if there are enough small changes, they might miss it.  The refactor operation names are the same in both IntelliJ and Eclipse (for Java), as well as Rider (for C#).  I know that Visual Studio has the same refactor operations, but I’m not sure of the exact names.

  • Refactor / Extract Method
  • Refactor / Introduce Parameter or Refactor / Introduce Variable and Refactor / Inline Variable

First you extract the common bit of code as a method from one of the places where it appears, ignoring for the moment the bits that are different between the versions.  Consider whether or not this needs to be a static method, or if all the places that need to call it are in the same base class, and make sure you put it in that base class if this is the case.
In the new method, select a part that is different between the copies and use Refactor / Introduce Parameter.  The refactoring tool is clever enough to add the right value for the parameter in the calling code.

Another approach is to start by introducing a new variable for each of the different bits of code, move those above the code you extract as a method, and then inlining the values back into the method call.  (This is what we used to do before Refactor / Introduce Parameter worked so well.)

Finally, go to the other instances of the code and add a call to your new method, copying in the right parameters into the arguments before you wipe out the old code.


Your code has shrunken

If you’ve done the job right, you will have reduced the overall size of your code.  Of course, if anyone is measuring you by the amount of code you write, it is time to get a new job.