10

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?

5
  • "Is there a name for this anti-pattern?" The 'violating-dry' anti-pattern? :) IMHO you pretty much answered it yourself. Sep 12, 2011 at 13:56
  • Maybe call it "The Dry Violator"? Sep 12, 2011 at 14:28
  • 2
    I call it: DRY bumping.
    – AJC
    Sep 12, 2011 at 14:54
  • 5
    Copy and Paste coding?
    – tylermac
    Sep 12, 2011 at 17:48
  • It is called the "too many cooks spoil the broth" pattern.
    – Doc Brown
    Apr 28, 2015 at 15:44

7 Answers 7

18
  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.

0
9

There is a reference to the WET (We Enjoy Typing) pattern but I don't know if it is a standard name.

...Software licensing is a notable exception to the DRY (Don't Repeat Yourself) practice - software licensing code should be as WET (We Enjoy Typing - the opposite of DRY) as possible.

If you isolate your licensing logic in one place, separated from other concerns, you make it far easier to modify your software to disable the licensing altogether. It is much better to repeat the licensing logic many times throughout the application, preferably such that it is executed numerous times throughout a single execution of the software.

For example, we suggest that you perform a licensing check during installation, during application startup, and whenever important features are accessed. Don't check the licence once during startup & pass that value around; instead, actually replicate the licensing check in each area. It's inconvenient, but far better than releasing a product that's easy to crack...

1
  • 3
    WET can mean: Write Everything Twice
    – StuperUser
    Dec 13, 2011 at 17:44
3

If I understand you properly, there is too much going on in the class. That creates methods that do not follow the single responsibility principle. Leading to code that needs to be moved around, pieces taken while others left out. This could also create a lot of members.

You should also review the accessibility modifiers. Ensure those things that are public, should in fact be public. The consumer doesn't need to know about every little member...use encapsulation.

This calls for a refactor. It also appears that code is being written with no upfront design. Look into Test Driven development. Write the code how it should be called rather than calling code however it is implemented. Look into TDD for some hints on how to accomplish the task.

3

If you're copying code, you'll introduce a technical debt of double maintenance or more specifically: code duplication.

Usually this is fixed through refactoring. More specifically you redirect all the calls to a new function (or a new method in a new class) that has the common code. The easiest way to start is to remove all the copied code and see what breaks, in which you fix by redirecting the calls to the common code.

Getting your customer to agree to refactor code may be difficult since it is hard to convince a non-technical person to fix a technical debt. So the next time you give time estimates, just include the time it takes to refactor to your estimates. Most of the time customers do assume you're doing clean up of the code during the time you do the fix.

1

Sounds like spaghetti code to me. The best fix is a refactor/rewrite.

a pejorative term for source code that has a complex and tangled control structure, especially one using many GOTOs, exceptions, threads, or other "unstructured" branching constructs. It is named such because program flow is conceptually like a bowl of spaghetti, i.e. twisted and tangled...

http://upload.wikimedia.org/wikipedia/commons/thumb/9/93/Spaghetti.jpg/175px-Spaghetti.jpg

6
  • -1 Refactor and rewrite are two very different options. Total rewrites, throwing software away, is never a good idea. joelonsoftware.com/articles/fog0000000069.html Sep 12, 2011 at 13:49
  • 1
    Spaghetti code is IMO a much more general - and looser - term. Although such code often contains duplcations, you can have spaghetti code without any duplication, and also highly duplicated but not spaghetti code. Sep 12, 2011 at 13:51
  • @P.Brian.Mackey I never said that Refactor and rewrite were the same thing. OP should decide which to use. Sep 12, 2011 at 13:54
  • 2
    I was never a fan of that article. I agree that the rewrite was a bad idea in the example cited, but just because it was a bad idea in that instance doesn't mean it's always a bad idea. For starters, will doing the rewrite block any other progress? If so, that's bad; if not, well then that's not nearly as bad.
    – jhocking
    Sep 12, 2011 at 14:25
  • @jhocking - I believe the point of no-rewrite policy is not that of blocking progress in other programs, rather loss of real fixes over time. That magical "if(goldenNugget > 22)" while poorly named, still solves a specific problem that may well be impossible to identify without hours or days of research. Now, taking that same data and improving it is what should be done instead. That is a refactor. Throwing it out and saying "we'll do it right next time" is a waste of time. The same reason resolving already solved problems is a waste of time. Adding good code on top of bad increases debt Sep 12, 2011 at 18:01
0

You say you cannot completely blame A - but copying a class this way is actually unforgivable. It’s a massive failure in your code review process. It’s possibly the most massive failure, having no code review at all.

IF you ever think you have to produce awful code to meet a deadline, then the absolute highest priority request for the release after that should be to fix the awful code NOW. So your problem is gone.

The DRY principle is for situations that are not quite perfect and can be improved. Duplicating a class is a whole new caliber. I’d first call it “ duplicated code”, and over time it will change to the worst of all time wasters, “divergent duplicated code”: multiple copies of the same code that are almost, but not quite identical, and nobody knows if the differences are intended, coincidence, or bugs.

-3

Almost a decade late to this party, but the name of this anti-pattern is Divergent Change, where multiple classes include copies of the same behavior but as time and maintenance progress and some classes are forgotten, those behaviors diverge.

Depending on what the shared behavior is and how its shared, it could instead be called Shotgun Surgery, the difference being that here a single logical feature is provided by many classes rather than a single one.

1
  • 1
    This doesn't look like the same thing. Divergent Change is when many changes are made to the same class. The OP describes code duplication. Shotgun Surgery isn't the same thing either. Shotgun Surgery describes the same change made to several different classes. Apr 5, 2019 at 21:56

Not the answer you're looking for? Browse other questions tagged or ask your own question.