Designing a better way of thinking
How many of you use a todo-list? I assume most of you do, in some form or another. But what about checklists? They are far more useful than you think.
If you’re not using checklists, you’re essentially counting on your working memory to keep things in check. That may be fine for simple things, but it can easily get you in trouble. For example, let’s say you’re going out with friends. You need to remember a few small things: your keys, your wallet, and probably to use some deodorant. About three elements, your working memory can handle that, no problem. But what happens if you add two more elements? That’s a little trickier.
For instance, on your way to meet your friends, you also need to pick up a package, and not only that, one of your friends asked for their book back, so you need to remember to take it with you as well.
Now, we’re in trouble. Our working memory is now juggling five different elements, and it’s not a terribly good juggler. Its limit is around four items.
Now that number may vary, but it seems to be true in most cases, and I can certainly attest to that. When I need to remember more than a few things at a time, I tend to forget at least one of them.
In the example above, I’d probably forget to bring the book. Now, forgetting something like that isn’t such a big deal, I’ll just bring it next time. But what happens when we’re dealing with more serious situations? If you’re treating patients, or, more likely for my readers, writing production code (that might serve the medical industry), you can’t afford to forget things, as these things you’ve forgotten might be on the critical path.
Checklists help you avoid costly mistakes. That’s definitely important, but there’s much more to it than that. So much so, that an entire book was written on the subject. However, this isn’t an entire article about checklists, this article is about writing better code, so let’s get to it.
If you’ve been in the software industry for a while, you’ve written your fair share of design documents. And if you haven’t — that might be the time to look for a new job. Not that design documents are all fine and dandy, they can be quite an ordeal at times. But if you have a good design template at your disposal, it can serve as an incredible facilitator of better thought processes, by helping you avoid cognitive biases.
The human mind is extremely biased. Now, that’s not necessarily a bad thing. Biases are shortcuts our mind takes in order to save time and energy. More often than not, they’re even quite useful. We can’t overthink every little thing in life. However, the tricky thing about being biased, is that it’s pretty difficult to become fully aware of it.
For example, let’s take the selective bias.
You’re building a new UI component that has a pretty simple backend, just one API. It’s not your first time tackling such a task, so you didn’t spend much time planning. You know exactly what you’re going to do — build a great UI and a straightforward API. You manage to finish the task in record time, so you pat yourself on the back, and deploy it to production.
A few months go by, and that component is starting to get a lot of traffic. You’re starting to see spikes in the average response time from the API. Users are bound to start complaining soon. You’re looking frantically at your code, what could possibly be wrong?
Well, it appears that the simple DB query that your API performed is now 10x slower. It used to rely on a small DB table that wasn’t too complicated. That table has now ballooned to x100 its former size and even has a few extra columns.
This dire issue could have easily been avoided if we’d drafted a good design document. We would then see that since we’re dealing with a UI component, responses are very time-sensitive. And in cases like that, caching common responses is usually a good idea. We would also consider adding an index for one of the columns we filter by, to make sure the query’s performance doesn’t suffer as the DB scales.
The main idea here is that design documents can be extremely beneficial.
They should not be treated as a chore, but rather as a tool that helps nudge you in the right direction. If your company’s design document uses a good template, it will help design a better thought process. That is no easy task, as most design document templates have too many sections, which tends to be overwhelming. When things are overwhelming, they tend to be avoided, and that essentially renders them useless.
In order to use design documents effectively, we need to make them simple. One way to make them simpler is by including a simple, yet comprehensive, checklist. That checklist should counteract all major biases and nudge its users to think in a better way. That means considering all possible contingencies, edge cases, things that could go wrong, using best practices, etc.
Other than using actual design documents, we must have internal checklists as well. These internal checklists should be tailor-made for our personal biases. For example, you might have a tendency to skim code, and not read it thoroughly. That can easily make you miss subtle implementation details, that are crucial for understanding the code (or bug) you’re dealing with. That happened to me recently when I worked with Flutter.
My tests were failing because of some odd issue that seemed to be related to a library I was using. I tried fixing it, yet it persisted. So I assumed there’s an actual bug with the library (which is almost never the case). Development, I filed a bug, and the issue was pointed out to me. I quickly realized that I’d skimmed the library code and missed a subtle detail in its implementation. So to counteract the tendency to skim code in the future, you can add the following item to your internal checklist: “I’ve read the code thoroughly.”
Only once that item is checked off, can you allow yourself to approve that PR, or report what seems to be a bug.
Building an internal checklist does not mean it should remain in your head. On the contrary, it’s best if you can write it down on a piece of paper, or use your favorite online note-taking app. The main idea is that you’ll have a personal checklist that is separate from the formal design template you might have used for more complex projects at work. That internal checklist should serve you on every task, large or small, and in your personal life as well.
Checklists can be extremely beneficial. They help us counteract our limited working memory capacity. If they’re particularly good, they can help guide our thought process in the right direction.
In software, using a good design template that is simple, yet comprehensive, can go a long way toward facilitating a better thought process, that will eventually result in better code. Its is critical, as it significantly increases the likelihood that such documents will be drafted in the first simplicity place.
You should also build your own internal checklist, in order to counteract your unique biases. This checklist should serve you on every task, not just tasks that require a full-fledged design document.