If all we do is rail against the "new" DRY and forget the original one, then we are at a net loss.
If the change was otherwise good, I would remark on the repetition as "here's how I would write it differently" and not "go back and fix it now".
The first time someone changes four of the cases the same way but misses the fifth, though. That sounds like a good time to refactor.
a) make the same null check fix in all 3 versions, thus resulting in 3 even longer functions with the same logic
b) collapse all 3 functions into one and provide an abstraction for the "adding object to document" part
c) refactor the 3 functions to use the same helper function just to do the object initialisation
In the end I went with c) because it required the least amount of code, and the only genuine duplication really is the foreach statement. But arguably if MS had kept their library DRY in the first place we would never have ended up with so much code duplication.I remember when The Pragmatic Program 20th Anniversary came out, the authors, in interviews and the new edition itself, described DRY as "the most misunderstood" concept in the book. If for 20 years that is the most misunderstood concept, then maybe the name is not the best.
It's funny, because "dribble" or "drool" is the opposite of being dry ;)
Although it doesn't have as fun of a pronunciation in English, DRBR is probably a better acronym? Don't Repeat Business Requirements
Source of truth, system of record.
Business decisions should have a source of truth. But the domain of things we want to duplicate or not duplicate is bigger than just the business rules.
If you are asking two questions, it’s okay to have two implementations. If you ask the same question twice, you should get the same answer, not just the same output.
But miscreants can twist the meaning of five different parts of what I just said. Like what even is a business rule? It’s whatever the last thing they said before you got them to stop talking. But if they come back later and want something that disagrees with what they already asked, they’ll wriggle like a fish on a river bank trying to gyrate a way to interpret what they asked for to say you’re wrong (and therefore you should work nights and weekends and we don’t owe you a raise).
We should ditch these principles altogether and focus on teaching a deeper understanding of these concepts that captures the nuances.
In any case, the reason I go on the anti-rant rant each time is because when I use DRY appropriately, I don't want some idiot flagging me in a code review saying "Don't do this. DRY is bad. Here are N blog posts explaining why" - when none of the blog posts are complaining about what I am doing.
Flagging code in code review is another great example of harmful behaviour principles encourage. I've stopped referencing principles altogether in code review and I encourage others to do the same. Instead I focus on trying to explain the specific impact the code will have on our specific codebase.
Structuring code so that abstractions don't depend upon implementation details is in my top 3 principles of all time (along with pure functions and good typing).
DI frameworks a la Spring and Guice just annoy me.
So you refactor everything, factor out the constructor, and then it passes but now you need to add a new dependency so you're right back to the same nonsense. And/or you have tons of classes getting dependencies they don't even need, because some do so the parent has to have them all.
Traits can help some.
But the abstractions and DI that were supposed to make things easier still often make things more complicated.