Categories
JavaScript Best Practices

JavaScript Best Practices —Comments

JavaScript is a very forgiving language. It’s easy to write code that runs but has mistakes in it.

In this article, we’ll look at the best practices for commenting code.

Keys to Effective Comments

Wrong comments should be removed. They’re misleading and may lead to developers making wrong decisions.

If they’re just a repeat of the code, then they should definitely not be written.

If there’re any tricky parts of the code that needs explanation, then we may need comments to explain them.

Markers shouldn’t be left in the code. If we use markers to mark defective code that should be fixed, then we should just fix the code.

Summaries of code are better than just repeating code since it lets us look for information more easily with the code.

If a piece of code describes the code’s intent, then it might be useful since it probably isn’t clear from just reading the code.

Information That Cannot Possibly Be Expressed by the Code Itself

Information like copyright can’t be written in the code itself. Therefore, we may need comments to explain them.

Comments that are used for generating documentation are also helpful.

Commenting Efficiently

Commenting shouldn’t be a time-consuming task. Too many or too few comments are both bad.

We got to achieve a middle ground.

If we’re using a tedious commenting style, then we should simplify it.

Words that describe what the program is doing also may not be easy to come by.

Use Styles that don’t Discourage Modification

We should make our comments easy to maintain just like our code.

For instance, if we’re making an elaborate table with comments, then we should consider simplifying that so that others won’t have to update it.

If we use asterisks to delimit comments, then we should reduce those.

Use the Pseudocode Programming Process to Reduce Commenting Time

We can outline code by writing them with pseudocode first before converting them to English.

Integrate Comments into Our Development Style

Leaving comments until the end isn’t a very good habit.

We’ll probably forget to do them and it becomes its own chore.

By the time we finished our code, we probably already forgot about the assumptions and decisions that we want to comment on.

Therefore, we should just comment as we code to make our lives easier and before we forget what to write.

Performance is not a Good Reason to Avoid Commenting

Comments increase code file size, but compilers and interpreters ignore them, so the performance hits are negligible if there’s any.

Optimum Number of Comments

We should just comment as much as we need to and forget about an optimum number of comments.

Avoid Self-Indulgent Comments

We shouldn’t write comments just to express our feels in the code.

No one really cares and they take up valuable space.

Endline Comments and Their Problems

Endline comments don’t align to the right side of the code since it’s hard to do so.

Also, we’ve to move our cursor all the way to the right to add or edit the comment.

Therefore, they’re hard to maintain and most people won’t want to touch them.

If they’re on the right, then people writing the comment have to make them short to keep the line lengths short.

Therefore, there isn’t much benefit to keeping them on the right and lots of problems.

Avoid Endline Comments on Single Lines

We shouldn’t comment on every line of our code. And we shouldn’t have them on the right.

There’s not that much to write about for one line of code.

Avoid Endline Comments for Multiple Lines of Code

Our comments probably won’t fit at the end of the line.

It’s just a bad place for comments.

Use Endline Comments to Annotate Data Declarations

Data declarations can have comments placed on the right of them.

These lines are usually short, so there’s space for comments to the right.

Avoid Using Endline Comments for Maintenance Notes

Since we’re supposed to be using version control systems for storing code, maintenance notes belong to the commit comments.

Therefore, keep them out of the code files.

Use Endline Comments to Mark Ends of Blocks

If we have long blocks, then we should mark the end of blocks with end line comments.

This way, we know where’s the end of each block is.

Conclusion

Comments can be tricky. We shouldn’t use them to repeat our code or commit comments.

Also, comments at the end of a line should be used sparingly or short lines.

Comments should also be easy to maintain so that we’ll be willing to update them.

Categories
JavaScript Best Practices

JavaScript Best Practices — Code Organization

JavaScript is a very forgiving language. It’s easy to write code that runs but has issues in it.

In this article, we’ll look at how we should organize our JavaScript code.

Statements That Must Be in a Specific Order

We should organize code that must be run in a specific order so that the dependencies are obvious.

For instance, we can write the code that needs to be run first by writing something like:

