One thing is code execution paths for later debugging. All else equal, code is simpler if everything you need to figure out what something does is in one place. Basically, minimizing the distance you need to travel in order to get related information. Keep variables closer to where you use them, etc.
There's some programming language specific stuff. A for loop that does a mapping is more complicated than calling a map on the collection. More generally, a program is simpler if it uses more specific abstractions, rather than using a very general abstraction in a highly specified way.
Likely, there's more than I'm completely forgetting but will recognize as general principles that I use.
Who was right?
[NB Obviously, I was right, but it would help if there was some objective measure of complexity to justify it ;-)]
1. Clearly map the code/functions to the specs of what it does almost line by line.
2. The code is expressed in a way simple enough for one person to understand it and verify it by hand.
3. The code is expressed in a way simple enough for a machine to verify it should someone want to try.
4. Minimal to no global effects/state happening in the local code.
These principles tend to result in code that's correct and easy to modify. I say they're a start on some objective measure of simplicity. We could empirically [dis]prove them as well with tests of various coding styles on people and tooling.
Blindly following anything -- especially nuanced, process-driven ideological frameworks -- is a recipe for a disaster.
KISS and YAGNI are examples of processes that require the person who is using them to actually think through the implications within the context of the problem being solved.
KISS and YAGNI did not cause the atrocities that you've seen. Those complex beasts of code existed because the team fundamentally didn't understand what they were doing.
It's like "agile" software development. Just declaring that you're following an agile methodology and scheduling stand-ups does not mean that you're going to be successful. It takes someone (and usually, many someones) who understand how to iteratively design and develop to be successful.
> It just takes a non-obvious path, and a few months of code and requirements evolution.
Can you expand on this comment? I'm interested in understanding what you mean by "non-obvious path".
Yep. That's the point, that's why I pointed it was blind.
Many people blindly follow and impose that kind of ideology. Most people that even mention YAGNI outside of a classroom are blind followers (for DRY things are more diverse).
By non-obvious path I mean things (requirement, underlining systems, user base size) changing in a way that was not unquestionably and blatantly obvious.
I can't agree with you more. Thank you for the follow-up.
Following KISS and YAGNI means you hard code lots of assumptions. When the requirements change, it means you have to fix all those subtle hard-coded assumptions everywhere and that is usually hard.
(edit:formatting)