The Future Makes Fools of Us All

There is a principle from extreme programming that I quite like, “you ain’t gonna need it” (YAGNI). Here’s a post which does a good job introducing the idea. Basically, we should only implement the features we actually need, not the ones we think we might need in future. But why should we follow the YAGNI principle?

Well, in my experience, there are five good reasons.

Firstly, try as we might, we can’t see into the future. We are likely to get the requirements for this future feature wrong, because they aren’t really requirements yet. Also, we will probably operate with all kinds of assumptions that will get invalidated by the time we really need this new feature. We won’t know what we need to implement, because we don’t need to implement it yet!

Secondly, as technically minded people, we enjoy writing code and solving complex technical problems. So, we have a bias towards over-engineering. There is a good chance, we’re not actually planning ahead for future requirements, but are really just doing some fun coding. So we should always check that impulse, and make sure that we are building something that will add value right now, rather than following a fun diversion.

Thirdly, all code has bugs in it, so the more features we add, the more bugs we add. And we want as few bugs in our code base as possible. Which means we write as few features as possible. In particular, a pre-emptive feature may contain bugs itself, but it is also likely to introduce bugs in existing code paths!

Fourthly extra features mean extra complexity. This makes our code harder to monitor, support and maintain. But worst of all, it makes it harder to extend. When new requirements do arise, it will actually be harder to implement them because of the extra complexity we baked in at the start. Often times we mistake complexity for extensibility. To me, code is extensible when adding new features is quick and easy. This means that complexity is the enemy of extensibility.

Fifthly, there is always a trade off with features we need right now! Every team I have been on has had a lengthy backlog of productive work that any one of us could have taken on at any time. Rather than trying to solve a problem before it arises, why not solve a problem that already exists. Don’t sacrifice what we need right now, for what we may need in the future. Moreover, we always underestimate how much work it will take to implement some new feature, which is likely to make the trade off even worse.

So, next time, when we are tempted to add some functionality to our code, we should ask, do we really need this right now? And, rather than guessing how our code will be used in the future, admit that we don’t, and can’t know how it will be used!

Watch Out For Hidden APIs – Part 1

I was caught out by a hidden API recently. I was rewriting some code that generates some daily caches. I was moving it over to use a newer scheduling framework. Nothing very exciting. The final part of this set of jobs sent summary emails to various inboxes.

However, what I did not consider, is that the owners of these inboxes had configured various rules in their mail clients to sort their incoming mail. I had changed the subject line of the summary emails, and it no longer matched these policies. Once my code was live, the summary emails stopped appearing in the appropriate mail folders. In fact, the change I had made meant that they were now getting sent straight to some recipients’ spam folders!

As soon as I realised what had happened I changed the subject line again. However, I did not know what the email filters actually where. What is worse, most of the email recipients didn’t know what their email filters where either. So I decided to just change the email subject back to what it was before. Unfortunately it took a couple of attempts to get it right! This is because, the old and the new scheduling code where both munging the email subject lines, but not in the same way. Eventually I managed to reverse engineer the old email subject line via the new scheduling framework, and all expected email notifications were restored.

The problem that I had was that the email subject line was an invisible API. I didn’t know about it when I was making my changes, indeed I couldn’t have known about it from the code, but it was there nonetheless.

When I was done, I left a unit-test in place that verified that the email subjects would pass all the appropriate email filters. This will, hopefully, warn any future maintainer not to make any changes to these email subjects!

Part of the lesson here is to always look out for hidden APIs. But more importantly, it is that you won’t see a hidden API until you break it! So don’t create hidden APIs in the first place. And, when you are making changes to your code, always ask yourself, could there be a hidden API here? Finally, hidden APIs are another reason why you should avoid making changes to code that has running in prod for a long time!