Categories
JavaScript Best Practices

Maintainable JavaScript — Names

Creating maintainable JavaScript code is important if want to keep using the code.

In this article, we’ll look at the basics of creating maintainable JavaScript code by improving naming.

Naming

To make our JavaScript code maintainable, we got to make the names descriptive so that we know what they do fro the names.

Also, the case should be consistent so that we won’t be confused with the names.

Variables and function should be camel case,

Camel case means that the name starts with a lower case letter and each subsequent word starts with an uppercase letter.

For instance, these are camel case:

let myName;
const someVariable;
let veryLongName;

They all start with a lower case with subsequent words start with upper case.

Variables and Functions

Variable names are camel case and should start with a noun.

This way, we know what they store.

For example, we can write:

let count = 10;
const firstName = "james";
let isTuesday = true;

to define variables with nouns.

If we define variables with other kinds of words like verbs, then we’ll easily confuse them with functions.

So we shouldn’t define variables with names like:

let getCount = 10;

get implies that we’re doing something so that doesn’t make sense.

However, we should create functions that starts with verbs:

function getCount() {
  return 10;
}

We’re getting some value when we call getCount so it makes sense for the function to start with get .

This also means that our function names shouldn’t look like variable names.

For instance, if we have:

function theCount() {
  return 10;
}

then we’ll easily confuse that with a variable.

Naming is more of an art than a science, but there’re some conventions we can follow.

Words like count , length , and size suggests number.

And words like name and message suggests that it’s a string.

Meaningless names like foo or bar should be avoided.

Some conventions for function names include prefixes like:

  • can to suggest a function that returns a boolean
  • has is a function to return a boolean
  • is is the same as can or has
  • get suggests that a function is returning a non-boolean value
  • set is a function that’s used to save a value

For example, if we have:

if (canSetName()) {
  setName("nick");
}

then we know that if we can set the name, then we set the name.

Another example would be:

if (getName() === "nick") {
  jump();
}

Then we know that we’re getting the name with getName and we’re doing something with jump .

Constants

Before ES6, there’s no concept of constants.

But now, we can define constants with const .

The names for constants should be upper case.

For example, we can write:

const MAX_COUNT = 10;

to let everyone know that MAX_COUNT is a constant.

Constants can’t be reassigned to a new value, but they’re mutable.

Having a separate convention for constants lets us distinguish between variables and constants.

Conclusion

We should follow some conventions for variable and function names and constants.

Categories
JavaScript Best Practices

Maintainable JavaScript — Multiline Comments

Creating maintainable JavaScript code is important if want to keep using the code.

In this article, we’ll look at the basics of creating maintainable JavaScript code by creating better multiline comments.

Multiline Comments

Multiline comments are comments that can span multiple lines.

They start with /* and ends with */ .

Multiline comments don’t have to span multiple lines.

For instance, we can write:

/* one line comment */

We can also write:

/* two line
comment */

or:

/*
two line
comment
*/

They’re all valid, but it’s better to put the asterisk on the left side so we won’t confuse it for code.

For example, we can write:

/*
 * two line
 * comment
 */

This is neater and delimits all the comment content.

Multiline comments always come before the code they describe.

They should be preceded by an empty line and should be at the same indentation as the code we’re commenting on.

For instance, we should write:

if (hasAllPermissions) {

  /*
   * if you made it here,
   * then all permissions are available
   */
  allowed();
}

We added a line before the comment to make it more readable.

This is better than:

if (hasAllPermissions) {
  /*
   * if you made it here,
   * then all permissions are available
   */
  allowed();
}

which has no line before it.

We should also have a space between the asterisk and the text.

For instance, we can write:

if (hasAllPermissions) {

  /*
   *if you made it here,
   *then all permissions are available
   */
  allowed();
}

It’s hard to read after the asterisk without a space.

We should also have proper indentation, so we shouldn’t write:

if (hasAllPermissions) {

/*
 *if you made it here,
 *then all permissions are available
 */
  allowed();
}

The intention should match the code that the comment is commenting on.

Also, we shouldn’t use multiline comment for trailing comments.

For instance, we shouldn’t write:

let result = something + somethingElse; /* they're always numbers */

We should leave multiline comments for block comments.

Using Comments

What to comment on is always a controversial topic.

But there’re some common conventions that most people accept.

One thing we shouldn’t do is to comment on things that are already described by the code.

So we shouldn’t have comments like:

// set count
let count = 100;

