I believe that humans are terrible at predicting the outcomes of complex systems over time and that software you get paid to write is always a complex system. Therefore, the best way to make your software better is to choose the option that produces less state. This has been my guiding principle of software development for about 6 years. The main problem I ran into is that going too far results in software that's hard to maintain because control flow jumps around.
My solution has been to think of code locality as being valuable. I start off writing something the straightforward way. When I go to implement something similar, I decide whether to abstract the code or not based on how much easier/harder it will be to naively trace the code. If I've done this thing 3 or 4 times, it's a concern and should be separated. If I'm just making something shorter/"nicer"/DRYer I should probably just write stupid code.
My solution has been to think of code locality as being valuable. I start off writing something the straightforward way. When I go to implement something similar, I decide whether to abstract the code or not based on how much easier/harder it will be to naively trace the code. If I've done this thing 3 or 4 times, it's a concern and should be separated. If I'm just making something shorter/"nicer"/DRYer I should probably just write stupid code.