• 15 heures
  • Facile

Ce cours est visible gratuitement en ligne.

course.header.alt.is_video

course.header.alt.is_certifying

J'ai tout compris !

Mis à jour le 19/01/2024

Write clean functions

Why is clean code important?

Before we dive into clean coding methods, let's explore why it is important to keep code as clean as possible.

Two colleagues review code on a computer screen.
Clean code is important!

Think of the messiest and least organized place in your home. It may just be a drawer, closet, or even a whole room. How hard is it to find something in that place? If you've recently used it, it's may not so bad, but if it's been a while, things can get tricky.

Things are the same, or worse, with code. If you haven't looked at it in a few months and you didn't write it cleanly, it can take forever to remember which function does what, and how things all fit together.

Now imagine that you inherited someone else's disorganized drawer, closet, or room, and they no longer live there. This is what it is like to work on someone else's code when they haven't kept it clean!

Now that you understand why you need to code cleanly, let's have a look at how!

To function or not to function

When should we use functions? How many should we write? How long should they be?

Let's have a look at some situations in which functions help make your code cleaner.

Don't repeat yourself

If you find yourself writing the same code multiple times, you should probably refactor it into a function.

Consider the following code:

if (firstUser.online) {
    if (firstUser.accountType === 'normal') {
      console.log('Hello ' + firstUser.name + '!');
    } else {
    console.log('Welcome back premium user ' + firstUser.name + '!');
    }
}

if (secondUser.online) {
    if (secondUser.accountType === 'normal') {
      console.log('Hello ' + secondUser.name + '!');
    } else {
    console.log('Welcome back premium user ' + secondUser.name + '!');
    }
}

if (thirdUser.online) {
    if (thirdUser.accountType === 'normal') {
      console.log('Hello ' + thirdUser.name + '!');
    } else {
    console.log('Welcome back premium user ' + thirdUser.name + '!');
    }
}

Here, we are repeating the same task multiple times for different users. This is a good time to refractor your code into a function:

const sendWelcomeMessageToUser = (user) => {
    if (user.online) {
        if (user.accountType === 'normal') {
          console.log('Hello ' + user.name + '!');
        } else {
        console.log('Welcome back premium user ' + user.name + '!');
        }
    }
}

sendWelcomeMessageToUser(firstUser);
sendWelcomeMessageToUser(secondUser);
sendWelcomeMessageToUser(thirdUser);

We have created a function called sendWelcomeMessageToUser (a name which clearly states what the function does) and called it for each user. In this case, we reduced the amount of code from 23 lines to 13 and made it more readable. By using a descriptive function name, you can tell that we are sending a welcome message to three users.

DRYDon't Repeat Yourself — is a programming principle that keeps code repetition to a minimum.

Practice the DRY principle!

Head to CodePen Exercise P3CH3a and follow the instructions below to figure out which code needs refactoring, and how to do so.

This code generates information for the site components and puts it in an array. However, it currently repeats the same code for each show. A great place for a function!

  1. Create a function which allows you to refactor this code, making it shorter and easier to read.

  2. Call your new function for each show to create the corresponding component, passing it the arguments it needs. 

Solution:

Once you've given it a go, watch me code a solution and see how your approach compares. And here is a new CodePen with a solution to the exercice.

In my demonstration, I have several JS files set up, so you'll notice that my code begins with an import from a database and ends with an export to a script. But in the CodePen exercise that you'll be working in, all the JavaScript your program needs is combined in a single file — the JS editor — so there's no need for importing or exporting. 😉

Does anyone know what this does?

Having functions which only do one thing (and have a name which describes what they do) can make your code much cleaner and easier to understand:

Consider the following function:

