If there is one single article about programming that I hate it is this one. It is completely the wrong message. One should instead be very eager to eliminate duplication. To avoid the pitfalls that the article notes one should create abstractions that are the minimal ones required to remove the duplication to avoid over-engineering. Also one should keep improving the abstractions. That way one can turn the abstraction that turned out to be wrong into the right one. It is the attitude of constant improvement that will make one succeed as opposed to the attitude of fear of changing something that this article seems to encourage. When one does things one learns. When one is afraid to try things everything will just calcify until it is no longer possible to add any new features. What one does need to make the refactoring work is automated tests.
In 30 years, I can count on the fingers of one hand the number of times I've encountered projects that were in trouble because there was copy/pasted code everywhere and the team was not abstracting out of fear of breaking the existing code.
What I have encountered is dozens of projects that had essentially ground to a halt because of numerous deeply, and incorrectly, abstracted systems, modules and libraries.
Correcting projects in this state has almost always been refactoring into fewer abstractions; less complex, more cohesive and less coupling.
Actually, I have in fact seen this. I worked at a place where this copy and paste programming actually lead to functions that are many thousands of lines long and are full of duplication and very deeply nested. At some point a file was split because the compiler would not handle such a large file (!). Very difficult to change anything.
And also, refactoring by removing abstraction is fine as well. The thing that is not fine is having problems and doing nothing about them. To me it seem that is what the article ultimately encourages to do.
> In 30 years, I can count on the fingers of one hand the number of times I've encountered projects that were in trouble because there was copy/pasted code everywhere and the team was not abstracting out of fear of breaking the existing code.
I think the level of experience where underabstraction is common as opposed to overabstraction is so low that it's uncommon to find a team where that gets through, because even if someone junior is at the level where it's common, they’ll get corrected before it becomes a widespread problem.
However, I've also noticed in those cases that it's very hard to get people to agree on what the problem actually is. One person's incorrect over-abstraction is another person's incompletely-DRYed-up code.