Frontend Quick Tips #6 To Comment or Not to Comment?

No one likes those big articles - that’s why we’re creating Quick Tips - short tips to change your developer's life from the moment you read them.
Those may be some patterns explained in JS code on real-life examples or some techniques for better code.
Problem
Your code has a lot of comments and everyone who sits down in front of the code needs to read between the lines. Some comments explain what the next line of code does, some describe data models, some are just outdated and others are just commented code, because someone forgot to remove it before putting it into a repository. As a result, the code is hard to read.
Examples
To better get what I mean here, let's take a look at examples below:
1. Explaining what the next line does:
// checking if user is logged in
if (user && user.token && user.token.length > 0) {
// fetching user comments
const userComments = commentsService.getComments(user.token, user.id);
// doing something else…
…
}
2. Describing data model:
// user state
const state = getState();
// time in millis
const relativeDate = (time) => {
…
};
const createUser = (…) => ({
id, // number
phoneNumber, // number
…
});
3. Outdated comment example:
// width in pixels
const width = '100%';
/* `createUser` from the example above */
const user = createUser(…);
/* at some point `phoneNumber` type has changed from `number` to `string` */
/* comment `// number` is no longer valid */
if (user.phoneNumber && user.phoneNumber.startsWith('+')) {
…
}
4. Inactive part of code:
// const activeUsers = allUsers.filter((user) => user.creditsCount > 0 && user.subscriptionDate > monthAgo);
const activeUsers = allUsers.filter((user) => user.isActive);
Solution
The solution is very simple: make your code more descriptive and self-explanatory. How to do that? Here are a couple of examples:
1. Introduce a variable:
const isUserLoggedIn = user && user.token && user.token.length > 0;
if (isUserLoggedIn) {
…
}
2. Introduce a function:
const isUserLoggedIn = (user) => user && user.token && user.token.length > 0;
if (isUserLoggedIn(user)) {
…
}
const fetchUserComments = (user) => {
const isUserLoggedIn = user && user.token && user.token.length > 0;
if (isUserLoggedIn) { … }
…
};
const userComments = fetchUserComments(user);
3. Introduce an object method:
if (user.isLoggedIn()) {
…
}
4. Adjust the variable/function name:
const widthInPixels = 69;If the context is pretty small - for example inside a 5-lines long function - this would be enough:
const cssPropertyWidth = '100%';
const relativeDateToNow = (timeInMillis) => {
…
};
const state = getUserState();But it is okay to be a little more descriptive:
const userState = getUserState();
5. Use a typing system:
interface User {6. Remove commented code:
id: number;
phoneNumber: string;
…
}
const createUser = (…): User => ({
…
});
const activeUsers = allUsers.filter((user) => user.isActive);
Exceptions
There are a couple of exceptions when you may, you should, or even you are forced to use comments.
1. When am I forced to use comments?
When you want to disable checking some ESLint rule, prevent Prettier from formatting a particular part of your code, or when you use comments as JSDoc. In other words, use comments when it is demanded by some external tool you use on your code base.
A couple of examples:
// eslint-disable-next-line no-alert
2alert('foo');
1// prettier-ignore 2matrix( 3 1, 0, 0, 4 0, 1, 0, 5 0, 0, 1 6)
1/**
2 * A song
3 * @typedef {Object} Song
4 * @property {string} title - The title
5 * @property {string} artist - The artist
6 * @property {number} year - The year
7 */
8/**
9 * Plays a song
10 * @param {Song} song - The {@link Song} to be played
11 */
12
13function play (song) {
14}
2. When should I use comments?
If you struggled with some weird case or some odd implementation was added to support a particular version of a browser, it is a good practice to give a note in the comment. In other cases, newcomers may accidentally remove or change the dangerous part.
Example from the Lodash library:
function addSetEntry(set, value)
{ // Don't return `set.add` because it's not chainable in IE 11.
set.add(value)
return set
}
3. When may I want to use comments?
Sometimes you want to attach a piece of code to your existing code base. Not through any package manager, not via a CDN, but by copying and pasting particular pieces of code directly into the code base. Leaving it with comments - untouched - is perfectly fine!
Remember to put in a link to the source and/or documentation 😉
A recent project I was working on comes to my mind as an example. I needed to use an implementation which has not been published on any package manager, but directly put in the documentation. This is the untouched part of the project code base:
// The ScanForAPI() function searches for an object named API_1484_11Source, section SCORM 2004 API Discovery Algorithm.
// in the window that is passed into the function. If the object is
// found a reference to the object is returned to the calling function.
// If the instance is found …
function ScanForAPI(win) {
…
}