const subtotal = calcSubtotal();
const taxes = calcTaxes(subtotal);
const total = subtotal + taxes;

With the code above, we know that we need to calculate the subtotal before we can use that to calculate the taxes.

Then we need both to calculate the total.

Also, the parameter for calcTaxes is subtotal so that we know that we know subtotal is a dependency for calcTaxes .

Document Unclear Dependencies with Comments

If dependencies aren’t clear, then we need to clarify them with comments.

For instance, if we didn’t have the parameter for calcTaxes , then we may have to explain that in the comments.

We may write:

/*
 1. calculate subtotal
  2. calculate taxes
  3. calculate total
 */
const subtotal = calcSubtotal();
const taxes = calcTaxes();
const total = subtotal + taxes;

Check for Dependencies with Assertions or Error-Handling Code

If our sequence of code have dependencies, then we want to check for them before we move on to the next step.

For instance, we may want to write assertions or error handling code to check if the required values are available before proceeding.

We may write something like:

const length = calcLength();
const width = calcWidth();
if (length >= 0 && width >= 0) {
  let area = length * width;
}

We check that length and width are 0 or bigger before we calculate the area by multiplying length and width .

If we’re writing a Node app, we may also use the assert module to check the conditions that we want to check instead.

Making Code Read from Top to Bottom

If we have code where the order does matter, then we can make the code read from the top and bottom.

This way, we can read the code easily without jumping up and down the page.

For instance, we may write something like:

travelData.calcQuarterlyRevenue();
salesData.calcQuarterlyRevenue();
marketingData.calcQuarterlyRevenue();

travelData.calcAnnualRevenue();
salesData.calcAnnualRevenue();
marketingData.calcAnnualRevenue();

This way, we can read them in sequence by grouping the quarterly calculations together and the annual ones together.

Grouping Related Statements

Grouping related statements are also important. Putting related statements together lets us read them together.

Reading unrelated code that overlaps with each other is hard because we’ve to jump around to read it.

Conclusion

We should organize our code in a way so that we don’t have to jump around the page to read our code.

Also, we should group related statements together so that we can read related statements together.

Assertions and error handling code should also be added so that we know what’s required to run the code that comes after the assertions.

Categories
JavaScript Best Practices

JavaScript Best Practices — Function Layout and Documentation

JavaScript is a very forgiving language. It’s easy to write code that runs but has mistakes in it.

In this article, we’ll look at the best practices for laying out JavaScript function code and documentation.

Use Blank Lines to Separate Parts of a Function

Any code that’s inside the function’s body should be grouped into related paragraphs so that we can see them easily.

Use Standard Indentation for Function Arguments

Function argument should be indented if they overflow the first line.

For instance, we may write:

const readFile = (
  fileName,
  employeeCount
) => {
  //...
}

and call it as follows:

readFile = (
  fileName,
  employeeCount
)

This is easier to read than having everything in the same line.

Laying Out Classes

We should put the constructor first in the class. Then we add methods.

For instance, we write:

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

  greet() {
    //...
  }
}

We have the instance method greet below the constructor.

If we have More than One Class in a File, Identify Each Class Clearly

We should be easily identify classes that are in the same file.

For instance, we write:

class Animal {
  //...
}

class Person {
  //...
}

to write 2 classes. We make them clear that they’re classes with the class keyword and PascalCase names for each class.

Put One Class in One File

Putting one class per file is a good idea.

We may want to do that to make finding them easier.

Give File a Name Related to the Class Name

If we have one class per file, then the class name should be related to the file name.

This way, we can find the class by their file name easily.

Separate Functions Within a File Clearly

Having blank lines between functions let us read them easily.

For instance, we can write the following:

const max = () => {
  //...
}

const min = () => {
  //...
}

This way, we can see our function code easily.

Sequence Functions Alphabetically

We can separate functions alphabetically so that we can look for them easily with our eyes.

So we can write:

const bar = () => {
  //...
}

const foo = () => {
  //...
}

Self Documenting Code

Having self-documenting code is important. We want our code to mostly explain themselves so that everyone else can understand it when they read them.

External Documentation

