4 ms·
This is why some advice from Sandy Metz really stuck with me. It is not a problem to /have/ the same code 2, 3 or even 4 times in a code base. In fact, sometim
by tetha 2y ago
This is why some advice from Sandy Metz really stuck with me.
It is not a problem to /have/ the same code 2, 3 or even 4 times in a code base. In fact, sometimes just straight up copy-paste driven development can be a valid development technique. Initially that statement horrified me, but by now I understand that just straight up copy-pasting some existing code can be one of these techniques that require some discipline to not overdo, but it's legit.
And in quite a few cases, these same pieces of code just start developing in different directions and then they aren't the same code anymore.
However, if you have to /change/ the same code in the same way in multiple places, then you have a problem. If you have to fix the same bug in multiple places in similar or same ways, or have to introduce a feature in multiple places in similar way - then you have a problem.
Once that happens, you should try to extract the common thing into a central thing and fix that central thing once.
It feels weird to work like that at first, but I've found that often it results in simpler code and pretty effective abstractions, because it reacts to the actual change a code base experiences.
- progmetaldev 2y agoI think another big part of deciding to use DRY is the complexity of what you're repeating. Copying and pasting lots of business rules means having to make complex edits whenever that logic needs to change. Having simple rules and a small amount of surface area for data reduces the initial need to have DRY code, and it's easier to take the initial risk of using duplicate code. At least in my experience, it's easier to start with duplicates of simple logic/data, and use DRY for more complex logic/data. The difficult areas are still those where the logic and/or data fall between simple and complex, or are expected to change often, but unknown whether they will change together or diverge quickly.
- nostrademons 2y agoThe challenge is that if you're not careful, you can end up copy-pasting the same bit of code hundreds of time before realizing it has to be changed. I once worked in a year-old startup of ~5 developers that found it had written the same line of code (not even copy-pasted, it was only one line of code so the devs had just written it out) 110 times. A bug was then discovered in that line of code, and it had to be fixed in 110 places, with no guarantee that we'd even found all of them. This was a very non-obvious instance of DRY, too, because it was only one line of code and the devs believed it was so simple that it couldn't possibly be wrong. But that's why you sometimes need to be aware of what you're writing even on the token level. That's why we have principles like "3 strikes and then you refactor". 3 times fixing a bug isn't too onerous; even 4-6 is pretty manageable. Once you get to 20+, there starts to be a strong disincentive to fixing the bug, and even if you want to, you aren't sure you got every instance.
- tetha 2y agoOh yeah we've had those as well. I kinda feel two things about these at the same time. At a practical level, these situations sucked. Someone had to search for the common expression, look at each instance, decide to change it to the central place or not. They spent 2-3 days on that. And then you realize that some people were smart and employed DRY - if they needed that one expression 2-3 times, they'd extracted one sub-expression into a variable and suddenly there was no pattern to find those anymore. Those were 2-4 fun weeks for the whole team. But at the same time, I think people learned an important concept there: To see if you are writing the same code, or if you're referring to the same concept and need the same source of truth, like the GP comment says. I'm pretty happy with that development. Which is also why my described way is just one tool in the toolbox. Like, one of our code bases is an orchestration system and it defines the name of oidc-clients used in the infrastructure. These need to be the same across the endpoints for the authentication provider, as well as the endpoints consumed by the clients of the oidc provider - the oauth flows won't work otherwise. And suddenly it clicked for a bunch of the dudes on the team why we should put the pedestrian act of jamming some strings together to get that client-id into some function. That way, we can refer to the concept or naming pattern and ensure the client will be identical across all necessary endpoints, over hoping that a million different string joins all over the place result in the same string. In such a case, early or eager DRY is the correct choice, because this needs to be defined once and exactly once.
- spion 2y agoThis really makes me think we should be focusing on cost/benefit, risk/reward, pros/cons at all times. If we have a bug in these 5 copies, will it be too hard to fix in all of them? No? What about these 10 copies? If that sounds like its starting to get difficult, maybe now is the time.
- danielmarkbruce 2y agoThat means you have to think. Most people hate thinking. Seriously.
- laserlight 2y ago> If we have a bug in these 5 copies, will it be too hard to fix in all of them? Yes, it will be, because copy-pasted code is never the same verbatim. First and foremost, name changes make it almost impossible to identify different copies. Then, there are different tweaks for each copy to make it suitable for the context. I always DRY early, because it's always free to copy-paste later.
- gmueckl 2y agoConversely, trying too hard to DRY when requirements at call sites start to diverge can lead to an unnecessary complex single implementation of something where there could be two very similar but still straightforward pieces of code.
- wging 2y agoYou're thinking of Sandi Metz: https://sandimetz.com/blog/2016/1/20/the-wrong-abstraction https://sandimetz.com/blog/2016/1/20/the-wrong-abstraction
- deleted 2y ago[deleted]