YAGNI isn't about writing the smallest amount of code to implement the most minimally-designed solution that will work for the most minimal set of requirements you can get away with. It's about writing your code in such a way that you only implement what you need, but you design for what you think you might need. Maybe this means you have a bunch of stub parent classes. Maybe this means you pass in
sub{1} instead of a complex callback. Maybe this means you choose the shell variable syntax because it's very flexible. But, you don't implement . . . yet. You give yourself room to implement.
Why do you want to do that? Because you don't know what the late requirement will be. If you start implementing now, you have already started to carve the statue. You might remove marble that needs to be there later on. It's really really hard to glue marble back and it never looks right. Much better to give yourself lots of marble to work with and carve only when necessary.
My criteria for good software:
- Does it work?
- Can someone else come in, make a change, and be reasonably certain no bugs were introduced?