4 ms·
The problem with DRY is people will see "Oh, hey, I'm doing the same thing in multiple places. DRY says I should factor that out!" without actually thinking abo
by lostcolony 10y ago
The problem with DRY is people will see "Oh, hey, I'm doing the same thing in multiple places. DRY says I should factor that out!" without actually thinking about whether it makes sense for there to be a dependency between those pieces of code. Moving duplicated code into a shared function/method/etc -creates an implicit dependency- between all callers of that function/method/etc. That's exactly what you want in some situations (and is in fact the benefit of DRY, i.e., because when you have to fix that code for one function, you have to fix it for the other(s)), but if you do it blindly you create a dependency between two unrelated bits of code, and that's where complexity comes from, as you start adding conditionals and things to try and make that shared code handle all cases.
I find considering whether the repeated code is innately related, or in the same domain, or not, to be the best metric for determining whether I should refactor it to not repeat. It's adhering to the principle of least astonishment. Sometimes it should all stay separate. Sometimes a few pieces should be refactored to share code, and others left to repeat. Sometimes one set of the repeated code should share a function, and then the other set should share a different function, -even if that different function has the same implementation-, simply because the second set is so unrelated to the first. Sometimes they all should share the same code, because they're all related.
Breaking things into small, reusable pieces helps avoid this because the dependencies you create are on small, easily understood, easily replaced snippets, which tends to have a very clear context/domain. It's easy to prove that the abstracted function is correct, since it's so simple, and it's clear what domain(s) it involves, since again, so simple, and thus the problem with any given bit of functionality is almost assured to be the composition of those functions, i.e., your specific use of it in this one instance. You can still run into issues if you reuse some of those composed functions, however.
In general, the greater the complexity and domain specificity of the code you're trying not to repeat, the greater the danger you're shooting yourself in the foot.
FP is especially beneficial, as such, because the higher order functions that tend to be common are both pretty simple in their function, and pretty universal in their domain.
- thex10 10y agoThis comment helped me immensely. Thank you.
- deleted 10y ago[deleted]
- andy_ppp 10y agoThere was a great talk in the Elixir Meetup London by Anthony Pinchbeck about organising functionality not around MVC but the functional unit being build. So for example if you have something that is dealing with registering your website, create a directory called register_website and all models, functions and controllers to do with that code go in there. The talk suggested deleting the controllers and models directories. He also said there was duplication but everything was more loosely coupled and you could always group things in deeper functional units later. I'm not 100% brave enough to go for this structure quite yet but it certainly makes coming to a project pretty clear as you literally have a list of all the functions of the site where the code sits for each thing :-)