15

I've inherited some research code where there's already a fair amount of code duplication: on several occasions, the original author duplicated a file and changed minor things to calculate a variation of the original problem. I'm tasked with making modifications to calculate a different variation. Following the style that's already going on, I could complete the task by duplicating and modifying 4-5 files. But, I started doing this and felt I was just making an already somewhat disorganized project, worse.

To be slightly more specific: say there's some class (this is C++) Foo whose definition makes use of some other class Bar. One possibility is to copy Bar to Bar2 and make minimal changes, and then copy Foo to Foo2 with some minimal changes including changing all instances of Bar to Bar2.

Alternatively, I could make use of templates: change Foo to FooX<BarX>, and then have Foo and Foo2 be aliases for FooX<Bar> and FooX<Bar2> with a handful of redefined functions. To me this feels like the right thing to do, but my worry is mostly that it increases the level of abstraction (there's already some templating going on so this will cause nested templates FooX<BarX<Baz>>) and it's unlikely there will be a third use of FooX.

I guess the general question it to what extent one can excuse code duplication by (1) reduction of questionably useful abstractions; (2) following somewhat questionable preexisting patterns.

1

2 Answers 2

19

Code duplication is not always a severe issue. It becomes an issue if both of the duplicates are still in use and hence under maintenance, which will impose a certain probability the duplication will cause the neccessity for fixing bugs or refactorings in several, duplicate places, and in consequence, will often lead to more bugs and inconsistencies.

So the first thing you need to check here is the life cycle of the code in stake:

  • are the original files / original calculations not in use any more, and only the duplicates / new variations under maintenance? Then the duplication is ok.

  • or is it expected that code duplication will also duplicate maintenance and evolvement efforts? Then keeping the code DRY should be the most sensible approach.

To my experience, in "research code" the first case happens more frequently than in "business code" (but YMMV).

Note for reducing duplication, you will always need to do some refactoring, and you need to make sure you don't break existing functions that way. For this, you need to have automated tests in place (using refactoring tools is also a good idea, if your IDE provides them) - make sure you have those before changing the existing code base.

For your question about "abstractions vs duplication": there is this cite from Sandy Metz "duplication is far cheaper than the wrong abstraction". When you are going to avoid duplication by abstraction, keep in mind there will be always a trade-off involved, and when an abstraction later turns out to make the evolving code overly complex, don't hesitate to turn the wheel back and use some duplication again if that's cheaper.

See also:

7
  • "are the original files / original calculations "frozen", and only the duplicates / new variations under maintenance? Then the duplication is ok" - I would say this is more like a vague guideline rather than a rule, or it's just one factor in the decision. If you're often duplicating the same code, then refactoring could probably save a lot of the time and effort that would've been spent on subsequent duplication. Also, a lot of duplication can make it a lot harder to broadly understand what's going on in a project. Commented Sep 8, 2021 at 11:46
  • 2
    @BernhardBarker: maybe I did not make this clear enough: surely you can make a duplicate of some code and refactor the new version. But frozen code which is not under maintenance any more cannot not cause any maintenance efforts by nature. In research projekts, it is not uncommon to have "experimental code", and once an experiment is over, the old version might only be kept for comparison purposes only, not intended to be changed or bugfixed any more.
    – Doc Brown
    Commented Sep 8, 2021 at 12:35
  • bool isUnderMaintenance(Code c) { if(you'reMaintaining(c)) { return True } else { return True }. Commented Sep 8, 2021 at 17:55
  • 1
    ...or more precisely: yes, research code often ends up frozen after the experiment – but if you ever rely on this, Murphy guarantees that someone will end up using the “frozen” version and complaining about a bug there that has already been fixed in the copy. Commented Sep 8, 2021 at 17:57
  • 1
    @alephzero: though your assessement of academic programming practicces is probably correct, that's not what I had in mind. Lots of research projects have a limited time frame, and no commercial pressure, When they end, often the code involved will not be used any more. Scientists often leave after a few years their institut, new ones come and create something new. Sure, this is simplified and not true for every project, but it is not uncommon. So long-term maintenance is often not a top-priority in certain research areas.
    – Doc Brown
    Commented Sep 9, 2021 at 9:19
20

The general rule of thumb is "three strikes and you refactor": you will generally see a useful abstraction emerge by the time you've written your third implementation of something. This doesn't mean that you should never abstract earlier, but it might be harder to come up with the right interface that will fit future implementations.

In your case, if you're just copying most of the code unchanged and only making minor modifications, there's a good argument for abstracting out the part that actually changes, especially since you said this has already been done once before. But there are always other factors to consider such as whether this is just a prototype that you plan to throw away or if other people will be reading/extending this code in the future.

2
  • 20
    As an aside, I always preferred "count like a caveman: one, two, many" over the three strikes rule, but maybe that's bc my culture is not into baseball.
    – Flater
    Commented Sep 8, 2021 at 7:25
  • @Flater: I think I'm going to start using that one now. :)
    – casablanca
    Commented Sep 9, 2021 at 1:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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