HACKER Q&A
📣 3737hdhd7372

How do you balance between creating flexible systems and YAGNI?


I feel this is a constant argument I get into on code reviews

Senior devs will give me feedback around “can we make this more generic/flexible/extensible in case we need to do X in the future”

But I lean more towards YAGNI

I would rather keep it simple/dumb/readable until we actually need the extra functionality, then refactor at that point

But I admit it’s hard to find a balance


  👤 lwhi Accepted Answer ✓
I find the decision is usually a cost vs. benefit exercise.

Separating out business logic by making code more generic _is_ basic good practice.

There doesn't need to be a high cost once you start to do this by default, and it leaves doors open for future changes.

My general feeling is to 'leave doors open' (or allow for flexibility) if the cost of doing so is minimal.

Simple / dumb / readable is something you can achieve no matter which route you take. Comment your code. Be more verbose if it helps legibility and necessary performance won't be impacted.

Fundamentally, the only certain thing is that change _will_ be required at some point. And unfortunately, the decision as to whether something will be needed in the future is rarely something a developer has a say in.

All you can do it make your future dev life easier by leaving doors open, not closed.


👤 scrapheap
Ah, the old "in case we need to do X in the future" line. It's a tricky one as it will always sound like a valid comment, but I've seen so many junior developers take it a face value and feel they have to implement every possible future requirement, just in case...

These days I try to get our junior devs to think of these comments as ETC comments, as the comment was made from an et cetera point of view, but they need to think of it from an Easier To Change point of view. The X they're asking about isn't a concrete requirement, it's just one of many possible future requirements. Putting effort into tackling X is a waste of time at this stage, but putting our code in a place where we could easily implement X, Y and/or Z will usually turn out to be time well spent (as the chances that some of them will be a requirement in the future, we just don't which ones).

In my experience trying to write an abstraction from only one instance of the concept in your code is a bad idea, you need at least two instances of the pattern you're trying to abstract to know what's the abstraction and what should be part of the instantiation.

Instead of falling into the trap of abstracting early, you'll be better off keeping your functions limited to doing "just one thing". That way, when you're asked "what if we need to do X in the future", you can reply with "we should be able to easily replace this function with an instance of whatever abstractions will work best for implementing X, Y or Z"


👤 rcxdude
The best way of thinking about it I have come across is that your plan for doing X in the future is allowed to be "We change the code to extend it to do X in the future". Flexibility doesn't need to mean you build something now to make it so you can add X by only writing new code in a neat little module, it can also be that you can just change how the code works across the system to accomodate X. In fact, if you focus on making the latter kind of changes easier, you'll do better in general, and that generally means keeping things simple.

👤 bjourne
Always yagni. Those senior developers are wrong.

👤 filedottsx
As an experiment, lean into more flexibility and see what feedback you get.

👤 aristofun
You better don’t look for the balance.

99% of the time YAGNI


👤 revskill
It is all about where to put your if then else statement.