Hacker News new | ask | show | jobs
by davidmnoll 1096 days ago
I agree with this to some extent. but there’s a flip side too.

This mentality is often taken way too far. I had an old boss who wouldn’t allow me to write unit tests citing this thought process.

Even at places with decent engineering practices, I’ve seen so many examples of software where you’re limited to a one to many relationship for something that could and easily should have been implemented as many to many, rendering the product useless to many because a product person couldn’t stand to think a couple months ahead.

Some people seem to take this idea too far and basically assume that if a problem is interesting or takes away a tedious task, it must be overengineering, premature optimization, or an imaginary problem.

Perhaps a better way to phrase the issue would be “artificial constraints”, which would encompass the flip side too.

4 comments

Yes. While it’s less common, I’ve seen orgs struggle because they didn’t have enough imagination.

Every feature is done quick’n’dirty and eventually you have people whose full time job is to respond to customer complaints and fix data straight in the production database.

Bad engineering but potentially good business if it’s all billed to the customer…
No, it’s bad business because it doesn’t scale. Software is lucrative because you make it once and sell it to thousands of customers. If you’re making every customer their own bespoke thing, you’ll spend all your time for little return.
“Billed to the customer” means you’re charging the customer by the hour / project. You can get plenty of return selling bespoke things this way. Accenture is a $200 billion company.
That’s called Professional Services. Professional Services assemble a solution for a customer from a variety of components and maybe build some glue or the equivalent of a dashboard. This is not the same as having a ton of “if” statements in code to handle customer X vs customer Y.

The secret, as a software vendor, is to generalise these bespoke customer requests so you can sell the solution to all your customers (and get more customers!). If you are really cheeky, you can even get that customer to help fund the development that will make your business more money (hey, it’s win-win). You need to ruthlessly follow this approach though, as the rot of bespoke code will quickly become an insurmountable quality nightmare that can sink your business.

Earlier in my career I ate up the lean startup, move fast and break things, y combinator stuff. And while there are some very good lessons there, I’ve also come to realize that when you stop working on a part of the code, that may very well be the last time someone goes in there to make serious changes for a while. So sometimes it makes sense to do it right, even if it takes a few days longer (but not if it’s going to turn into some massive overengineering project).
Yeah I agree. I think the biggest mistake people make when applying YAGNI is not considering how difficult it will be to change later. If it's just some hard-coded value that you could easily add to a config later? Fine. YAGNI.

If it's something more fundamental like language choice or system architecture... Well fine YAGNI now but if you ever do need it you're screwed.

Ive seen a lot of engineers complain about YAGNI being taken too far but none who have seen their concerns validated by reality.
I have seen it validated by reality several times… more times than the opposite. I had a boss refuse to let me do a refactor that changed these sketchy dynamic field tables into json columns because “it’s not customer facing.” They were unable to show off features in an important demo because the endpoints were timing out despite putting 2 other people on it for 2 weeks to find code-based optimizations.

3 days later I deployed my “nice to have” fix and the performance issues disappeared.

I’ve also seen a company stall out scaling for years and lose multiple million-dollar customers despite having a novel in-demand, market leading product because they refused to do anything to clean up their infrastructure.

>I had a boss refuse to let me do a refactor that changed these sketchy dynamic field tables into json columns because “it’s not customer facing

YAGNI isnt about not refactoring existing technical debt. It's about not trying to pre-empt future requirements.

If youre refactoring in anticipation of as yet unmaterialized requirements then YAGNI applies - e.g. generalizing code when when today there is 1 specific use case because tomorrow you think there will be 3+.

If youre cleaning up existing code while working on it and the boss stops you because "it's not customer facing" then he's just asking you to violate the boy scout rule.

All of these definitions are fuzzy... refactor versus upgrade versus feature. When the people wrote it the way they did, they were almost certainly thinking that they don't need to overthink or over-engineer, and that they should discount hypothetical future concerns.

