Categories
JavaScript Best Practices

JavaScript Clean Code — Function Exceptions and Duplicate Code

Functions are important parts of JavaScript programs. They are used for dividing code up into reusable chunks that does one thing mostly.

Therefore in order to have clean JavaScript code, we have to have easy to understand functions.

In this article, we’ll look at more parts of a function including output arguments, command query separation., throwing exceptions, and duplicated code.

Output Arguments

Output arguments are arguments that are accepted by a function that’s directly returned by the function.

This is weird since arguments are usually interpreted as inputs rather than being directly used as outputs. There aren’t many use cases for this. Usually, the arguments are computed in some way by combining them or checking them and returning the results by these checks and operations.

In JavaScript, if we want to change a shared state, we can put shared as state as class members and then we can have methods to manipulate the class members.

So we should write something like:

class FruitStand {
  constructor(numFruits) {
    this.numFruits = numFruits;
  }

  addFruit() {
    this.numFruits++;
  }

  removeFruit(numFruits) {
    this.numFruits--;
  }
}

rather than returning arguments that are passed in.

Command Query Separation

A function should either change the state of an object, or it should return some information about an object. However, it shouldn’t do both.

For example, we shouldn’t have a function like the following:

const setProperty = (obj, property, value) => {
  obj[property] = value;
  return value;
}

The function changes the obj object in place and also returns the value.

It does 2 things, which isn’t good, and the name doesn’t convey that also returns some information about the object. This misleads the user of this function when he or she didn’t read the function definition and just goes by the name.

Therefore, it’s better to separate the property setting and returning the value as follows:

const setProperty = (obj, property, value) => {
  obj[property] = value;
}

const getProperty = (obj, property) => {
  return obj[property];
}

It’s just much better to have functions that do one thing each like we have above so people don’t get confused about what they’re doing.

Throwing Exceptions in Better than Returning Error Codes

Returning error codes violate the command and query separation rule that we mentioned above. This is because the function that returns something returns it when an error occurs and returns something else when the function runs successfully.

This means the function both do something, which forms the command part and returns something, which forms the query part.

It should only do one or the other. Since the main purpose of the function is to do something rather than return something, so it should just do the command part rather than also returning an error code.

This means instead of writing like the following:

const setProperty = (obj, property, value) => {
  obj[property] = value;
  if (!value) {
    return 'Value not found';
  }
}

We should instead throw an exception as follows:

const setProperty = (obj, property, value) => {
  if (!value) {
    throw new Error('Value not found');
  }
  obj[property] = value;
}

Then we can catch and handle it if we need to:

try {
  let obj = {};
  setProperty(obj, 'foo', null)
} catch (ex) {
  console.log(ex);
}

We can eliminate lots of error code checking conditional statements with try...catch instead of having an if statement to check each error code returned by a function.

Extract Try…Catch Blocks

try blocks shouldn’t contain normal processing code. This is because it makes it confusing as to where we’re expecting errors to be thrown.

Instead, we should just wrap the code that we expect to have errors thrown inside a try block. Then we can write a catch block right below it to catch the exception.

For example, if we have normal code and code where exceptions need to be caught, then we can write the code as follows:

