(Replying to PARENT post)
In theory, it would be nice if the code included appropriate hooks and abstractions. But in practice, it's often quite hard to guess where those hooks should be, and which aspects of the code should be abstracted. And since the abstractions are based on hypothetical designs, they're very often useless.
Basically, I'd rather maintain over-simplistic code that implements a few features well than code that has been prematurely generalized to support half a dozen features which don't exist yet. All too often, the generalizations are wrong, or simply get in the way of other features I'm trying to add.
Unfortunately, YAGNI is one of those rules that requires common sense to apply well. It works best as a sanity check for an already-experienced programmer: "Really? Do I actually need a whole new set of abstract interfaces here? Or can it wait?" If a programmer is totally lacking in taste and judgement, YAGNI won't save them by itself.
(Replying to PARENT post)
I think I've been tainted by too many counter-examples: seeing a piece of code that was specially written for a very narrow and specific use case, and needing to extend it to some scenario that the original author did not envision. If the author hadn't been thinking in terms of re-use and extensibility ("because they ain't gonna need it"), it gets frustrating and regression-prone.
In other words, you ain't gonna need it, until you eventually do. Lazy programmers shouldn't be excused for dismissing maintainability with a simple catch phrase.
(Replying to PARENT post)
A lot of times "architecture astronauting" is simply good separation of concerns. To take the Dog example: there is a lot of code necessary to get a Dog into the world of minecraft that isn't specific to the concept of Dog at all, such as drawing itself, keeping track of its state in the world, etc. These are the types of concerns you would want in a base class of Dog and potential Cats and Chickens. This is something that should be factored out, not because you may eventually make a Cat, but because those concerns have no connection to the concept of Dog at all. Keeping such code together will just make comprehending the actual Dog specific code harder.
(Replying to PARENT post)
I think YAGNI is a really good rule of thumb when you define "need it" as "need it for the current release".
(Replying to PARENT post)
First, people systematically underestimate uncertainty. The human brain is good at recognizing patterns and making plans but not so good at dealing with randomness and uncertainty. When talking about software development and maintenance we're talking timescales of years. Companies go out of business, projects get cancelled, code gets thrown out and rewritten. It's easy to paint a pretty picture about how the Cat class will get added to the Pet hierarchy but there is tons of uncertainty involved in even the simplest project. Because the scenario is specific the brain overvalues its likelihood compared to the nebulous unknown alternatives.
Second, keeping code as simple as possible is almost always for the best. YAGNI forces smaller simpler code. More complexity and more code means more room for bugs. All the studies I know of consistently show that more code means more bugs.
Finally YAGNI is a principle that forces priorities to be in the right place. The question is never between spending time making something that might be useful in the future or doing nothing, it's between doing one particular useful thing or another. I can't think of a single case where the right priority is to do something that MIGHT help in the future. You start by doing things that DO help now, then things that WILL help in the future.
(Replying to PARENT post)
There is a non-linear relationship between number of requirements and the complexity of the resulting software. The exact relationship is hard to nail down - I've seen some data suggesting that complexity goes as the cube of the number of requirements - but it is clearly non-linear.
This goes whether or not the requirements are handed down by a product manager, or generated by a developer who mistakenly believes that the future types of requirements are predictable. The impact on the complexity of our software of additional requirements is all out of whack with how many requirements you added.
Here is food for thought for those who are not convinced. Suppose that a developer who wants to abstract things doubles the set of requirements and the relationship is the cubic one that I suspect. Then your task is 8 times as hard. And you don't have working software until it is done.
Suppose that 2/3 of those requirements turn out to be needed eventually and, horror, there is no way to do it without a complete rewrite. Then you expect the full energy now, 4x as much work later, and your total effort eventually is 5x what it takes to produce what you really needed right now, AND you get to enjoy a working partial solution before you're done.
Even a worst case scenario for YAGNI (yet) comes out better than trying to aggressively plan for the unknown future.
(Replying to PARENT post)
I think a better wording might be, "don't increase complexity writing code you may not need". The issue is usually not the presence of additional code. Rather, it's making design decisions based on requirements that may never in fact come to bear.
(Replying to PARENT post)
(Replying to PARENT post)
If the OPs software design (for a particular subset!) is so complex he can't imagine it in his head: either the design is too complex or the programmer is not very good, imo.
Any why the hell do we need the next acronym?!
(Replying to PARENT post)
I'll bite: it's really terrible for security purposes. Aside from the typical YAGNI feature examples, there's plenty for application maintenance and back-end development.
Let's say you have a database with several layers of privileges. You frequently have to perform actions that require higher privileges than that user has, and you're a lazy dev. So you try to automate this process by adding further code to your system design, expediating the entire process at the cost of some authentication.
Bam, huge red flag and a half. Yes, you can have this and defend it at the same time, but in most cases, it's silly to try. Adding code just adds another vector and a half.
That said, yes of course adding features you don't need will bloat the system. But that pet example kinda sucked, I'm sorry.
(Replying to PARENT post)
(Replying to PARENT post)
(Replying to PARENT post)
If you are doing a waterfall PM process, it doesn't apply so much.
(Replying to PARENT post)
However, the very second you know for sure that you'll need to expand the system, you need to stop and pull on your big-kid pants and do some design. Any fool can keep throwing code at slight variations of a problem until they're buried in spaghetti (and many do!), but people that actually know what the hell they're doing will bust out the abstraction hammer when it becomes clear that it's prudent (and not a moment before).
Generally, once I've had to solve a similar problem three times it's time to refactor. Once is providence, twice is coincidence, but three times suggests that things need to be designed.
EDIT:
The author's example is particularly poor. A dog, chicken, and cat all need to move, follow a player, interact with the game world, update, spawn, and die. It makes perfect sense to have a Pet class handle this glue entity lifecycle code, and then to specialize a subclass to override the rendering or update code.
There are cases where YAGNI is alive and well, but this example simply isn't it.