There's not a more loaded, dangerous, and ambiguous term in programming than "simple". KISS (keep it simple, stupid) is probably the least helpful advice possible, especially for novice programmers. The only other competitor here is DRY.
What does "simple" even mean? Is a Django MVC-esque application simpler than, say, a full blown DDD-ed, event sourced, hexagonal service? Is an application simpler when it has a framework instead of an architecture?
In some ways, yes - it's easier to understand and get around technically, because proficiency in the framework is sufficient and proficiency in the domain is not required. At the same time, try modifying a system of this sort — in any but the least demanding of domains — after a little bit of time... Good luck with that.
The usual understanding is that simple is about less parts, but that’s not true. Welding wheels to a car's axles removes parts (lug nuts), but it arguably makes the car harder to change. It also makes the car harder to understand, because the boundary between two very distinct parts — an axle and a wheel — gets fuzzy. It becomes more challenging to understand what a car is made of.
Just to be clear, this is not an attack on Django or MVC. It's just that "simple" is context dependent, and in more than one way. What we mean by it depends on the domain under implementation, as well as the knowledge and skills we have.
With great advice comes great responsibility
Simple is defined as "easily understood or done; presenting no difficulty, without much decoration or ornamentation". A related word, simplistic, by contrast means "treating complex issues and problems as if they were much simpler than they really are". And while the difference in these definitions is striking, the boundary between the two is not at all clear cut or obvious...
At least not at first. One day you just notice that your system is so fragile that touching it in any way whatsoever resembles a game of Mikado...
The advice to “keep things simple”, “build only what you need”, and “try not to predict the future” flow from the experienced to the novice (obviously...), and the experienced don't always take the time to explain what they mean. Or even manage to remember the novice might not be equipped to understand the message as intended.
The solution? Stop pretending any software system with a TTL longer than a week can ever be described as "simple". Understand that simplistic leads to complicated, and that people will naturally gravitate towards simplistic when told to make something simple.
They will disregard, or lack the experience to appreciate, the complexity and design involved, and will just assume that if they don't “over-engineer” everything will be fine. It probably won’t.
It's a similar story with up-front design. People were told to limit (or scrap) up-front design, and they listened. Unfortunately, what was lost in translation was that it never meant don't design. It means "accept that programming is a design activity and design as you code, using the knowledge you're gaining".
The unintended consequence are systems with no design, which basically look like a steaming pile of entropy.
The hidden assumption
It seems to be implicitly assumed that it will be understood that the simplicity of design stems from the skilled usage of paradigms and careful selection of patterns, driven by design techniques named with acronyms ending with *DD - DDD, TDD, BDD, ATDD.
Reality, however, is different. Sounds bites, like KISS and DRY, are picked up by people who then assume simplicity is simple to achieve and try to achieve it in simplistic ways with none of the tools initially assumed. And that's how systems with noting but accidental complexity happen.
I say these things because I see them happen all the time, and because I've fallen victim to these misconceptions myself. I got so hung up on thinking that design is wasteful, that simplicity is all that matters, and that simplicity is easily achieved, that I've been heard saying that "a monkey could do programming, as long as it had access to stack overflow". It was a terribly stupid thing to say, but I used to think that.
What’s worse, the people I used to work with, who then had multiples of my years of experience, thought that to! And the software they wrote made it painfully obvious we were all wrong. What I'm trying to say is that people can be easily mislead, even if the message's intent is good. And then they go on to radiate the misconceptions until the whole continent is dead. To be abundantly clear — I don’t blame anyone for having been an idiot, but I do think that there’s room for improvement in communication.
So... what are the solutions? What I started to say instead of "keep it simple" is "choose your complexity wisely". The reason I like this way of putting it is because it brings two truths to the front:
Complexity is inevitable and unavoidable, but you can choose your fights
It takes wisdom to make the right call, and you will still be wrong
The most important emphasis, to me, is that managing complexity requires knowledge. It is, itself, a complex subject and one should not be fooled into thinking it's easy.