We know that we’re setting count by looking at the code, so we don’t need a comment for that.

But if there’s something that needs explaining, then we can do that.

For instance, we can write:

// this will make it rain
let count = 100;

Now we know changing count will make it rain.

Difficult-to-Understand Code

If we have hard to understand code, then we should put a comment on it.

If there’s anything that’s hard to understand by just reading the code, then we should add some comments.

Conclusion

We should be careful when using multiline comments.

Also, if we have anything that’s not obvious from the code, then we should write a comment on it.

Categories
JavaScript Best Practices

Maintainable JavaScript — Loops and Variables

Creating maintainable JavaScript code is important if want to keep using the code.

In this article, we’ll look at the basics of creating maintainable JavaScript code by looking at various block statements and declaring variables.

The for-in Loop

The for-in loop is used for iterating over the properties of an object.

Instead of defining control conditions, the loop goes through each property and returns the property name in a variable.

For instance, we can use it by writing:

for (const prop in object) {
  console.log(prop, object[prop]);
}

object is the object, prop is the property key.

The for-in loop gets all the properties in the object itself and all its prototypes.

So we may end up with results that we don’t expect.

Therefore, we want to use the hasOwnProperty method to check if the property is in the method.

For instance, we can write:

for (const prop in object) {
  if (object.hasOwnProperty(prop)) {
    console.log(prop, object[prop]);
  }
}

Some style guides, like Douglas Crockford’s requires the hasOwnProperty in for-in loops.

Both ESLint and JSHint warns us when we use for-in loop without the hasOwnProperty method.

A common mistake is to use the for-in loop to iterate over an array.

For example, we shouldn’t use the for-in loop to loop through an array:

const values = [1, 2, 3, 4, 5];

for (const i in values) {
  console.log(values[i]);
}

This is because the order isn’t guaranteed.

And it’s not its intended purpose.

The for-in loop is for treating over keys of the object and its prototype.

The for-of Loop

The for-of loop lets us iterate through an iterable object.

This is the loop that we should loop through an array.

For instance, we can use it by writing:

const values = [1, 2, 3, 4, 5];

for (const val of values) {
  console.log(val);
}

val is the entry of the array.

We can loop through any iterable object, so we can loop through maps and sets.

For example, we can write:

const values = new Set([1, 2, 3, 4, 5]);

for (const val of values) {
  console.log(val);
}

and:

const values = new Map([
  [1, 'foo'],
  [2, 'bar'],
  [3, 'baz']
]);

for (const val of values) {
  console.log(val);
}

We can destructure the keys of a map:

const values = new Map([
  [1, 'foo'],
  [2, 'bar'],
  [3, 'baz']
]);

for (const [key, val] of values) {
  console.log(key, val);
}

This is the recommended loop by many style guides like ESLint and Airbnb.

Variable Declarations

Variable declarations can be done with the var , let or const keywords.

var is the old way to declare variables.

We should use let and const since they’re block-scoped and they’re only available after they’re defined.

const variables also can’t be reassigned.

For instance, instead of writing:

function doWork() {
  var result = 20 + value;
  var value = 30;
  return result;
}

We write:

function doWork() {
  const value = 30;
  const result = 20 + value;
  return result;
}

We use const as many as places as we can so the variables can’t be reassigned accidentally.

Conclusion

The for-in loop is only used for iterating through the keys of an object.

The for-of loop is for iterating through any iterable object.

Also, var should no longer be used for declaring variables.

Categories
JavaScript Best Practices

Maintainable JavaScript — Lines

Creating maintainable JavaScript code is important if want to keep using the code.

In this article, we’ll look at the basics of creating maintainable JavaScript code by improving formatting.

Line Length Conventions

There’re various line length conventions we can use as guidelines to come up with our own conventions.

Java’s style guide specifies 80 characters as the max length of a line.

The Android style guide specifies 100 characters.

Ruby specifies 80 characters.

Python specifies 79 characters.

Therefore, around 80 to 100 is probably a suitable length for a line.

Line Breaks

When a line reaches a maximum length, then we’ve to split them into 2 lines.

If a line is a continuation of the previous line, then we indent it.

For instance, we can write:

callAFunction('foo', 'bar', window, document, true, 123,
  navigator);

We indent the continuation of the first line with 2 spaces so that we can see the indentation.

This way, we know the 2nd line is actually th continuation of the first line.

The comma stays in the first line for more clarity.

We should use the same convention for statements.

For instance, we can write:

