Code has to be maintained, or it will eventually fail as other moving parts around it change their interfaces.
Code rots. Platform norms are always changing, so today's fresh new code becomes tomorrow's smelly old code.
Code interacts with other code. As the volume of code increases linearly, the number of these interactions increases exponentially. Eventually the complexity becomes unmanageable and the whole system has to be rebuilt. The more code you add to a system, the faster you hasten its demise.
All of which means that code is a liability, in the balance-sheet sense of the term. Throwing code at a business problem hurts the bottom line. The goal therefore becomes to throw just enough code at the problem to solve it, and not one line more than that.
This is the difference between inexperienced and experienced developers. Inexperienced developers handle code like it's spackle. Experienced ones handle it like it's uranium.
All code we write is going to be wrong in some way as a result of our understanding of the problem domain being incomplete so I'd rather see code with an obvious place to put an if statement than a lovingly constructed masterpiece of indirection and abstraction.
Obviously there are basic rules to follow, make it testable, don't mix too many concerns in one place but I see so much bikeshedding and overcomplicated code when it just needs to not be obviously wrong and easy to replace when needed.