DRY Principle – Understanding Violations and Anti-Patterns

anti-patternsdryterminology

I am sure there's a name for this anti-pattern somewhere; however I am not familiar enough with the anti-pattern literature to know it.

Consider the following scenario:

or0 is a member function in a class. For better or worse, it's heavily dependent on class member variables. Programmer A comes along and needs functionality like or0 but rather than calling or0, Programmer A copies and renames the entire class. I'm guessing that she doesn't call or0 because, as I say, it's heavily dependent on member variables for its functionality. Or maybe she's a junior programmer and doesn't know how to call it from other code. So now we've got or0 and c0 (c for copy). I can't completely fault Programmer A for this approach–we all get under tight deadlines and we hack code to get work done.

Several programmers maintain or0 so it's now version orN. c0 is now version cN. Unfortunately most of the programmers that maintained the class containing or0 seemed to be completely unaware of c0–which is one of the strongest arguments I can think of for the wisdom of the DRY principle. And there may also have been independent maintainance of the code in c. Either way it appears that or0 and c0 were maintained independent of each other. And, joy and happiness, an error is occurring in cN that does not occur in orN.

So I have a few questions:

1.) Is there a name for this anti-pattern? I've seen this happen so often I'd find it hard to believe this is not a named anti-pattern.

2.) I can see a few alternatives:

a.) Fix orN to take a parameter that specifies the values of all the member variables it needs. Then modify cN to call orN with all of the needed parameters passed in.

b.) Try to manually port fixes from orN to cN. (Mind you I don't want to do this but it is a realistic possibility.)

c.) Recopy orN to cN–again, yuck but I list it for sake of completeness.

d.) Try to figure out where cN is broken and then repair it independently of orN.

Alternative a seems like the best fix in the long term but I doubt the customer will let me implement it. Never time or money to fix things right but always time and money to repair the same problem 40 or 50 times, right?

Can anyone suggest other approaches I may not have considered?

Best Answer

  1. it is just called duplicate code - I don't know of any more fancy names for this. The long term consequences are as you described, and worse.

  2. Of course, eliminating the duplication is the ideal option if only possible. It may take a lot of time (in a recent case in our legacy project, I had several methods duplicated across more than 20 subclasses in a class hierarchy, many of which had evolutionarily grown their own slight differences / extensions over the years. It took me about 1,5 years through successive unit test writing and refactoring to get rid of all duplications. Perseverance was worth it though).

    In such a case, you may still need one or more of the other options as temporary fixes, even if you decide to start moving towards eliminating the duplication. However, which of those is better depends on a lot of factors, and without more context we are just guessing.

    Lots of small improvements can make a big difference in the long run. You don't necessarily need the customer's explicit approval for these either - a little refactoring every time when you touch said class to fix a bug or implement a feature can go a long way over time. Just include some extra time for refactoring in your task estimates. It is just like standard maintenance to keep the software healthy in the long run.

Related Topic