if (isLeapYear && isFebruary && day == 29 && isBirthday &&
  hasNoPlans) {
  wait4Years();
}

We also have an indent in the boolean expression we passed into the if statement.

The && operator stays in the first line.

The assignment of variables can be indented the same way.

For example, we can write:

let result = something + anotherThing + anotherThing +
  somethingElse + oneMoreThing + anotherSomethingElse;

to indent the code the same way.

Blank Lines

Blank lines are useful for grouping bunch of code together,

We can make our code clearer by inserting some blank lines between the groups.

For example, we can write:

if (wl && wl.length) {
  for (i = 0, l = wl.length; i < l; i++) {
    p = wl[i];
    type = Y.Lang.type(r[p]);
    if (s.hasOwnProperty(p)) {
      if (merge && type == 'object') {
        Y.mix(r[p], s[p]);
      } else if (!(p in r)) {
        r[p] = s[p];
      }
    }
  }
}

We have all the code bunched together which makes them hard to read.

Instead, we can write:

if (wl && wl.length) {

  for (i = 0, l = wl.length; i < l; i++) {
    p = wl[i];
    type = Y.type(r[p]);

    if (s.hasOwnProperty(p)) {

      if (merge && type == 'object') {
        Y.mix(r[p], s[p]);
      } else if (!(p in r)) {
        r[p] = s[p];
      }
    }
  }
}

We have some extra blank lines in if and for statements so that we can read them easier.

A good convention for adding blank lines would be:

  • between methods
  • between local variables and methods and its first statement
  • between comments
  • between logical sections in a method

They all make our code easier to read.

Conclusion

We can make our code easier to read by indenting our line continuation and add some line breaks.

Categories
JavaScript Best Practices

Maintainable JavaScript — Constructor Names and Strings

Creating maintainable JavaScript code is important if want to keep using the code.

In this article, we’ll look at the basics of creating maintainable JavaScript code by improving naming.

Constructors and Classes

Constructors are used for creating objects.

They’re functions that are called with the new operator.

The class syntax is syntactic sugar for constructors.

JavaScript’s standard library has many built-in constructors like Object or RegExp .

They all have Pascal case, and this is the convention that we should follow with our own constructors.

Instead of someName , we write SomeName for a constructor.

Constructor names are typically nouns since they create objects of a given type.

For instance, we can write:

function Person(name) {
  this.name = name;
}

Person.prototype.greet = function() {
  console.log(`hello ${this.name}`);
};

or:

class Person {
  constructor(name) {
    this.name = name;
  }

  greet() {
    console.log(`hello ${this.name}`);
  }
}

Person starts with upper case so we can tell them apart from other entities like variables and functions.

Following this convention makes the code easier to read.

Errors are also easier to spot.

Almost all JavaScript style guides like Airbnb, Google, etc. all recommend this casing for constructors and classes.

Literal Values

JavaScript code can have various kinds of literal values.

They include strings, number, booleans, null or undefined .

It also has object and array literals.

Booleans can only be true and false so we don’t need to set our own conventions for them.

The other kinds of values need some convention so they stay consistent and reduce confusion.

Strings

Strings can be delimited with single or doubles or backticks.

Single or double quotes delimit traditional strings.

While backticks delimit template literals.

There’re no difference between single and double quotes for strings.

Traditional strings can only be concatenated if we want to create string that has other kinds of expressions in them.

So we can write:

const greeting = 'hello ' + name;

Concatenation is hard to work with when we have multiple expressions.

Making multiline strings is also harder than with traditional strings since we’ve to add the newline characters ourselves.

For instance, we can write:

const greeting = 'hellon' + name;

So if we want to create string with many lines, then we’re going to confused.

We can still use them for short strings.

To make them easy to work with, we stick with either single or double quotes everywhere.

We shouldn’t use the “ sign to create multiline strings since it’s a non-standard syntax and doesn’t work on all engines.

So we shouldn’t write things like:

let longStr = "The quick brown fox jump
 over the dog.";

We have a long string with a “ .

This isn’t a standard.

What we should do is to use a template literal top create our strings.

They can have expressions in them and we don’t have to do any special to create multiline strings.

For example, we can write:

const greeting = `hello ${name}`;

to embed the value of name variable in the string.

And to create a multi-line string, we just write:

let longStr = `The quick brown fox jump
 over the dog.`;

The string will be returned with the new line intact.

Conclusion

We can make creating strings easier with template literals.

Constructors and classes are Pascal case.