- modularity
- readability
- abstraction
- maintainability
- scalability
- reusability
- testability
- cost
We've all seen codebases that are over-abstracted in the name of code reuse, or to adhere to this or that software design philosophy, and are nightmares as a result. "You Ain't Gonna Need It" is a restatement of the premature-optimization adage, just for a different metric.You can design for modularity, readability etc., but optimising for them doesn't sound right. Something to do with them not having well-defined, agreed-upon definitions of where the optimum is.
For example, modularity could be modelled as the time/edit-distance/etc. it would take to swap-out N out of C components, where C >> N. If we're defining things centrally and passing them around via dependency-injection then it's O(N) (each component is defined once, so change N of them); if we're hard-coding references everywhere then it's O(N*C) since we'll have to check for references in all of the components, and each one needs to be checked for the N possible swaps.
On the other hand, dependency injection is less optimal than hard-coding for a metric like API size: for N components, the number of references grows as O(N^2) (since new components need to reference existing ones, and existing ones will need to reference them); so APIs using DI will have O(N^2) arguments.
But when people warn against "premature optimisation", specifically, they are advising you to give higher priority to things like modularity, readability, abstraction and maintainability, and not sacrifice them all for a singular goal, typically speed.
“The Last Responsible Moment” is subtle. You have to include user benefit (they may not care yet) versus snowballing consequences of delay, versus having more and better information later on.
One of the things that drew me to CI/CD was the notion that you’re not going to get better at handling your problems by avoiding them. You can’t learn to pick your optimization battles if you never fight them. You won’t learn something I’ve been saying for almost 25 years now and I still haven’t heard come out of anyone else’s mouth: there are code changes that improve readability and performance. Making those changes as refactors is hardly ever premature.
"Use a set instead of a list, it's faster". "that's premature optimization!"
It's fairly easy to remove the set and replace it with something else if this does come up.
Doesn't seem like it'd be the general case though. And it seems like it'd be fairly obvious when something like this applies.
I have massive respect for anyone who can pull off steady improvements, no matter how small.