8 ms·
This whole article is based on a bad reading of the problem. The problem that happens when code is first duplicated is that the correct abstraction is a fundam
by lamontcg 3y ago
This whole article is based on a bad reading of the problem.
The problem that happens when code is first duplicated is that the correct abstraction is a fundamental UNKNOWN.
If you knew the right way to de-duplicate it, you would of course always construct that abstraction, because that would always be better.
What happens in practice is that the wrong abstraction is usually chosen.
Then that incorrect abstraction isn't usually held around because of "[feeling] honor-bound to retain the existing abstraction" (if that's a direct quote from Sandi then I disagree with the quote and feel it has entirely the wrong emphasis). The problem is that it is always easier to add a new knob to the bad abstraction than it is to go back and de-dup the whole code and fix the abstraction. So the bad abstraction tends to accrete more bad abstractions on top of it until it becomes a mess because of doing the cheap, easy thing.
We should not do that. But the realities of software development are that when you are dealing with an orthogonal problem, you WILL wind up adding a knob to something that can be done in a day, rather than taking 2 weeks to refactor a different subsystem that your original problem only barely touches and isn't the primary concern of whatever business objective you are trying to deliver.
So the advice is to let it sit for awhile. Let the code accrete a few more requirements over the weeks or months ahead, and when you find yourself doing a double edit to both sides of the code and the right abstraction is clear to you then go ahead and de-duplicate it.
Note that if the problem is TRIVIAL then go ahead and de-dup it right from the start. This isn't advice for junior programmers who are faced with something as simple as dropping two hash keys into an array and then iterating over it so that it makes it easy to add a third key. This is more about having two classes which are fairly similar and extracting a whole base class and jamming all the shared code into the base with a tightly-coupled poorly-thought-out "wide" interface (using inheritance as a hammer to de-dup code). And the whole problem becomes even worse if someone external might come along and pick up that base class and start using it with the existing API and you might be locking yourself into a shitty API that you can't change without breaking backwards compatibility.
And even if you're in a "non-OO" language like Go you can still make this mistake by designing bad interfaces, it is the exact same thing.