In my experience the OP is right. The worse problem is when you eliminate duplications in the wrong place or using the wrong abstraction, leading to brittle abstractions that break in the future.
However what I've seen happen on multiple occasions is somebody merrily driving along churning out code then suddenly hitting the "ohhh - duplication is bad" wall and halting as they feel their way around the duplication and abstract they may need (or may not - since they've not written the code yet).
Duplication is not a mortal sin. Having it sit there for a few hours while you work out the meat of the problem isn't going to kill any kittens.
And often the easiest way to fully grok the abstraction that you need is to make the duplication really, really obvious.
I do agree that for newbie devs, your approach is a good one, but I think that as folks get more experience, shortcuts often are appropriate.
A pattern I sometimes see with newbies who understand the value of DRY is - as soon as they get to the point when they're about to repeat something or about to copy and paste - they stop themselves and start refactoring to remove the duplication they haven't typed into existence yet. They see adding the code that will produce the duplication as bad / waste.
Don't do that.
It's hard - because the code that they've not typed or copy/pasted doesn't exist or work yet. It's still in their head.
Make the duplication explicit first.
Type it out. Copy and paste. Change those two branches so they have exactly the same structure.
When you've done that - and everything is working and all tests pass - then refactor the heck out of it.
Much simpler, faster and less error prone.