Clean Code - Testing, Concurrency, & Error Handling - Beau teaches JavaScript

Making Clean Code: Testing Concurrency and Error Handling

When it comes to writing clean code, there are several key principles to keep in mind. One of the most important is testing. It's always good to strive for 100% test coverage of your code. This means that every line of code should have at least one test associated with it.

The Use of a Single Concept per Test

There's an example provided in the transcription of a bad way of writing tests. The test is trying to test three different things: handling 30-day months, leap years, and non-leap years. This is a problem because callbacks aren't clean and they can cause a lot of nesting. In contrast, using a single concept per test makes the code much cleaner and easier to understand.

The Problem with Callbacks

Callbacks aren't clean and they cause a lot of nesting. They're often used when working with asynchronous code, but they can lead to a lot of complexity in the code. In this example, we see callbacks being used to get the free Code Camp Wikipedia page, write a file, and log the written file all in a row. This is a problem because it's difficult to read and understand.

The Solution: Using Promises

So what can we do instead? The solution is to use promises. Promises are a built-in global type that allows us to handle asynchronous code in a much cleaner way. Instead of using callbacks, we can use the dot notation and the `do-then` function to write our code.

Using Promises for Asynchronous Code

Here's an example of how you might use promises to get the free Code Camp Wikipedia page, write a file, and log the written file:

```

fetch('https://en.wikipedia.org/wiki/CodeCamp')

.then(response => response.json())

.then(data => {

const content = data['Content'];

const title = 'Code Camp Article';

const filename = `codecamp-${Date.now()}.txt`;

fs.writeFileSync(filename, content);

console.log(`File ${filename} written successfully.`);

})

.catch(error => {

console.error('Error occurred:', error);

});

```

As you can see, this code is much cleaner and easier to understand than the original example using callbacks.

The Benefits of Using Async/Await

But promises aren't the only way to write clean asynchronous code. With the introduction of async/await in ES8, it's now possible to write even cleaner code that's easier to read and understand.

Async/Await for Cleaner Code

Here's an example of how you might use async/await to get the free Code Camp Wikipedia page, write a file, and log the written file:

```

async function main() {

try {

const response = await fetch('https://en.wikipedia.org/wiki/CodeCamp');

const data = await response.json();

const content = data['Content'];

const title = 'Code Camp Article';

const filename = `codecamp-${Date.now()}.txt`;

fs.writeFileSync(filename, content);

console.log(`File ${filename} written successfully.`);

} catch (error) {

console.error('Error occurred:', error);

}

}

main();

```

As you can see, this code is even cleaner and easier to understand than the previous examples using promises.

Handling Errors

When working with asynchronous code, it's often necessary to handle errors. This means that we need to do something when an error occurs, rather than just letting it propagate up the call stack.

The Problem with Ignoring Caught Errors

One common mistake is to ignore caught errors. This can happen if we don't properly log or report the error, or if we don't take any action to recover from the error.

Using console.error for Error Reporting

In the past, `console.log` was often used for error reporting. However, this isn't always the best approach. Sometimes, it's necessary to use `console.error` instead of `console.log`.

The Benefits of using console.error

Here are some benefits of using `console.error` for error reporting:

* `console.error` logs errors in a different color and with more detail than `console.log`.

* It provides better feedback on what went wrong.

* It allows you to take action when an error occurs, rather than just ignoring it.

Reporting Errors to the User

In addition to logging or reporting errors internally, we may also want to report them to the user. This can be done using various means such as email notifications, in-app alerts, or even messaging services like Twilio.

Conclusion

Making clean code is essential for writing efficient, maintainable, and scalable software systems. By following best practices for testing, concurrency, error handling, and code organization, developers can write cleaner, more readable code that's easier to understand and modify.

In conclusion, this article has explored the key principles of making clean code using promises and async/await for writing asynchronous code in JavaScript.

