I wholeheartedly agree with the author where he talks about documentation. Documentation is presentation, and you present to different audiences. You will repeat concepts.
However, duplicate code is the greatest sin in software design. Almost every good practice or rule we have conjured is an attempt to reduce code duplication. Redemption comes in the form of abstraction. How could anyone defend duplicate code?
The author mentioned two kinds of duplication in tests. The first is a case of "You're doing it wrong." Here is a good rule of thumb for tests: if you find yourself copy-pasting between the code you wrote and the test you write for that code, you are not testing the code. Find an alternative way to test it. You will find a lot more value in it.
The second is a discussion of setup and teardown being repeated. You are writing a lot of extra noise. Perl's Test::Class, for example, allows you to write one setup and teardown for all the tests in a Test::Class child. Reduce copy-paste by grouping together classes of tests. Even without a nice test framework, setup and teardown are trivial to implement yourself. Don't write tests that are a series of lines in one large main function.
Sometimes you can factor out this duplication. However, in less dynamic languages like C, it may not always be easy to do so.
What does this "less dynamic" mean? The example is easy to refactor into a function for both:
stuff(1);
call_something_unrelated();
stuff(2);
C can abstract. It is not as good at abstracting as Lisp (what language is?), but there are solutions for most situations.
Don't ever accept the idea that code duplication is legitimate.
DRY when it makes things simpler. Sometimes you would have to make things so much more complicated in order to completely not repeat yourself that it ends up not being worth it if it's not maintainable or difficult to debug what it's doing.
The point of DRY is to keep things simple and more maintainable. If DRY ends up making things more complicated and less maintainable overall then hold your nose and use your judgment. DRY makes some people miss the forest for the trees; KISS is better than DRY, which ought to be subservient to it.
If your DRY code is "excessively bound", then by definition you have repeated yourself. The binding which must be expressed on both sides is repeated on both sides. A better language could factor it out.
For any given excessive binding, the "better language" that can factor it out may not yet exist... but then again, you might be surprised. One of the most interesting things about learning Haskell is to see the way that community has used Haskell to refactor out code that you would literally never even conceive of factoring out in another language. The "magical mystical monad" is nothing less and nothing more than the refactoring of a certain common, recurring bit of code; it is worth your time as a developer to progress your Haskell knowledge to the point that you understand what I mean by that, even if you never use Haskell itself. In fact the recurring code in question is actually very, very small, and I've gone from confused about why they do it to astonished at how obvious it is in hindsight and how thoroughly we've screwed up a very simple concept for lo these sixty years.
I completely agree. I think DRY is a very single-developer orientated aspect. There is value in repeating your self or copy and paste programming as that can enable further polish and customizing where DRY causes more intense mental activity to keep everything clean.
However, duplicate code is the greatest sin in software design. Almost every good practice or rule we have conjured is an attempt to reduce code duplication. Redemption comes in the form of abstraction. How could anyone defend duplicate code?
The author mentioned two kinds of duplication in tests. The first is a case of "You're doing it wrong." Here is a good rule of thumb for tests: if you find yourself copy-pasting between the code you wrote and the test you write for that code, you are not testing the code. Find an alternative way to test it. You will find a lot more value in it.
The second is a discussion of setup and teardown being repeated. You are writing a lot of extra noise. Perl's Test::Class, for example, allows you to write one setup and teardown for all the tests in a Test::Class child. Reduce copy-paste by grouping together classes of tests. Even without a nice test framework, setup and teardown are trivial to implement yourself. Don't write tests that are a series of lines in one large main function.
Sometimes you can factor out this duplication. However, in less dynamic languages like C, it may not always be easy to do so.
What does this "less dynamic" mean? The example is easy to refactor into a function for both:
C can abstract. It is not as good at abstracting as Lisp (what language is?), but there are solutions for most situations.Don't ever accept the idea that code duplication is legitimate.