const printStringStats = (stringToTest) => {
  const wordArray = stringToTest.split(' ');
  const wordCount = wordArray.length;
  let letterCount = 0;
  for (let word of wordArray) {
    word.replace(/[.,\/#!$%\^&\*;:{}=\-_`~()]/g, "");
    letterCount += word.length;
  }
  const averageWordLength = parseFloat((letterCount / wordCount).toFixed(2));
  const stringStats = {
    wordCount: wordCount,
    letterCount: letterCount,
    averageWordLength: averageWordLength
  };
  console.log(stringStats);
}

Although it has a descriptive name, and you can see that it's going to print the word count, letter count, and average word length of a string, there is so much going on that it is hard to follow if you don't understand each line. This function is doing too much at once.

Now consider this refactoring:

const getWordCount = (stringToTest) => {
  const wordArray = stringToTest.split(' ');
  return wordArray.length;
}

const getLetterCount = (stringToTest) => {
  const wordArray = stringToTest.split(' ');
  let totalLetters = 0;
  for (let word of wordArray) {
    word.replace(/[.,\/#!$%\^&\*;:{}=\-_`~()]/g, "");
    totalLetters += word.length;
  }
  return totalLetters;
}

const getAverageWordLength = (stringToTest) => {
  return parseFloat((getLetterCount(stringToTest) / getWordCount(stringToTest)).toFixed(2));
}

const printStringStats = (stringToTest) => {
  console.log({
    wordCount: getWordCount(stringToTest),
    letterCount: getLetterCount(stringToTest),
    averageWordLength: getAverageWordLength(stringToTest)
  })
}

While this version is longer, there are three functions —  getWordCount,  getLetterCount, and  getAverageWordLength  — which are called by the printStringStats function.

You may not understand the intricacies of each function, but you can understand what is going on because they only do one thing, and it's in their name. You could use the individual functions without needing to know what's going on under the hood.

Leave comments

Learning how to leave clear, consistent comments will make you shine as a developer. However, do not comment on every single line or function. Comments should clarify anything which is not immediately clear when reading the code.

There are two types of comments — single-line and multi-line — and each has their place. Let's comment our previous example:

const getWordCount = (stringToTest) => {
  const wordArray = stringToTest.split(' ');
  return wordArray.length;
}

const getLetterCount = (stringToTest) => {
  const wordArray = stringToTest.split(' ');
  let totalLetters = 0;
  for (let word of wordArray) {
    // remove punctuation so as to only count letters
    word.replace(/[.,\/#!$%\^&\*;:{}=\-_`~()]/g, "");
    totalLetters += word.length;
  }
  return totalLetters;
}

/*
** returns average word length to 
** two decimal places
*/
const getAverageWordLength = (stringToTest) => {
  return parseFloat((getLetterCount(stringToTest) / getWordCount(stringToTest)).toFixed(2));
}

const printStringStats = (stringToTest) => {
  console.log({
    wordCount: getWordCount(stringToTest),
    letterCount: getLetterCount(stringToTest),
    averageWordLength: getAverageWordLength(stringToTest)
  })
}

As you can see, not every function or line has a comment.

  • The single line comment explains the reason for the complex-looking replace call.

  • The multi-line comment explains that the average word length will be returned to 2 decimal places, as this is not immediately clear.

Leaving just the right number of comments is a bit of an art form, but practice makes perfect, so make sure you comment your code!

Write code with style

Sticking to a consistent style is necessary for code to remain clean, and while there are no absolute right ways to do things, there are a handful of conventions which can make your life easier.

What's in a name?

Naming conventions

As you have seen so far, variable and function names in JavaScript are generally written in lower camel case (getWordCount,  numberOfCats), while class names are written in upper camel case       (PremiumAccount,  SpecialGuest). You are not obligated to use this convention; however, it makes your code easier to read as it is respected by the vast majority of developers.

Choosing a name

Clear, descriptive names for variables and functions are easier to read than shortened, cryptic, or random ones. For example, consider the following function:

const lc = (s) => {
  const w = s.split(' ');
  let l = 0;
  for (let wel of w) {
    wel.replace(/[.,\/#!$%\^&\*;:{}=\-_`~()]/g, "");
    l += wel.length;
  }
  return l;
}

This function will work perfectly and do what it is supposed to. But what does it do???

100 points if you recognized it as the letter count function from our previous example!

const getLetterCount = (stringToTest) => {
  const wordArray = stringToTest.split(' ');
  let totalLetters = 0;
  for (let word of wordArray) {
    // remove punctuation so as to only count letters
    word.replace(/[.,\/#!$%\^&\*;:{}=\-_`~()]/g, "");
    totalLetters += word.length;
  }
  return totalLetters;
}

Choose your names carefully, and your code will be clear and easy to read (and you won't have to write so many comments!).

Code formatting

The term code formatting covers many areas — here are a handful:

  • Indenting
    Tabs or spaces? Two spaces or four? Whatever you choose, stick to the same style throughout:

    if (userOnline) {
        for (let message of user.messages) {
            message.send();
        }
        sendNotification();
    }
  • Spacing
    Both of the following work identically:

    if(condition) {
        let i=0;
        i+=condition.thing;
        let j=i-3;
    }
    if (condition) {
        let i = 0;
        i += condition.thing;
        let j = i - 3;
    }

    Generally speaking, adding a bit of space makes code easier to read, but both are technically correct. You can only pick one though!

  • Curly brace placement

    if (condition) {
        doTheThing();
    } else {
        doTheOtherThing();
    }

    or

    if (condition) 
    {
        doTheThing();
    } 
    else 
    {
        doTheOtherThing();
    }

Code formatting is the source of many arguments between developers, and it will often depend on the rest of your team. When writing your own code, pick whichever style you prefer and stick to it!

Let's recap!

In this chapter, we looked at some clean coding techniques and best practices:

  • Refactoring code into functions — when code is repeated, or when one function is doing too many things.

  • Having functions with only one purpose are often clearer than multi-purpose functions.

  • Leaving appropriate comments makes your code much easier to understand.

  • Having a strict naming convention with clear, descriptive names is very important.

  • You saw examples of code formatting, and different choices you can make.

In the next chapter, we will look into how to test functions to avoid surprises! 

Exemple de certificat de réussite
Exemple de certificat de réussite