Home Home

Aren't we misusing YAGNI too often?

Arseni Mourzenko
Founder and lead developer, specializing in developer productivity and code quality
130
articles
December 19, 2014

OK, I get it, I'm over-thinking and over-engineering this app. I should KISS, because YAGNI. Great. I should not attempt to solve problems I don't have.

I should not attempt to solve problems I don't have.

Or should I?

Development is filled with compromises and golden middle.

  • Should I make this method short by splitting it into more methods, or should I reduce the number of methods by merging them?

  • Should I rename this field to a longer, more explicit variant, or should I shorten the names of my longer methods?

  • Should I care about the small details when writing code, or should I release it before my competitors do?

  • Should I achieve a better code coverage, or should I rather focus on adding new features?

  • Should I use this shorter version of the code, or should I keep that one, which is longer, but slightly easier to understand?

In a context of continuous refactoring, there is a tendency to apply YAGNI as strictly as possible, which makes sense in theory. In theory, this leads to permanent simplicity, which means that at instant t, the code is as simple as possible because (1) it was refactored from a more complicated form and (2) no unneeded complexity is present in the first place.

In practice, I see a bit too often how YAGNI hurts me and teams I'm working with. A good example: my question What are the valid uses of static classes? on Programmers.SE. The first answer, obviously: YAGNI: static classes are simpler than dependency injection or other constructs.

I understand the point, but I still disagree. 259 characters limit for file paths in .NET Framework was hurting me in dozens of projects, and always when I was not prepared to be hurt. For example, I release the system used internally in my company for the replication of files. It works for a while, and then starts to fail because there are now files which exceed the 259 characters limit. So now I need to deal with this, and do it quickly, but since I've used the static File class, I should now change a great deal of the code and the tests to make it work correctly. TAGNI now costs me six hours of work I could easily avoid.

The worst part is that it sometimes doesn't cost too much to “over-engineer” in the first place. Using the library which let you access either the file system or isolated storage, or memory, or specifically NTFS with its transactional capabilities and support for long names isn't that more difficult compared to the calls to the static File class.

Actually, I believe YAGNI might be the reason we have the 259-characters limitation in the first place (note that I'm unaware of the actual reasons, so this paragraph is purely speculative). Long ago, they designed a system which supports the arbitrary limit which seemed reasonable. Since it was indeed reasonable and because of YAGNI, they developed the system in a way the length cannot be changed. Years later, the limitation becomes a real issue, but changing the limit is now too expensive to be possible in practice.

Who needs to store 2 TB of data in a single file? Thirty years ago, nobody. Today, a lot of companies. In a few years or decades, probably any average user.

Who needs 100 Mbps internet connection? Thirty years ago, nobody. Today, a lots of persons. Very soon, probably any user of Netflix or YouTube.

Let's talk about databases. When designing a database schema, there is often a question of type for an unique identifier. int appears a good choice for most tables. But then, your project is a huge success, and you've got your 2,147,483,647th comment, and the next person who comments makes your website crash. Why this makes me think about Y2K problem?

YAGNI is an excellent principle. But like any other principle in software development, it may easily be misused. Using every time the easiest design without bothering about tomorrow is certainly not the best practice, even in a context of regular refactoring.