You have 5 places in code where you draw a blue rectangle:
drawRectangle("blue", x0, y0, x1, y1);
Do you refactor them into drawBlueRectangle(x0, y0, x1, y1)?
It seems you removed the duplication but you didn't. Because if you now have the requirement to draw red rectangles instead you surely won't leave it as
So instead of changing 5 places you now have to change the invocation in 5 places and implementation in 1 place.
You can argue it's because you named it wrongly, it should be "drawWhateverThingTheyHaveInCommonRectangle" instead, for example drawHighlightingRectangle. And you'll be right.
But you don't know if they will have that thing in common forever. And splitting the code is harder than refactoring it, so it often leads to code like this:
This code may seems ok, but it tends to grow business logic inside, and you don't immediately know what combinations of deciding factors are actually possible without looking at all the invocations. So either you look at all the invocations before implementing your change (and then the refactor didn't actually save you any work - what does it matter if you look at code and change it vs just look at code and change stuff elsewhere), or you ignore the invocations and add your change in isolation (probably writing code that is redundant and overcomplicated because you handle cases that cannot happen).
This is obviously oversimplified example, but I've done these exact mistakes several times :)
I think you should ask yourselves why you are drawing blue rectangles. What is their purpose? Do they just happen to be blue? Or are they blue because they have they all "do the same job"? Maybe you should have
drawInlineHelpBox(x0, y0, x1, y1)
or
drawEnergyShield(x0, y0, x1, y1)
We can see from the language that unlike your example this is a true abstraction. You went from color parameter to a specific color. It's both phrased in terms of colors.
But here we go from color to ui elements. The terminology is completely different.
Yeah, the idea of DRY is simple, but it doesn't change the fact that you have to use your judgement, do and learn from mistakes etc. Nothing ever does.
then call separately? Depends on the number of calls to drawHighlightingRectangle I guess.
Something I've learned recently is to try to think in terms of behaviours, then compose them instead of mixing them together. Also it's easier to juggle the pieces by erring on the side of decomposition initially, then recompose a bit once they're organised, but only if it makes more sense.
DRY is not very useful as a concept. It doesn't define any rules how to identify bad repeated code, nor how to change it and doesn't define limitations of the concept or it's application.
I know this sounds wild and harsh but we have to overcome the habit of explaining non trivial or even unsolved problems with truisms.
In my last interdisciplinary role, I tried to simplify this as "you drew circles around the wrong parts". If many lines still cross the module boundary...