HELLO ERRORS MY OLD FRIEND
Tags: javascript, webdev, tutorial, react
Published: 2020-10-22 05:00:51

Errors get a bad rep in the newborn [#devjokes](https://github.com/shrutikapoor08/devjoke) lingo, which is just a few years old at this point. Btw did you notice when words like programming, algorithm, software, and AI became part of the everyday expression 🤭🤭, extra points to the person who can tell the catalyst of this reaction 😛😛?

**Anyways, my point is errors are not bad at all.**
I would even go as far as saying errors are great, they are like that friend who tells you his honest opinion and notifies you when you do something wrong.

Enough babbling, let's look at an example.
```javascript
const TASKS = ["Task 1", "Task 2", "Task 3", "Task 4"];
function getNextTask(currentTask) {
  let currentIdx = TASKS.indexOf(currentTask);
  return TASKS[currentIdx + 1];
}
```
we created a function that returns the next task from the `TASKS` Array, using `currentTask` as its input. We can try the function and it works, *until* it doesn't.

If we look closely, we will observe that we left a `segmentation fault` error in our code("segmentation fault" is just an OG way of the compiler telling us, it can't find the thing we are looking for as the index is incorrect).

And since we have found out the problem, it's an easy fix.
```javascript
const TASKS = ["Task 1", "Task 2", "Task 3", "Task 4"];
function getNextTask(currentTask) {
  let lastIdx = TASKS.length - 1; 
  let currentIdx = TASKS.indexOf(currentTask);
  if(currentIdx >= lastIdx) {
    return null;
  }
  return TASKS[currentIdx + 1];
}
```
Looking so much better already :)

## Introducing Uncertainty 😈
Happy with the implementation we deploy it to production. Few days in, you suddenly observe that the function seems to have some error and the code is failing in production. 

Our initial investigation tells us the function keeps returning the first element of the array. **Can you guess what might be causing the issue ??**


*Congratulations* to everyone, you all win the explanation, ready here goes 🥁 🥁 🥁


## The curious case of the missing item

Our investigation has finished, the errors seem to be caused when `currentIdx` is `-1`, which happens when the item is not found in the array.

Now that we know the issue, an obvious solution seems like handling this cause.
```javascript
const TASKS = ["Task 1", "Task 2", "Task 3", "Task 4"];
function getNextTask(currentTask) {
  let lastIdx = TASKS.length - 1; 
  let currentIdx = TASKS.indexOf(currentTask);
  if(currentIdx === -1) return null;
  if(currentIdx >= lastIdx) return null;
  return TASKS[currentIdx + 1];
}
```
We fixed the issue and our function seems to work fine now.

## The Problem
Considering the above function as a reference we fixed the issue by adding a defense condition which work. But the function `getNextTask` was designed to return the next task which we accidentally changed to `validateTaskAndReturnNextTask`, this is an issue but not a deal-breaker. The bigger problem here is, we didn't fix the problem, we just patched the inception point of the error, which can be lead to more unexpected issues.

## Error Friendly Functions
We need to rethink how we write functions, make them more robust so that they make our software better.

```javascript
const TASKS = ["Task 1", "Task 2", "Task 3", "Task 4"];
function getNextTask(currentTask) {
  let lastIdx = TASKS.length - 1; 
  let currentIdx = TASKS.indexOf(currentTask);
  if(currentIdx === -1) throw new Error(`Invalid task ${currentTask}`);
  if(currentIdx >= lastIdx) return null;
  return TASKS[currentIdx + 1];
}
```
When you look at the code above not a lot has changed, we updated the defense condition from a return to an error. 
You might say I just increased your work and now you need to write `try-catch` everywhere, to which I will say "No good sir you don't".

## Don't handle the error
Yes, I am serious "don't handle errors". Yes I know, that would mean your application will crash, but that's exactly what we want. 
Consider our `getNextTask` function. In an ideal world, we will never get the case where `currentTask` is not found in the `TASKS` array. And since our function works on that assumption, it should shout on us when its conditions are not met and hence we throw an error. 
With this idea of letting our applications crash, we made an unexpected superhero friend [The Stack Trace](https://en.wikipedia.org/wiki/Stack_trace). 
Stack Traces are great, they give you an exact history of what happened and how it happened to maintain both state and order of execution of operations, which is extremely helpful in finding the actual error, which in our case would be the statement that makes the `currentTask` an invalid entry in `TASKS` array so that we can solve the actual problem and not just patch the problem inception point 🚀🚀🚀🚀.

But leaving unhandled exceptions in our code is a terrible idea, especially when deploying to production. So, to deal with that we create a helper.

```javascript
function reportError(message) {
  if(process.env === "PRODUCTION") {
    // Call to your logging service or bug tracker
    // MyBugService.error(message)
  } else {
    throw new Error(message);
  }
}

const TASKS = ["Task 1", "Task 2", "Task 3", "Task 4"];
function getNextTask(currentTask) {
  let lastIdx = TASKS.length - 1; 
  let currentIdx = TASKS.indexOf(currentTask);
  if(currentIdx === -1) reportError(`Invalid task ${currentTask}`);
  if(currentIdx >= lastIdx) return null;
  return TASKS[currentIdx + 1];
}
```

And with that, you just created a better critic for your code which can help you catch hidden bugs in the development phase and will help your make more robust software from the get-go.