So your point is that refactoring is so often done badly, that it's better off if everyone cut & pastes?
In one sense, this doesn't surprise me. I remember doing lots of ill-advised refactorings when I was younger. Refactoring is a nifty idea, and so it's easy to be enamored of it and eager to apply it like it's a new toy. I'm sure lots of people act this way with new power tools and often the resulting "oops" gets thrown in the scrap bin.
The problem with refactoring code, is that recognizing the "oops" is harder. Probably, the thing still runs and all the tests still pass. It requires putting yourself in the shoes of someone who hasn't seen the thing before. It's not like seeing that you gouged a sanded surface. It's more like realizing that the technique you were so fond of conflicts with the composition. Not only is it subtle, you often also have to be mature enough to swallow your pride.
That said, a properly done poor refactoring is still superior to copy & paste. Why? Because, done correctly, you can pretty much guarantee finding all the places you need to change. With cut & paste, in a large codebase, you need to do some inspired searching and second-guessing -- and this is where the major risk comes in when you have to change something. You're still going to need some of that in a large codebase, even when it's very DRY. The smart move is to minimize that as much as possible, because again, that is where the risk comes in.
Ultimately, refactoring and DRY should be thought of, at its core, as a clerical tool. You need to take steps to ensure that ideas don't get lost in the codebase -- those give rise to bugs. However, you should only take those steps when the downside risk of ideas getting lost definitely outweighs the risk of making a mistake and introducing bugs or decreasing code clarity and flexibility.
The article talks about when to refactor: when you are making the code more closely resemble the product specification.
I'm disappointed that the key point of my entire article, which is the difference between accidental sameness and essential sameness, was apparently misconstrued as an attack on all refactoring.
In one sense, this doesn't surprise me. I remember doing lots of ill-advised refactorings when I was younger. Refactoring is a nifty idea, and so it's easy to be enamored of it and eager to apply it like it's a new toy. I'm sure lots of people act this way with new power tools and often the resulting "oops" gets thrown in the scrap bin.
The problem with refactoring code, is that recognizing the "oops" is harder. Probably, the thing still runs and all the tests still pass. It requires putting yourself in the shoes of someone who hasn't seen the thing before. It's not like seeing that you gouged a sanded surface. It's more like realizing that the technique you were so fond of conflicts with the composition. Not only is it subtle, you often also have to be mature enough to swallow your pride.
That said, a properly done poor refactoring is still superior to copy & paste. Why? Because, done correctly, you can pretty much guarantee finding all the places you need to change. With cut & paste, in a large codebase, you need to do some inspired searching and second-guessing -- and this is where the major risk comes in when you have to change something. You're still going to need some of that in a large codebase, even when it's very DRY. The smart move is to minimize that as much as possible, because again, that is where the risk comes in.
Ultimately, refactoring and DRY should be thought of, at its core, as a clerical tool. You need to take steps to ensure that ideas don't get lost in the codebase -- those give rise to bugs. However, you should only take those steps when the downside risk of ideas getting lost definitely outweighs the risk of making a mistake and introducing bugs or decreasing code clarity and flexibility.