Recently, I got pulled into a discussion about regular expressions (regex). For anyone familiar with regex, they'll know that it is both an immensely powerful tool, as well as a readability nightmare. To most of us mortals, any sufficiently long enough regex is indistinguishable from pure gibberish. So then, how do you decide when is the right time to sacrifice readability for the speed and convenience that such a tool can provide?

This post outlines my general order of precedence for such decisions, and then dives into some of the nuances.

Credit: Dilbert by Scott Adams

The Order of Operations

Without further adieu, here's my list of priorities for developing quality software:

  1. Functional
  2. Secure
  3. Readable
  4. Maintainable
  5. Performant
  6. Quick to Develop

In general, higher tiered concerns should not be sacrificed to meet lower tiered concerns. For example, you should not be sacrificing security to make something more readable. Similarly, you should not sacrifice readability to finish the work sooner. It's imperative to note these are guidelines, not rules! The list represents a good place to start thinking, but exceptions should be considered.

But Why, Though?

Functionality, I hope, is self-explanatory. If your product does not sufficiently do what it is intended to do, then it is not useful at all. It is the primary purpose, and therefore the primary goal, of your code.

Next up is security, which I consider a close cousin to functionality. An app that can be exploited to behave in ways it was not intended to has broken functionally. Furthermore, the breakage is existential: it directly threatens the continued existence of the app itself, or at the very least its adoption.

Coming in third on the list we have readability. And this is where we get more into the philosophical basis of my list. Readability allows your code to be more easily understood and reasoned about by engineers. This pays in dividends by increasing velocity, onboarding, bug hunting and general engineer happiness. A project which is easy to read and understand helps support the rest of our priorities.

Readability is not important for Kel from Good Burger.

Maintainability is similar to readability, with the difference of focusing on how easy the system is to change. That difference aside, the reasoning is very similar to that of readability. Code which is easier to maintain increases the project health in many ways and supports the other priorities.

Once we have made our project functional, secure and easy to work with, we can start thinking of performance. Does the app run well? Does it scale? With the ranking of this item, I suspect there's a lot of people ready to send me angry emails. Hold on just a moment, I'll touch on this subject more in the later sections.

Ringing in dead last is our concern for how fast we can actually develop the app or feature that we're working on. How many engineer hours will it take? Just like performance, I can almost hear the furious clacking of keyboards as people get ready to rage. Put down the pitchforks and continue reading!

The Nuances and Controversy

There's some common arguments that I suspect people will have with the above guidelines. In this section, I'll try my best to dodge the hatemail by getting ahead of the most obvious rebuttals. Please, temporarily lower your pitchforks.

Why Is Speed to Develop Last?

In practice, I will admit this usually does end up higher in the list of priorities. There are plenty of valid business reasons why the velocity that you get features out the door is important. And while valid, they are not what we should be gauging our system on. It's not the priority that we strive for as engineers. So although pragmatism often dictates this to be prioritized higher, the reasons are not due to an effort for engineering excellence.

But These Aren't Binary Choices!

Correct, my dear hypothetical reader! This isn't binary! Rarely must you deal with these in an all-or-nothing fashion. Perhaps you can sacrifice just a little readability to make it much more maintainable. And that is a great choice for you to make.

Why Don't We Prioritize Testing?

We definitely should, in the sense that testing is a subset of maintainability.

With that statement, I imagine many will now be protesting that maintainability should come before readability. My counterpoint is to take the tradeoff to the logical extreme. Would you rather work on a well-tested project that's backed by a pile of spaghetti code, or a cleanly-written project that lacks adequate testing? For me, I would rather work on the well-written project. It's much easier to add testing than it is to refactor entire systems, especially when the code is well-written and easy to understand.

Okay, But What About Accessibility?!

While undoubtedly important, this prioritization is largely driven by business context, and not one of the software itself. For instance, a project which is used internally by an HR department based in the United States probably doesn't need to highly prioritize localization. Conversely, a project which is targeted for paraplegics should have accessibility right up at the top, brethren to functionality. Our decision making here is based entirely on the business goals of the product, and being so context dependent, it would be impossible to accurately place it on this order of operations.

Fine. But Performance Should Be Higher.

Unless you have strong evidence that it's needed, performance should not be a top priority. It's a classic mistake to prematurely optimize for performance, and in doing so you put the cart before the horse. Satisfy the higher priority items, and only then can you accurately profile the system and determine where the bottlenecks are. In general, you should prioritize the higher tier items until you have a strong reason to believe performance is (or will be) an issue.

TL;DR

If you want to optimize for engineering excellence, focus on making your code work well, and then be easy to read and maintain. After you meet those bars, you can start to worry about performance and speed of delivery.

Most importantly, recognize that there are tradeoffs that you can (and should) make. If you only sacrifice a little readability for a whole lot of performance, it's a fine trade to make. But you should rarely trade the opposite way. Don't make large concessions on readability to achieve minor gains in performance until you have very strong evidence to support the need to do so.