The problem with dry is no one tells when when to not use it. It's great when you have 5 instances of the same string, much like oop is great when all your objects are animals that fit into a neat little category. It's not so great when you're drying code across feature boundaries. Features tend to diverge over time rather than converge so what's dry one day is garbage the next. You refactor the code to be dry so 3 features are now one function and someone comes along asking for an amendment to one of those 3 features which adds an edge case to your function. Now you've broken another feature because you didnt check if your new edge case would change other features but quality control didn't check the other features cause no one asked for that feature to be changed and how do they know that it's all one function under the hood. Now you have bugs in production and no one to cover your ass. Time goes on and you add more edge cases and now you have one function that does many things with special edge cases throughput it. You cant separate one feature without interacting with another, almost like you're interacting with strands of spagetti and you can't help but pick up a bunch when you only really wanted one noodle.
Tldr if you're making code dry and you insist that you make code dry across feature boundaries then for the love of god make unit tests for those functions. Or keep your functions dry and your features wet.
Tldr if you're making code dry and you insist that you make code dry across feature boundaries then for the love of god make unit tests for those functions. Or keep your functions dry and your features wet.