1

In a fairly complex system with a dozen or more git repositories, most of them are done in a cookie-cutter fashion.

What is or would be your best approach to deal with duplication?

In my opinion the project creation could become a template so that you can easily scaffold another project. (so not centralized but copypasted) I would avoid centralize this code because it makes the application very stiff regarding i/o capabilities, security constrains and interfacing with your metal or cluster.

Then there is the business logic, which I would centralize in the parts that belong to the same model in the same bounded context. Copy pasting here means ensuring bugs crop up from diverging codebases.

Finally there is utility codes which appear over and over but are not part of the business logic, for example some code related to logging or monitoring. I would just copy and paste that. Centralizing this kind of code does not bring any advantage.

3
  • 1
    This is a pretty broad topic, and the reuse strategy can heavily differ depending on the number of people and teams or subteams involved. In larger teams, centralizing certain components can increase the communication efforts to a degree it compensates any savings by avoided duplication. In a smaller team of, say five people at maximum, I would recommend to stay as "DRY" as possible. And though your general strategy sounds reasonable, it sometimes pays off to develop reusable utilities, and sometimes not, this is usually a "per case" decision. – Doc Brown Feb 11 at 15:36
  • ... I was going to write an answer, but then found this Blog article "The Dilemma of Code Reuse in Microservices" which contains most of what I would have to say, and more. – Doc Brown Feb 11 at 16:02
  • "In my opinion the project creation could become a template so that you can easily scaffold another project." Templates sound appealing, but really, on day 0 when a template is instantiated, the project drifts and diverges from then on. The template could be reflected to update best practices and such, but all the existing microservices won't benefit, because they don't have a way to keep synced with the template. – Alexander Apr 16 at 22:36
2

If I understand you correctly then you should always ask:

When I want to do the same things inside of function A and inside of function B and somewhen the requirement for this implementation changes in function A: What is the probability that this change should also be applied in function B? If high probability: Centralize/Outsource this and avoid duplicated code. If low probability (maybe because the functions are only "randomly" doing some similar things): Do not outsource this, copy&paste is ok because semantically there are 2 two different things so the implementations should be independent.

2

Don’t Repeat Yourself (DRY) can be over applied. If you see x = 10 and y = 10 together it doesn’t mean you need to replace y with x. Here x and y mean different things even if they happen to hold the same value. Eliminating y destroys information and harms flexibility.

It’s the same with lines of code. Just because two functions happen to have the same lines of code within doesn’t mean one must be eliminated. Those functions do the same thing but depending on their names and what they are obligated to support when called they can still be very different functions. Ones that may soon change independently.

You must protect that need to change independently when it exists. It can be just as real as the need to change together when you’re copying around a bug.

But none of that is an excuse to blindly copy and paste duplicate code everywhere. Never just focus on getting done what needs to be done. Always keep an eye on how well you’re showing why you’re doing what you’re doing.

Unexplained duplicate code causes a serious problem because it’s been stripped of it’s meaning. Without meaning people fall back on dogma to make decisions and DRY gets over applied. If you dupe, make why you dupe clear.

1

Say you are in the UK. You have a function that adds 20% to a price. But in reality, its responsibility is to add the correct VAT, whatever that is, not 20%.

That function should be in a central place, so if you need to change it (which you would have a few times in the last ten years), it’s one change and it’s changed everywhere.

Now you have another function that converts feet and inches into meters. That function is never going to change. You can duplicate it as much as you like.

And what was mentioned elsewhere: “Add 20%” might really mean “Apply the correct VAT” or “Add some stuff for free on large orders”. So these MUST be two different functions with possibly identical code.

4
  • 1
    It's not the function necessarily that should be in a central place - the arithmetic is a simple multiplication, and that is already a standard operation, with a single definition per environment (and equivalent implementations between environments). It's the plain figure of 20% that should be central in some way. And since different products attract different levels of VAT, that central place is actually as part of your sales catalogue data. (1/2) – Steve Feb 13 at 12:38
  • And since products can move categories over time (e.g. the dispute over the "tampon tax", or the "tax on womanhood"), as well as the percentage for each category changing over time, that master data should be structured in such a way that the applicable tax category and tax rate, is looked up from the combination of catalogue product and transaction date. It's really the data that ought to be most central here, moreso than the functions which manipulate that data. (2/2) – Steve Feb 13 at 12:44
  • Steve: Abstraction. – gnasher729 Feb 14 at 12:10
  • If the function name mentions vat then it should change when vat changes. If it mentions 20%.... – candied_orange Feb 15 at 13:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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