DRY says not to write the same code twice. I think a better rule of thumb is to not write code three times.
The second time you need to solve some problem that’s similar to a problem already solved by your code, resist the urge to update the existing stuff to also solve the new problem. Solve it again, without reuse. The third time you come across the problem is the time to generalize.
The thought of “this is almost the same as that other thing” is often a little off—there’s some essential difference that sits awkwardly between the two. Going through with the second implementation forces you to expose those little differences and write them down fully. When you come to write the third, generalized version, you’ll have two complete implementations to refer to and draw analogies between. You’ll be able to see the pitfalls that one or the other solution fell into. And you’ll have a third data point to draw on when understanding what the general solution needs to address.
And maybe a third problem will never arise, and you’ll have saved yourself the effort and complexity of generalizing.