I can give you an abundance of examples. We were creating a page that was going to use state in a certain way. I was trying to insist that we address the way state will be handled across pages ahead of time. These concerns were dismissed as premature optimization. A few months later we had 5 pages with the state being handled in 5 different ways, and being synced in different ways between each page, complete with if statements, sometimes passing state through URLs, sometimes through local storage, sometimes through session, sometimes through JWT data, generally through a combo of several of them. Then we'd end up with confusing redirect loops for certain edge cases, state getting overwritten, etc.. We spend weeks fixing these bugs, and, eventually, weeks refactoring to manage state in a simpler way. These bugs often got caught by customers, drawing us away from feature delivery that was critical for demos to large customers.

All of that could have been avoided by spending 1 day thinking a little harder and planning for the future.

It ultimately boils down to a couple assumption that people like to make. (1) engineers know nothing about the domain, they can never predict what will be needed. That might be true in a large company with obscure domain-specific things for engineers who work far away from the day-to-day, but sometimes the engineers know exactly what's going to come up. (2) You can hill-climb your way into optimal program implementation. You can get to local maxima this way, but there are regular ways that programs grow based on how the business is growing and you can predict certain places where you will soon hit diminishing returns for current implementations. As long as you're up front about it and double-check your assumptions about the way the business is growing (and hence the application), I think there are ample places where you actually are going to need it.

>I can give you an abundance of examples. We were creating a page that was going to use state in a certain way. I was trying to insist that we address the way state will be handled across pages ahead of time. These concerns were dismissed as premature optimization. A few months later we had 5 pages with the state being handled in 5 different ways.

The right time to address this was probably a bit at a time after the 1st, 2nd and 3rd pages. Certainly not before the 1st and definitely not after the 5th.

>All of that could have been avoided by spending 1 day thinking a little harder and planning for the future.

The reason why you try as hard as possible to avoid planning for the future is because it's really hard to predict the future. Moreover humans have an inbuilt bias towards thinking we are better than we are at it (hence the gambling industry).

Refactoring as soon as possible after the fact will always produce better designs than up front planning for this reason.

>there are regular ways that programs grow based on how the business is growing and you can predict certain places

This is the kind of phrase that makes alarm bells go off in my head that somebody SHOULD be following YAGNI and isnt.

If it's defaults in a well worn framework that doesnt railroad you then fine but anything more than that - red flags all around.

Rule of 3 is often correct, first time just do it, second consider if it'll very likely happen a third time and when the third time happens it's darn well time to do it!

HOWEVER, this only works if you have the agency at an organization to allocate time for doing something. Contrary to this when you are in an organization of management that doesn't understand technical debt (or is fine with it because it just means more consulting hours) then it's absolutely the correct choice to stall and/or fix things "prematurely" (iff you can see what product they are trying to create without knowing it) if you'll be holding the shit-can of duplicated crap down the line getting knuckled because things aren't going fast enough due to technical debt.

I’ve had tons of times where YAGNI has bitten teams at a FAANG. It’s been responsible for re-orgs as products have to pivot to meet the goals that were dismissed but turned out to be needed.

I was creating a very important demo once, features i had said were important were classified as YAGNI. Leadership eventually saw that we couldn’t deliver without said features. YAGNI bit those teams in the butt.

these things happen all the time internally to companies but get ironed out internally as well.

All depends on what the I is in the YAGNI. I have seen development be parallised where the same work is being done again and again by different developers in different ways because YAGN { maybe 2-3 days of upfront architecture and design for a 6 month project }. This results in bugs and maintenance nightmares. This was before unit tests were common though, so maybe unit tests may have saved it. But surely it was slower to develop that way.

But tautologically you can't take YAGNI too far, if the "YAGN" part is actually true :-). But that is always under debate.

It certainly feels that way. 2 or 3 days of up front architecture and design with hindsight is always better than 2 or 3 days of up front design in reality, but of course you dont have that hindsight when you start.

I've had to do up front on multiple projects and it always results in overengineering - we focused on things that didnt matter, designed things that were inappropriate, etc.

I'd always rather take those 3 days and redistribute them as extra refactoring time.