Assume we have a software module A that implements a function F. Another module B implements the same function as F'.
There are a number of ways to get rid of the duplicate code:
- Let A use F' from B.
- Let B use F from A.
- Put F into its own module C and let both A and B use it.
All of these options generate additional dependencies between modules. They apply the DRY principle at the cost of increasing coupling.
As far as I can see, coupling is always increased or at leased moved to a higher level when applying DRY. There seems to be a conflict between two of the most basic principles of software design.
(Actually I don't find it surprising that there are conflicts like that. This is probably what makes good software design so difficult. I do find it surprising that these conflicts are normally not addressed in introductory texts.)
Edit (for clarification): I assume that the equality of F and F' is not just a coincidence. If F will have to be modified, F' will likely have to be modified in the same way.
you should copy/paste F into B just for the sake of maintaining the conceptual autonomy of A and B but I haven't ran into a scenario where I would do that.
Both are valid approaches depending on the context. For example, just becausePerson
andCountry
both have astring Name
property doesn't mean that they share the same reused property. If a country's name becomes anint
, that doesn't mean that people's names also get turned intoint
. You should only abstract reused logic and you should avoid abstracting currently similar logic. – Flater Jul 16 '18 at 09:26Name
if it was complex enough and let both classes use it. If it were just a "property" with little behavior I might copy/paste it. Though to be fair I am currently maintaining a codebase where the author copy/pasted an entire giant class including duplicated mathematical function implementations that have no reason to differ between implementations, so I've been living the "copy/paste cleanup" life for a while now. – jrh Jul 16 '18 at 16:41