Even though the code is self-documenting, external documentation is still important.

They’re for high-level decisions mostly, between business requirements documents and the code itself.

Unit development Folders

Unit development folders is an informal document that has notes by developers that are written during development.

It includes justifications for decisions and top-level design standards, and related knowledge that aren’t covered in code.

Detailed-Design Document

This is a low-level design document that let us document class and function level design decisions.

It documents the cases that we considered and alternatives that were skipped.

Programming Style as Documentation

The internal documentation is done with a clear code.

Code-level documentation is done with a good programming style.

Even if a piece of code doesn’t have comments, we should still be able to understand it.

So the name should be descriptive, spacing should be good and consistent, and code groups should be small.

To Comment or Not to Comment

It’s easy to write comments poorly. And bad comments are more damaging than helpful.

Therefore, we shouldn’t write too many of them.

Keys to Effective Comments

Wrong comments should be removed. They’re misleading and may lead to developers making wrong decisions.

If they’re just a repeat of the code, then they should definitely not be written.

If there’re any tricky parts of the code that needs explanation, then we may need comments to explain them.

Markers shouldn’t be left in the code. If we use markers to mark defective code that should be fixed, then we should just fix the code.

Conclusion

We should aim to write self-documenting code.

To do that, we have good spacing and names.

Code groups should be short and clear so that they’re easy to read.

Blank lines and indentation are important for readability.

Categories
JavaScript Best Practices

JavaScript Best Practices — Arrays and Global Variables

JavaScript is a very forgiving language. It’s easy to write code that runs but has issues in it.

In this article, we’ll look at how we should work with arrays and global variables in JavaScript.

Make Sure that All Array Indexes are Within the Bounds of the Array

We should make sure that we don’t access array indexes that are out of bounds.

Otherwise, we get undefined as the returned value.

Consider Using Objects Instead of Arrays

Arrays are meant to be accessed sequentially, so if we don’t need that, we may want to use an object instead.

This way, we won’t have to worry about indexes and just access things the way we want.

JavaScript also has maps for key-value pairs and sets for containers that don’t hold duplicate values.

Check the End Points of Arrays

We should check the endpoints of arrays to catch errors that may occur there.

Off by one error isn’t good, so we should be checking for those.

If an Array is Multidimensional, Make Sure its Subscripts are used in the Correct Order

arr[i][j] and arr[j][i] are completely different. So we should make sure that the index is in the right order.

Watch Out for Index Cross-Talk

If we have nested loops, it’s easy to confuse arr[j] with arr[i] , so we should make sure that our code don’t have typos like that or we’ll get unexpected results.

Inadvertent Changes to Global Data

It’s easy to mess up global data since they can be accessed anywhere, so we shouldn’t use them anywhere.

Instead, we can use local variables as much as possible.

Block-scoped variables are even better.

Code Reuse Hindered by Global Data

If we want to reuse code that has global data, then we got to make sure that the global data aren’t affected by the reuse.

This means that reusing code that references global data is hard.

This is another reason that we should have global data in our apps.

Reasons to Use Global Data

It’s rare that we have to have values that must be global, but they may exist.

Things like constants for the mode of our app may be a constant.

Global variables may also be used for simulating enum types if they don’t exist, which is the case in JavaScript.

If we have some values that are related and we need to access them everywhere, then we may want to make one or more global variables out of them.

Also, if we have data that are used everywhere, we may also want to define them as global data.

Use Global Data Only as a Last Resort

Global data should only be used as a last resort.

If something can’t be local at all, then they may have to be global.

However, that shouldn’t be the case in most cases with JavaScript modules.

Access Function

An access function allows us to access global variables in a controlled manner.

We may want to create functions for getter and setting global variables.

Also, we may want to have a locking mechanism for accessing global variables so that we won’t have issues with multiple pieces of code accessing the same global variable.

Reduce the Risks of Using Global Variables

If we ever declare global variables, we should make their name obvious.

For instance, all global variables may start with g .

We should also create a list of all global variables so that everyone knows that they’re global.

They also shouldn’t contain intermediate results.

