How to minimize and prevent bugs

How to minimize and prevent bugs

Write more stable and robust software.

Featured on Hashnode

Introduction

In this article, I want to talk about minimizing bugs in the first place, and also how to prevent bugs from happening again. This article is aimed at all types of developers. I wanted to write it because I know bugs are inevitable. Still, personally, in my earlier days of coding, I wish there was an article specifically about bugs and avoiding them. I'll focus on JavaScript as it is my primary programming language.

What is a bug

I'd describe a bug as a thing that is wrong in the software. Specifically speaking about the output. When doing a certain operation or action, then it doesn't do what the user expects it to do.

Minimize bugs

So, how can we minimize writing bugs in the first place?

TypeScript

Since we're using JavaScript which isn't type-safe, we can start off by using TypeScript, which is a superset of JavaScript, basically JavaScript with types and type safety.

Schema validation

It is good to have some sort of runtime validation because TypeScript only checks your types during compile time and not runtime. This is because the actual code that runs is JavaScript and not TypeScript itself. Personally, I'm a huge fan of Zod.

Eslint

ESLint is a tool that statically analyzes your code to quickly find problems. The nice thing with Eslint is that you can configure its rules to your own needs and also run its checker as a part of your CI pipeline.

Tests

Writing tests can help us minimize the bugs by catching them early on. We want to write our tests resembling the way our users would use our software, this way we get the most confidence.

It is important to know that more tests don't equal more confidence, and ideally we want to write enough tests to get the confidence to ship our product.

I'm personally a huge fan of TDD, Test-Driven Development. I enjoy writing my tests resembling the user, seeing it fail, then implementing the feature and seeing my test pass.

If you want to dig deeper into this area I highly recommend you taking a look at the material and resources by Kent C. Dodds, his article Write tests. Not too many. Mostly integration. is a good start.

Bugs...

Bugs are inevitable after all, they will occur, whether you like it or not, and you will have to fix them, but how can we ensure that they won't happen again? Let's have a look.

Preventing bugs

Tests

If we can reproduce the bug manually, that's a good sign, but what we want to do is to write a test that resembles the desired behavior. That test should fail since the bug is in the way causing the behavior not to be as it should.

We should fix the bug and then make the test pass, this way we can be fully sure that we've fixed the test since it initially failed.

5 Whys

One thing I learned from Toyota Production System which also inspired me to write this article, is the 5 Whys.

Ask 5 Whys in order to discover the root of a problem, if we'd fixed the root cause of the problem, then it wouldn't happen in the first place.

An example

Let's say we have a bug in production: Clicking "Save and Exit" in the form within the dialog only saves the item but doesn't exit out of the dialog.

In this case, we could ask ourselves the Whys. By the way, it doesn't have to be exactly 5 questions, it can be more or less, till you figure out the root cause.

Whys:

  1. Why aren't we exiting out of the dialog: Because we haven't implemented the logic in the code for the "Save and Exit" action.

  2. Why wasn't that captured before this was merged into the main branch: Because the author and reviewer of the code didn't notice it, and no tests were written.

  3. Why weren't any tests written: Because the author of the pull request implemented the feature but didn't do so without tests, nor followed the TDD approach which would've led to all of this being avoided.

In this scenario, had the person who implemented the feature followed the TDD approach, for example, they would've captured the bug before the pull request got merged and it all exposed in production.

This is a very simple example, but I think it is a great thing to do when discovering a bug in production and wanting to prevent the same or similar bugs from happening again, can also apply to other things in life other than programming.