Why software ends up complex
This is one vector for complexity, to be sure.  Saying "no" to a feature that is unnecessary, foists a lot of complexity on a system, or has a low power to weight ratio is one of the best skills a senior developer can develop.One of my favorite real world examples is method overloading in Java.  It's not a particularly useful feature (especially given alternative, less complicated features like default parameter values), interacts poorly with other language features (e.g. varargs) and ends up making all sorts of things far more complex than necessary: bytecode method invocation now needs to encode the entire type signature of a method, method resolution during compilation requires complex  scoring, etc.  The JVM language I worked on probably had about 10% of its total complexity dedicated to dealing with this "feature" of dubious value to end users.Another vector, more dangerous for senior developers, is thinking that abstraction will necessarily work when dealing with complexity.  I have seen OSGi projects achieve negative complexity savings, while chewing up decades of senior man-years, for example.