Yes, you read that right. Duplicating code (a.k.a copy + paste) can be a good thing. Namely when the abstraction that would replace repetitive portions of your codebase is a pain to understand.
Yes, this 1000 times! DRY or any pattern/principle is not some sort of universal truth/declaration of ultimate goodness from your deity or some deep law like the Heisenburg Uncertainty Principle! It's just a rule of thumb. As a practical technologist, you must always implement with respect to the contextual cost/benefit. Taking any principle as an automatic ultimate good is simply intellectual laziness!
I was in a company with a Java product and a Smalltalk product. The Smalltalk product was rather well factored. We had a policy of rewrites to keep things architectually clean. We had the fantastic Smalltalk Refactoring Browser as our IDE, and we weren't afraid to use it. (To this day, you can refactor an order of magnitude or more faster with it than you can in other languages.) The Java product consisted of many independent parts with tons of duplicated code between them. Definitely not DRY. (There were also 20X more Java programmers than Smalltalk, for a comparable product.)
One thing I noticed, is that bugs on the Java side were more prevalent, but never affected the entire application. Whereas, the far better factored Smalltalk product could occasionally have the rug pulled out from underneath the entire application by the introduction of a library bug. (Though it would be very rapidly fixed.)
Another thing at that shop: We had a policy of only empirically verified DRY. We never wrote code to DRY in anticipation: only in response to actual code duplication. Generally, actual practice and experience is better at producing exactly the needed architecture than the prognosticating cleverness of programmers.
EDIT: Shower thought! (Yes, I literally got out of the shower just now.) There is a lot of emphatic but somewhat thoughtless application of principles and rules of thumb because it's actually motivated by signalling. The priority is actually on the opportunity to signal and not on the underlying cost/benefit calculation. There is a nice analogy for this in music. Once a musical scene gets a certain degree of prominence and/or commercial success, people start prioritizing sending the signal that they are part of that musical scene. So you will find bands and musicians using those techniques and stylistic flourishes, not because of the underlying aesthetic principles in support of the particular piece of music, but as an opportunity to signal. This happens in OO and also in the startup scene. (And, OMG, but is signalling given a lot of energy in the Bay Area!)
So the insider move is this: Look for the underlying motivation behind the signal. Did this person jump on the opportunity to signal, or did they first seek out the information to make the determination of cost/benefit? How carefully did they do that? (Hopefully, we can get some of the hipsters/pretenders to at least go through the motion of doing the above. Even just going through those motions turns out to be beneficial.)
A lot of software developers are awful story tellers, and what they end up using for abstractions sounds like something George Orwell would cook up.
And when those developers discover TDD, then their code spends multiple pages saying nothing at all. Oof.
I think deep down most of us intuit that this is a problem. We will persue an articulate but not particularly bright candidate and pass on someone who quickly arrives as the solution without showing any work.
But we let in people with good verbal and poor written skills and they create deserts, their code is so dry. No, I don't want you to explain to me again how great your code is. I just want to be able to follow it without using a debugger. Because maybe this bug isn't even in your code and I just want to make a determination and keep moving.
No I meant newspeak. If you name everything in an app with noncommittal things and then use them in different spots to mean different things, you end up with code that has to be memorized to be understood.
As someone more eloquent said, they are so afraid of making a bad decision that they try not to make any at all. Everything is named neutral words like 'context' or 'options', the verbs are neutral too, and there are other code flows that use the same name with different data.
As a general rule, if you would describe a code flow out loud in plain English, and not use any of the nouns or verbs that appear in the code, someone has ruined that piece of code.
I would say that the article simply states the obvious: bad abstractions are bad, but for some reason that I'm missing tries to derive from there that copy and paste sometimes is good.
And the quoted comments persist in the same illogical path.
Saying that bad abstractions are a bad thing and then copy and paste must be a good thing in some cases is simply a non sequitur.
There is no whatsoever correlations between the two statements.
And if you want to know my opinion, blind copy and paste is always bad.
Especially in codebases over 1MLOC.
Those bugs that you have to fix multiple times in multiple places will kill yourself and, believe me, you will really curse whoever thought that doing a copy and paste was a good idea simply because they couldn't see a better solution.
These kind of trends in HN, that now I'm seeing more often, make me terribly sad, it's like promoting mediocrity instead of a well thought solution just because of laziness.
If you can't understand some abstraction then try harder, or if the abstraction is not good then find a better solution.
But PLEASE don't start to copy and paste and above all don't start promoting this abomination.
Source: I wrote a lot of copy and paste when I was too young to understand and I had to read too many copy and paste when I stopped doing it.
Saying that bad abstractions are a bad thing and then copy and paste must be a good thing in some cases is simply a non sequitur.
What happens when you are under deadline and you understand just enough to make a bad abstraction, but not enough to make a good abstraction? So here, you seem to have an underlying assumption of timeless omniscience. (This is common in people attracted to absolutes and abstractions.) By all means, if you have the time to make the right abstraction and DRY, then please do that. However, it's just as fallacious to suppose that any DRY abstraction is necessarily the right thing to do. Again, it's all about contextual cost/benefit. (Most of the time, it is the right thing to do, but this certainly isn't absolute.)
To be more specific, what if you have an abstraction that lets you do DRY, but it's obtuse, it looks like it's not quite the right answer, and it would involve the modification of a library that is used by many other parts of the system for which you don't have tests? Are you certain that in all cases like this, the cost/benefit of not having to do the search in your code next week is going to be worth it?
Your case is not in favour of duplication, it is in favour of temporary duplication because of a deadline.
So I think that you agree with me that duplications is always bad, because you can justify writing whatever abomination close to a deadline, not only duplication.
But if you leave untouched that mess in the future then sooner or later it will bite your ass.
My take: I try to write it DRY first. If I fail to come up with a good intuitive abstraction after half an hour, I just write it simple and copy code.
The next day or later I come back to the code and sometimes I find a neat abstraction then, which just needed more context. Sometimes I can get rid of the whole section too...
My rule of thumb is wait to generalize something until it is repeated 3 times. If I try before I can't really know what the problem is. But if it's something that's repeated across projects, sure I tackle it right away, but then maybe it should be open source?
Half an hour? When you're first writing the code, you should know immediately if you're going to need to repeat it and what the abstraction should be. If you don't, then don't waste your time. Later, if it turns out that you actually do need to repeat the code, it should be clear at that point what the abstraction should be.
Let the actual need for duplication guide you in finding abstractions, so you don't waste your time and produce difficult-to-follow code for no reason.
>Yes, this 1000 times! DRY or any pattern/principle is not some sort of universal truth/declaration of ultimate goodness
I think "write the least code", from which DRY is derived from is universal.
It's just in competition with a few other axiomatic principles - typically the rule of least power and loose coupling, which can suffer when DRY is maximized at the cost of everything else.
>We had a policy of only empirically verified DRY. We never wrote code to DRY in anticipation
Can't agree enough with this one. The worst kind of re-factoring is that done in anticipation of future code.
Great point about signaling. You should write a blog post or something about it.
I find that many so called best practices propagate because of how engineers want to be perceived. You want to be seen as the smart guy who reads the Gang of Four book so you shove OO patterns where they don't belong. Or you let others blindly follow dogma because you don't want to be seen as the dummy who just doesn't get it.
> Yes, you read that right. Duplicating code (a.k.a copy + paste) can be a good thing.
No it is never a good thing because the code you write is the code that has to be tested and managed. If a routine you're going to copy paste 15 times has a bug you might not give a damn but the guy after you who has to clean up the mess might prefer this routine to be only in 1 place. The rule is simple, if some substantial logic is used at 2 different places it has to be refactored into its own component. Just like a variable has to be declared if a data is used at 2 different places, that's basic CS. If one has hard time to figure out what is what then it's a naming and documentation problem, not an "DRY code" problem.
10 years ago I had pretty much the same ideas that I expressed in my previous post about copy and paste.
Maybe at the time I was much more extreme given the codebase mentioned above on which I was working on.
I still don't see any argument that explains why copy and paste should be better than find a better solution, apart from laziness obviously.
Yes, this 1000 times! DRY or any pattern/principle is not some sort of universal truth/declaration of ultimate goodness from your deity or some deep law like the Heisenburg Uncertainty Principle! It's just a rule of thumb. As a practical technologist, you must always implement with respect to the contextual cost/benefit. Taking any principle as an automatic ultimate good is simply intellectual laziness!
I was in a company with a Java product and a Smalltalk product. The Smalltalk product was rather well factored. We had a policy of rewrites to keep things architectually clean. We had the fantastic Smalltalk Refactoring Browser as our IDE, and we weren't afraid to use it. (To this day, you can refactor an order of magnitude or more faster with it than you can in other languages.) The Java product consisted of many independent parts with tons of duplicated code between them. Definitely not DRY. (There were also 20X more Java programmers than Smalltalk, for a comparable product.)
One thing I noticed, is that bugs on the Java side were more prevalent, but never affected the entire application. Whereas, the far better factored Smalltalk product could occasionally have the rug pulled out from underneath the entire application by the introduction of a library bug. (Though it would be very rapidly fixed.)
Another thing at that shop: We had a policy of only empirically verified DRY. We never wrote code to DRY in anticipation: only in response to actual code duplication. Generally, actual practice and experience is better at producing exactly the needed architecture than the prognosticating cleverness of programmers.
EDIT: Shower thought! (Yes, I literally got out of the shower just now.) There is a lot of emphatic but somewhat thoughtless application of principles and rules of thumb because it's actually motivated by signalling. The priority is actually on the opportunity to signal and not on the underlying cost/benefit calculation. There is a nice analogy for this in music. Once a musical scene gets a certain degree of prominence and/or commercial success, people start prioritizing sending the signal that they are part of that musical scene. So you will find bands and musicians using those techniques and stylistic flourishes, not because of the underlying aesthetic principles in support of the particular piece of music, but as an opportunity to signal. This happens in OO and also in the startup scene. (And, OMG, but is signalling given a lot of energy in the Bay Area!)
So the insider move is this: Look for the underlying motivation behind the signal. Did this person jump on the opportunity to signal, or did they first seek out the information to make the determination of cost/benefit? How carefully did they do that? (Hopefully, we can get some of the hipsters/pretenders to at least go through the motion of doing the above. Even just going through those motions turns out to be beneficial.)