4 ms·
> What does YAGNI even mean if it can stand in opposition of DRY? If it just means "you don't need to do that," and "that" can mean whatever you want, then it's
by lstamour 3y ago
> What does YAGNI even mean if it can stand in opposition of DRY? If it just means "you don't need to do that," and "that" can mean whatever you want, then it's not a useful guiding principle.
> YAGNI is about functionality, DRY is about structure.
I absolutely see where you’re coming from and I agree, the reason DRY caught on and YAGNI hasn’t is indeed the vagueness of YAGNI. But I would equally argue that the simplicity of DRY is what gets you in trouble if you over-optimize for DRY regardless of context.
DRY can be about functionality: if you’ve already implemented a feature, even if it’s a library maintained by another team, as long as the tests encourage your use case, you should re-use existing functionality over creating yet another abandoned half-baked attempt at something.
YAGNI, by opposition, might suggest that the effort spent learning the other team’s library and maintaining a connection to what might be brittle code is itself overhead. A similar debate can be found in using an npm library. DRY would argue if you already use the library, keep using it. YAGNI would argue if the library is only used in one place, rip it out for simplicity and replace it, especially if the code is old.
Taken to extremes, DRY is how we end up with a left-pad module on npm while YAGNI is using padStart built-in to modern JS. Likewise taken to extremes, YAGNI may result in missing functionality and unmaintainable spaghetti code, while DRY is one possible approach to taming complexity in codebases. Both are essential principles, neither actually more important than the other.
I agree with JUCS, but it’s even less defined than YAGNI ;-)
- mike_hock 3y agoThis over-generalization of vague concepts isn't helpful. An example of DRY would be: You're using libraries "foo" and "baz," and whenever foo::get_bar() returns 1, 2, or 3, you need to call (for your use-case) baz::qux(9), baz::qux(31), or baz::qux(-5), respectively. So you create one function that either handles both calls completely, or at least maps the return value from get_bar to the argument required by qux. The violation of DRY would have switch statements littered throughout the code that all do the same mapping manually. A build-or-"buy" decision isn't about being DRY or not.