"WEBVTTKind: captionsLanguage: enin this video I will be covering how to make your code clean in testing concurrency and error handling it's always good to strive for 100% test coverage of your code there are plenty of good testing Frameworks for JavaScript and the following principle applies to all of them you should just use a single concept per test so in this bad example um we're using the the assert um test framework and this test actually is testing for three different things you can see we're trying trying out three different things in regards to the dates and this uh make moment JS great again so this is the bad way to do it the good way to do it is to create three different tests so now we have it handles 30-day months it handles leap years it handles non- leap years before remember we just had it handles date boundaries so you us should just use a single concept per test the next thing I want to talk about is concurrency you should use es6 promises not callbacks callbacks aren't clean and they cause a lot of nesting sometimes you need them but in es6 promises are a built-in Global type so here you can see we use some callbacks when we're getting the free code Camp Wikipedia page so we get that page and then we have this call back and then we have to see if there's an error then we're going to write the file and then there's another call back and then we have to check on the error and then there's a lot of nesting here but if we just use promises it's going to look like this so here you can see that that looks a lot simpler we're still getting that the page but then we're going to use the dot then notation the do then function to say what what's going to happen after we get the page which is we're going to write the file and then we're going to use the do then function again to log the files written and then we can catch all the errors in one place as opposed to having a bunch of places where we catch the errors so promises are cleaner than callbacks however ever if you're using es8 I know most people at this time are on es6 but an es8 async and a weight are even cleaner than promises so the bad code in this section is actually the same as the good code in the last section because it it is good to use promises but it's even better to use async await if you can so this is how it looks like with promises but with async await it's even simp all you need is a function that starts with the async keyword and then you can write your logic imperatively without a then chain of functions so we have a sync and then we can say we're going to await this and when that's done we're going to await that and then you can just console that log just like we did before and then catch errors down there because this is all in a tri catch block the last thing I want to talk about is error handling um there's just one main thing to know about for this which is just to not ignore caught errors don't ignore caught errors logging the errors to the console with console.log is sometimes not even much better than doing nothing because it can get lost in a SE of things printed to the console a lot of programs have a lot of things logged to the console so with just console. log you may not you may miss it also anytime you have a try catch block you need to do something with the error because that means you're you're expecting to possibly have an error so one thing you can do instead of console.log is console. error console. error is better than console.log to log errors because it highlights the error in red and gives a little extra information and these other functions uh notify user of error and Report error to service are not built into JavaScript this is just showing that you can create functions that do these things and you probably should create functions that do those things if possible and as you can see above you should always make sure you handle errors for rejected promises or the rejected async await functions okay that's all for this video this video is based on Ryan mcdermitt's excellent article on clean code and JavaScript check the description for the link my name is Bo KS thanks for watching don't forget to subscribe and remember use your code for goodin this video I will be covering how to make your code clean in testing concurrency and error handling it's always good to strive for 100% test coverage of your code there are plenty of good testing Frameworks for JavaScript and the following principle applies to all of them you should just use a single concept per test so in this bad example um we're using the the assert um test framework and this test actually is testing for three different things you can see we're trying trying out three different things in regards to the dates and this uh make moment JS great again so this is the bad way to do it the good way to do it is to create three different tests so now we have it handles 30-day months it handles leap years it handles non- leap years before remember we just had it handles date boundaries so you us should just use a single concept per test the next thing I want to talk about is concurrency you should use es6 promises not callbacks callbacks aren't clean and they cause a lot of nesting sometimes you need them but in es6 promises are a built-in Global type so here you can see we use some callbacks when we're getting the free code Camp Wikipedia page so we get that page and then we have this call back and then we have to see if there's an error then we're going to write the file and then there's another call back and then we have to check on the error and then there's a lot of nesting here but if we just use promises it's going to look like this so here you can see that that looks a lot simpler we're still getting that the page but then we're going to use the dot then notation the do then function to say what what's going to happen after we get the page which is we're going to write the file and then we're going to use the do then function again to log the files written and then we can catch all the errors in one place as opposed to having a bunch of places where we catch the errors so promises are cleaner than callbacks however ever if you're using es8 I know most people at this time are on es6 but an es8 async and a weight are even cleaner than promises so the bad code in this section is actually the same as the good code in the last section because it it is good to use promises but it's even better to use async await if you can so this is how it looks like with promises but with async await it's even simp all you need is a function that starts with the async keyword and then you can write your logic imperatively without a then chain of functions so we have a sync and then we can say we're going to await this and when that's done we're going to await that and then you can just console that log just like we did before and then catch errors down there because this is all in a tri catch block the last thing I want to talk about is error handling um there's just one main thing to know about for this which is just to not ignore caught errors don't ignore caught errors logging the errors to the console with console.log is sometimes not even much better than doing nothing because it can get lost in a SE of things printed to the console a lot of programs have a lot of things logged to the console so with just console. log you may not you may miss it also anytime you have a try catch block you need to do something with the error because that means you're you're expecting to possibly have an error so one thing you can do instead of console.log is console. error console. error is better than console.log to log errors because it highlights the error in red and gives a little extra information and these other functions uh notify user of error and Report error to service are not built into JavaScript this is just showing that you can create functions that do these things and you probably should create functions that do those things if possible and as you can see above you should always make sure you handle errors for rejected promises or the rejected async await functions okay that's all for this video this video is based on Ryan mcdermitt's excellent article on clean code and JavaScript check the description for the link my name is Bo KS thanks for watching don't forget to subscribe and remember use your code for good\n"