const functionThatThrowsError = () => { //... };
const doSomething = () => { //... };
const runFunctionThatThrowsError = () => {
  try {
    functionThatThrowsError();
  } catch (ex) {
    console.log(ex);
  }
}

const runEverything = () => {
  doSomething();
  runFunctionThatThrowsError();
}

The code above isolates the exception throwing and handling code into its own function, which makes it clear to the reader that the particular throws an exception that needs to be handled.

Don’s Repeat Yourself

Repeating code is definitely a big no-no. Repeated code has to be changed in multiple places when one thing changes. It’s also easy to miss repeated code.

The code also becomes a lot more bloated since they’re repeated in different places.

There’re many ways to eliminate duplicated code in JavaScript, like with functions and modules. We should use those as much as possible.

If we have repeated object declarations, then we should also use classes as a template to create those objects.

Repeated literals should be assigned to a constant and reused.

Conclusion

Output arguments should be eliminated because we don’t have to use them to change shared states in JavaScript.

Functions that do something should be separated from functions that return something.

Also, pieces of code that throw exceptions are preferred to code that returns error codes. The exception throwing code should be separated into its own function when we need to handle the exception to make our intentions clear that we want to handle the exceptions.

Repeating code is bad. It takes more time to change the code since we have to change them in multiple places. We should take steps to eliminate them by using code that can be accessed in different places.

Categories
JavaScript Best Practices

JavaScript Clean Code — Functions

Functions are important parts of JavaScript programs. They’re used for dividing code up into reusable chunks that do one thing.

Therefore in order to have clean JavaScript code, we have to have easy to understand functions.

In this article, we’ll look at how to write functions that are clean and easy to read and change. The most important thing is to write small functions.

Small Functions

Functions should be small. Smaller functions do less and it’s easier to read. Each line in a function should be around 100 characters long so they fit on any screen.

Doing less means less code means that it’s easier to read. If a function does more than a few things, then it should be divided into smaller functions.

Making small functions is very difficult in old JavaScript code since functions are used for many things they shouldn’t be used for like creating blocks and namespacing code.

However, now that we have JavaScript modules as a standard, we can gradually transform functions into doing things that functions are supposed to do, which is doing one thing.

For example, instead of creating blocks with functions as follows:

(function() {
  var numFruits = 1;
})();

We can instead write:

{
  let numFruits = 1;
};

They both create isolation, but instead of abusing the use of functions, we instead have just an isolated block of code. We can do this with ES6 or later.

let and const should be used to create block-level variables and constants respectively.

In addition, we can use modules if we want to put related pieces of code into a group. They can be used by importing the exported members of another module.

For example, we can create a file called fruit.js that exports a member as follows:

export color = 'red';

Then we can import it in another module called main.js as follows assuming that they’re in the same folder:

import { color } from './fruit'
console.log(color);

Then we get code isolation without using functions.

Blocks and Indent

Indentation should be automatically done with code formatters. We should have conditional statements and loops that are indented with 2 spaces.

Spaces are better than tabs because they don’t create issues with different operating systems. Tabs might look messed up in some systems.

We can use ESLine, JSLint or other linters to deal with indentation if we aren’t using a text editor that does formats JavaScript code automatically.

Do As Little As Possible

Usually, good functions should only do one thing. Long function is hard to read and if they have a lot going on, then it confuses the reader of the code.

The one thing may be hard to know. If it does more than one action, then it’s probably too much.

For example, code for rendering simple HTML to the user can be one function since that’s all it does.

However, if the HTML has many parts in it like looping through items retrieved from an API in multiple places and if statements, and so on, then they should split up into their own function.

If one function has lots of conditionals and loops, then they can probably be split into their own functions.

Another way to know if we can move something into its own function is that we can describe the piece of code without restating the implementation of the function.

One Level of Abstraction

Each function should only have one level of abstraction. This means if a function does something that has a high level of abstraction then it should only do that.

For example, if we want to write a function that loops through elements of an array and adds it to a list, then it should only do that.

Below is an example of dividing code into functions by the level of abstraction:

const addFruitLis = (fruits, ul) => {
  for (const f of fruits) {
    const li = document.createElement('li');
    li.innerHTML = f;
    ul.appendChild(li);
  };
}

const addFruitUl = (fruits) => {
  const ul = document.createElement('ul');
  addFruitLis(fruits, ul);
  document.body.appendChild(ul);
}

const fruits = ['apple', 'orange', 'grape'];
addFruitUl(fruits);

In the code above, we have a function addFruitLis that create the li elements and append it to the ul element that’s in the parameter.

This is one level of abstraction because we’re adding the li elements after the ul element is generated. It’s one level below the ul in terms of hierarchy.

Then we defined the addFruitUl function to create the ul element and delegate the addition of li elements to the addFruitLis function. Then the ul is appended to the document’s body. This way, each function only does as little as possible.

Finally, we call the addFruitUl function by passing in an array and then we get the elements on our page.

Each function only deals with one level of abstraction, as addFruitLis only deals with the li elements in the ul element and addFruitUl only deals with the ul element.

The wrong way to write the code above would be to combine everything into one function. It makes the function’s code complex and confusing.

Conclusion

Functions should do a little possible. We can do this by isolating them in blocks and modules. Old code that uses functions to do that should be eliminated.

Also, each function should do as little as possible and only deal with one level of abstraction. Otherwise, the function’s code gets long and confusing.

Categories
JavaScript Best Practices

JavaScript Clean Code — More About Naming

Writing clean, readable, and maintainable code takes some effort. One of the most basic parts of a program is identifiers. To make reading and changing the code easier, the naming of them has to be good.

In this article, we’ll look at some ways to name things in an easy to understand way.

Avoid Mental Mapping

Developers shouldn’t have to map their names into their meaning in their brains.

For example,

let r;

is a bad variable declaration for something that holds a URL string since there’s nothing about URL in the name r .

We can just name it url like we wanted to save the effort of mapping it in our brains.

Clarity is the most important thing when naming things.

Class Names

In JavaScript, class names are upper camel case. So FruitStand is a good name and fruitStand is not a good name for a class.

We should stick with convention to avoid confusion and mistakes.

Method Names

Method names should have camel case names in JavaScript. For example, getName is a good name for a function but GetName isn’t.

Don’t Use Clever Names

We should use clever names to confuse readers of our code. For example, holyCow is a bad variable for something that holds the number with the number of fruits since it doesn’t convey the actual content of the variable.

It makes the code hard to read and it’s not really funny.

Instead, we should name if numFruits so people actually know that the variable holds the number of fruit.

We should name things by what they mean.

Pick One Word Per Concept

We should pick one word per concept. For example, if we want to convey that a function gets a value. Then we shouldn’t have fetch, get, or grab in different function names.

Picking one word per concept reduces the mental capacity required for developers to understand the code since everything is predictable.

No Puns

Having 2 words for the same purpose in identifiers makes them confusing. Therefore, we should avoid them since they can be interpreted differently by different people.

For example, augment is a bad name for a function that can mean adding entries to arrays, or appending things to a string. So we should name it with the name that shows what it actually does.

Name that Developer Understand

It’s important to name things that developers understand. In our code, we should name things that are relevant to the domain of the solution.

For example, many developers know what a MessageQueue or Database is. Therefore, those are good names.

Problem Domain Names

If there’re no names in technical speak that developers understand, then we should name things in a way that describes the problems that we’re trying to solve.

Meaningful Context

We should name things with meaning context to our identifier names. For example, username and password are good names because we know that these variables are about the user entity which is used for logging into a system.

On the other hand, generic names like number and modifier aren’t good variables names because they don’t provide much context about what we’re set to values of these variables to.

If we’re using these names to construct a string that has the quantity of something and then the modifier for the thing we’re quantifying, then we should write something like:

let numberOfItems = 1;
let pluralModifier = numberOfItems ? '' : 's';
let numItemsString = `${numberOfItems} item${pluralModifier}`;

As we can see, these names are much more meaningful than number and modifier . They provide us with the context of the situation that the variables are used.

Don’t Add Useless Context

Useless context is also bad. For example, if we prefix every identifier with foo or Foo because we’re writing software for the company Foo, that’s bad because we already know that the software is for company Foo, so we don’t need to add the company name to everything and take up more space on the page and disk space.

We only need enough information in our names to convey the meaning of the identifier. If we can do it in a shorter way, then it’s better.

Naming things the right way takes some thought. We should add only enough context that people will gain a better understanding of the code.

Also, there shouldn’t be a need for developers to mentally map the names to something in their minds. If it’s needed then the name has to convey more meaning.

Clever names and puns are also bad since they’re misleading.

Finally, sticking to conventions of JavaScript is much needed so avoid confusion.

Categories
JavaScript Best Practices

JavaScript Clean Code — Naming

Writing clean and easily readable and maintainable code takes some effort. One of the most basic parts of a program is identifiers. To make reading and changing the code easier, the naming of them has to be good.

In this article, we’ll look at some ways to name things in an easy to understand way.

Intention Revealing Names

Names have to have the intention of what you’re trying to define. This way, people will know what your identifier actually means.

Function, class, variables, and constants should all names that show what they’re used for.

For example,

let x;

would be a bad variable declaration because x doesn’t reveal with it’s doing.

We should name it something like:

let numApples;

so we know that our variable actually holds the value of the number of apples.

As we can see, numApples is much easier to understand than x .

Likewise, for arrays, we should name them with meaningful names. For instance:

let list = [];

isn’t a good name because we don’t what list actually holds. Instead, we should write something like:

let fruits = [];

So we know that the array holds Fruit objects.

Avoid Misleading Names

Names shouldn’t be misleading. They shouldn’t be leaving false clues for the reader and lead them to the wrong conclusion about your identifiers.

For example, fruitArray should actually be an array rather than anything else. This is especially important in JavaScript because the types of variables can change and there’re no type annotations to let us figure out what the type is.

Names should also have a consistent convention. In JavaScript, variables are camel case. Constants are upper case and functions and classes are upper camel case.

So we should stick with that and don’t deviate from it. Otherwise, it gets confusing fast and other developers looking at our code can easily miss the different cases.

For instance:

let FruitArray;

isn’t a good variable declaration since it starts with a capital letter.

It should instead be:

let fruitArray;

The consistent convention makes code easy to read and remember.

Meaning Distinctions

To make identifiers distinct, we should name them in a meaningful way.

For example, if we want to copy an array from the source to the destination array, we shouldn’t write something like:

let a2 = [...a1];

since we don’t know what a2 and a1 means. Number series naming as we had above is bad. It doesn’t reveal the intentions of the names.

Instead, we should name them for what they are. So we can write:

let destinationArray = [...sourceArray];

The code above is much clearer since we know that they’re both arrays and we know that we’re making a copy of sourceArray and set as the value of destinationArray .

They’re still distinct and they reveal their meanings.

We shouldn’t add noise words like variable in a variable. It makes the name longer without revealing additional information.

However, adding the type name may be helpful in some cases since we’re always assigning literals to a variable or constant. Since JavaScript has dynamic types, the type can be added to the name in cases that we aren’t assigning literals to something.

Pronounceable Names

Pronounceable name are easier to remember and understand. Therefore, we should name things in a way that is pronounceable.

Also if it’s easier to pronounce, people won’t look dumb when they’re discussing about something with such names.

For example:

let genmdy;

isn’t a good name for a variable that means generated date and time because nobody knows how to pronounce it.

Instead, we can instead write:

let generatedDateTime;

would be much better since it reveals more information and it’s pronounceable.

Searchable Names

Developers often have to search through to add new code and debug. Therefore, it’s important to have names that are searchable by typing in the search box or command line.

This means that variable declarations like:

let a;

is bad since the character a is everywhere in almost all pieces of code. This means that it’s hard to search for it when we need to.

Instead, we should write something longer and more meaningful like:

let numApples;

so we can search for it.

Stick to Plain English Letters and Digits

Plain English letters and digits aren’t encoded in any special way, so it won’t cause problems in different systems and we can easily search for the names.

Also, most languages have English keywords so it’s more consistent with the rest of the code.

It justs taxes people’s brains more to figure out the encoding of characters of different languages. That’s the time that can be used to read and code.

Member Prefixes

We don’t need prefixes are class and function member names since they’re already inside the class. Namespacing them with a prefix is just extra noise. Also, classes and functions should be small enough that there shouldn’t be too many members.

Most people also ignore the prefix and look straight at the name.

Therefore, something like:

let m_description;

isn’t any more useful than:

let description;

It just takes up more space and creates noise.

Naming things properly takes some effort. We have to make identifiers with meaningful names that reveal their intentions. Also, the convention should be consistent to reduce confusion and mistakes.

Identifiers should also be searchable and pronounceable so that people can look for them and talk about them without sounding dumb.

Characters with special encoding also shouldn’t be used to avoid extra useless effort.

Finally, we don’t need prefixes in member names since there shouldn’t be soo many that they need to be namespaced.

Categories
JavaScript Best Practices

Why it’s Time to Stop Using JavaScript IIFEs

In JavaScript speak, IIFE stands for Immediately Invoked Function Expressions.

It’s a function that’s defined and then executed immediately.

In this article, we’ll look at why it’s time to stop writing IIFEs in our code.

We Can Define Block-Scoped Variables in JavaScript

Since ES6 is released as a standard, we can declare block-scoped variables and constants with let and const. It also introduced stand-alone blocks to isolate variables and constants into their own blocks, unavailable to the outside.

For example, we can write:

{
  let x = 1;
}

Then x wouldn’t be available to the outside.

It’s much cleaner than:

(()=>{
  let x = 1;
})();

Now that ES6 is supported in almost all modern browsers, we should stop using IIFEs to separate variables from the outside world.

Another way to isolate variables are modules, which are also widely supported. As long as we don’t export them, they won’t be available to other modules.

We Don’t Need Closures As Much Anymore

Closures are functions that return another function. The returned function may run code that’s outside of it but inside the enclosing function.

For example, it may commit some side effects as follows:

const id = (() => {
  let count = 0;
  return () => {
    ++count;
    return `id_${count}`;
  };
})();

Again, this is more complex and unnecessary now that we have blocks and modules to isolate data.

We can just put all that in their own module, then we won’t have to worry about exposing data.

It also commits side effects, which isn’t good since we should avoid committing side effects whenever possible. This is because they make functions hard to test as they aren’t pure.

Functions that return functions also introduce nesting when we can avoid it and so it’s more confusing than ones that don’t.

The better alternative is to replace it with a module.

With a module, we can write:

let count = 0;

export const id = () => {
  ++this.count;
  return `id_${count}`
}

In the code above, we have the same count declaration and we export the id function so that it can be available to other modules.

This hides count and exposes the function we want like the IIFE, but there’s less nesting and we don’t have to define another function and run it.

Aliasing Variables

Again, we used to write something like this:

window.$ = function foo() {
  // ...
};

(function($) {
  // ...
})(jQuery);

Now we definitely shouldn’t write IIFEs just to create aliases for variables since we can use modules to do this.

With modules, we can import something with a different name.

Today’s way to do that would be to write:

import { $ as jQuery } from "jquery";

const $ = () => {};

Also, we shouldn’t attach new properties to the window object since this pollutes the global scope.

Capturing the Global Object

With globalThis , we don’t have to worry about the name of the global object in different environments since it’s becoming a standard.

Therefore, we don’t need an IIFE to capture the global object by writing the following in the top-level:

(function(global) {
  // ...
})(this);

Even before globalThis , it’s not too hard to set the global object by writing:

const globalObj = self || window || global;

Or if we want to be more precise, we can write:

const getGlobal = () => {
  if (typeof self !== 'undefined') { return self; }
  if (typeof window !== 'undefined') { return window; }
  if (typeof global !== 'undefined') { return global; }
  throw new Error('unable to locate global object');
};

Then we don’t have to add the extra function call and nesting introduced by the IIFE.

Optimization for Minification

With JavaScript modules, we don’t have to segregate code with IIFEs any more so that our files can minify properly.

Webpack, Browserify, Parcel, Rollup, etc., can all deal with modules properly, so we should use them instead to create much cleaner code.

Conclusion

It’s time to stop writing IIFEs in our code. It adds extra function definitions and nesting.

Also, it’s an anachronism from the times before JavaScript modules are introduced and widely used. In 2020, we should use modules and blocks for segregating code.

Block scoped variables are used for keeping variables from being accessible from the outside within a module.