And we definitely shouldn’t put everything in one big global object and pass them everywhere.

That’s just a recipe for disaster since they can be changed by anything in our program.

Conclusion

We should avoid global variables as much as we can. They just aren’t good for much and they may cause lots of unexpected results.

If we want to use global variables, then we’ve to make sure that they’re accessed in an orderly manner.

If we’re using arrays, then we should watch out for off-by-one errors.

Also, we don’t have to use an array if we don’t need to access the data sequentially. We can use other things like sets and maps.

Categories
JavaScript Best Practices

JavaScript Best Practices — Formatting Lines

JavaScript is a very forgiving language. It’s easy to write code that runs but has mistakes in it.

In this article, we’ll look at the best practices for layout code with blocks and lines.

Make the Incompleteness of a Statement Obvious

If statements have to be broken across lines, then we should make that obvious.

For instance, we write:

str.incluees('a') &&
str.incluees('z') &&
str.incluees(0) &&
str.incluees(9)

Now we know that the expression continues to the next line since we have && at the of the line.

Keep Closely Related Elements Together

Related elements should be kept together to let us follow the code more easily.

For instance, instead of writing:

const name = person['firstName'] + ' ' + person[
  'lastName'
]

we write:

const name = person['firstName'] + ' ' +
  person['lastName']

so that we can have the object property access code in the same line.

Indent Function-Call Continuation Lines the Standard Amount

If we’re calling a function, we should indent all long expressions by the same amount.

2 spaces are also pretty standard for indenting argument expressions, so we can write:

fn(
  'foo',
  'bar'
)

Make it Easy to Find the End of a Continuation Line

Having each argument on their own line is also a good idea to make the arguments more readable.

So we may want to put them in their own line, especially if they’re long.

Indent Control-Statement Continuation Lines the Standard Amount

Conditionals and loops should also be indented the same amount.

For instance, we should write:

while (!done) {
  //...
  doSomething();
}

for loops. We have 2 spaces to indent the body.

For conditional statements, we write:

if (!done) {
  //...
  doSomething();
}

Which has the same indentation as the loops.

Do not Align Right Sides of Assignment Statements

We shouldn’t align the right sides of the assignment statements.

For instance, we shouldn’t write:

bill      = bill + purchases;
totalBill = bill + previousBalance( customerID ) +
     lateCharge( customerID );

It just takes extra effort and doesn’t improve readability that much.

We should just let our code formatter decide on the alignment, so we write:

bill = bill + purchases;
totalBill = bill + previousBalance(customerID) +
  lateCharge(customerID);

Using Only One Statement Per Line

Only one statement per line makes sense for readability. Shorter lines are more readable.

So instead of writing:

let i = 0, j = 0, k = 0; destroy(i, j, k);

We write:

let i = 0,
  j = 0,
  k = 0;
destroy(i, j, k);

In addition to better readability, it also provides a more accurate view of our program’s complexity.

Putting several statements in one line also doesn’t provide optimization clues to compilers.

We can also follow the left margin of the code to following it line by line

Syntax errors are also easier to find if everything is on their own line.

Individual statements can also be edited or deleted more easily if they’re on their own line.

Use Only One Data Declaration Per Line

We should declare variables and constants on their own line.

For instance, we can write the following:

let i = 0;
let j = 0;
const k = 0;

This makes each declaration clear. We can also see what kind of data they are.

Declare Variables Close to Where They’re First Used

Variables should be declared close to where they’re first used.

It’s better to declare close to where they’re first used to avoid accidental assignments and group related code together.

It’s also easier to follow how variables are used if they’re only used in a few lines apart.

Order Declarations Sensibly

Grouping declarations by type makes sense since they’re grouped logically.

It’s easier to read logically related things.

Indent a Comment with its Corresponding Code

If we have comments, they should be indented the same way as code.

For instance, if we have a loop, we write:

while (!done) {
  // comment
  doSomething();
}

Conclusion

We should only have one statement per line to make them easier to read.

Also, we shouldn’t align the right side of assignment statements since it’s just extra effort for not much reward.

Indentation should be consistent with code and comments.