Here 15 Ways to Write Self-documenting JavaScript

View: 296    Dowload: 0   Comment: 0   Post by: hanhga  
Author: none   Category: Javascript   Fields: Other

0 point/0 review File has been tested

But writing code with zero comments isn’t an option. In my more than 15 years of programming experience, I’ve never seen a codebase where comments were completely unnecessary.

Introduction

But writing code with zero comments isn’t an option. In my more than 15 years of programming experience, I’ve never seen a codebase where comments were completely unnecessary.

However, there are ways to reduce the need for comments. We can make use of certain coding techniques to clarify our code, simply by using the programming language’s features to our advantage.

Not only does this help make our code easier to understand, it can also help improve the design of the program overall!

This type of code is often called self documenting. Let me show you how you can take this approach to coding right now. While the examples I’ll present here are in JavaScript, you can apply most of the techniques in other languages as well.

Overview of Techniques

Some programmers include comments as part of self-documenting code. In this article, we’ll only focus on code. Comments are important, but they’re a large topic to be covered separately.

We can split the techniques for self-documenting code into three broad categories:

structural, where the structure of code or directories is used to clarify the purpose

naming related, such as function or variable naming

syntax related, where we make use of (or avoid using) features of the language to clarify code.

Many of these are simple on paper. The challenge comes from knowing when to use what technique. I’ll show you some practical examples as we tackle each one.

Structural

First, let’s look at the structural category. Structural changes refer to shifting code around for enhanced clarity.

Move code into a function

This is the same as the “extract function” refactoring — meaning that we take existing code and move it into a new function: we “extract” the code out into a new function.

For example, try to guess what the following line does:

var width = (value - 0.5) * 16;

Not very clear; a comment here could be quite useful. Or, we could extract a function to make it self documenting:

var width = emToPixels(value);

function emToPixels(ems) {
    return (ems - 0.5) * 16;
}

The only change was I moved the calculation into a function. The function’s name is descriptive of what it does, so the code no longer needs clarification. As an additional benefit, we now have a useful helper function that you can use elsewhere, so this method also helps reduce duplication.

Replace conditional expression with function

If clauses with multiple operands can often be hard to understand without a comment. We can apply a similar method as above to clarify them:

if(!el.offsetWidth || !el.offsetHeight) {
}

What is the purpose of the above condition?

function isVisible(el) {
    return el.offsetWidth && el.offsetHeight;
}

if(!isVisible(el)) {
}

Again, we moved the code into a function and the code is immediately much easier to understand.

Replace expression with variable

Replacing something with a variable is similar to moving code into a function, but instead of a function, we simply use a variable.

Let’s take a look at the example with if clauses again:

if(!el.offsetWidth || !el.offsetHeight) {
}

Instead of extracting a function, we can also clarify this by introducing a variable:

var isVisible = el.offsetWidth && el.offsetHeight;
if(!isVisible) {
}

This can be a better choice than extracting a function — for example, when the logic you want to clarify is very specific to a certain algorithm used only in one place.

The most common use for this method is mathematical expressions:

return a * b + (c / d);

We can clarify the above by splitting the calculation:

var multiplier = a * b;
var divisor = c / d;
return multiplier + divisor;

Because I’m terrible at math, imagine the above example has some meaningful algorithm. In any case, the point is that you can move complex expressions into variables that add meaning to otherwise hard-to-understand code.

Class and module interfaces

The interface — that is, the public methods and properties — of a class or module can act as documentation on its usage.

Let’s look at an example:

class Box {
    setState(state) {
        this.state = state;
    }

    getState() {
        return this.state;
    }
}

This class could contain some other code in it as well. I purposely kept the example simple, to illustrate how the public interface is documentation

Can you tell how this class should be used? Maybe with a little bit of work, but it isn’t very obvious.

Both of the functions have reasonable names: what they do is clear from their name. But despite this, it’s not very clear how you should be using them. Most likely you would need to read more code or the documentation for the class to figure it out.

What if we changed it to something like this:

class Box {
    open() {
        this.state = 'open';
    }

    close() {
        this.state = 'closed';
    }

    isOpen() {
        return this.state === 'open';
    }
}

Much easier to see the usage, don’t you think? Notice that we only changed the public interface; the internal representation is still the same with the this.state property.

Now you can tell at a glance how the Box class is used. This shows that even though the first version had good names in the functions, the complete package was still confusing, and how, with simple decisions like this, you can have a very big impact. You always have to think of the big picture.

Code grouping

Grouping different parts of code can also act as a form of documentation.

For example, you should always aim to declare your variables as close to where they are being used as possible, and try to group variable uses together.

This can be used to indicate a relationship between the different parts of the code, so that anyone changing it in the future has an easier time finding which parts they may also need to touch.

Consider the following example:

var foo = 1;

blah()
xyz();

bar(foo);
baz(1337);
quux(foo);

Can you see at a glance how many times foo was used? Compare it to this:

var foo = 1;
bar(foo);
quux(foo);

blah()
xyz();

baz(1337);

With all the uses of foo grouped together, we can easily see which parts of the code depend on it.

Use pure functions

Pure functions are much easier to understand than functions that rely on state.

What is a pure function? When calling a function with the same parameters, if it always produces the same output, it’s most likely a so-called “pure” function. This means the function should not have any side effects or rely on state — such as time, object properties, Ajax, etc.

These types of functions are easier to understand, as any values affecting their output are passed in explicitly. You won’t have to dig around to figure out where something comes from, or what affects the result, as it’s all in plain sight.

Another reason these types of functions make for more self-documenting code is you can trust their output. No matter what, the function will always return output only based on what parameters you give it. It also won’t affect anything external, so you can trust it won’t cause an unexpected side effect.

A good example of where this goes wrong is document.write(). Experienced JS developers know you shouldn’t use it, but many beginners stumble with it. Sometimes it works well — but other times, in certain circumstances, it can wipe the whole page clean. Talk about a side effect!

For a better overview of what a pure function is, see the article Functional Programming: Pure Functions.

Directory and file structure

When naming files or directories, follow the same naming convention as used in the project. If there’s no clear convention in the project, follow the standard for your language of choice.

For example, if you’re adding new UI-related code, find where similar functionality is in the project. If UI-related code is placed in src/ui/, you should do the same.

This makes it easier to find the code and shows its purpose, based on what you already know about the other pieces of code in the project. All UI code is in the same place, after all, so it must be UI related.

Rename function

Function naming is often not too difficult, but there’s some simple rules that you can follow:

  • Avoid using vague words like “handle” or “manage”: handleLinks()manageObjects(). What do either of these do?
  • Use active verbs: cutGrass()sendFile() — functions that actively perform something.
  • Indicate return value: getMagicBullet()readFile(). This is not something you can always do, but it’s helpful where it makes sense.
  • Languages with strong typing can use type signatures to help indicate return values as well.

Rename variable

With variables, here are two good rules of thumb:

  • Indicate units: if you have numeric parameters, you can include the expected unit. For example,widthPx instead of width to indicate the value is in pixels instead of some other unit.
  • Don’t use shortcuts: a or b are not acceptable names, except for counters in loops.

Follow established naming conventions

Try to follow the same naming conventions in your code. For example, if you have an object of a specific type, call it the same name:

var element = getElement();

Don’t suddenly decide to call it a node:

var node = getElement();

If you follow the same conventions as elsewhere in the codebase, anyone reading it can make safe assumptions about the meanings of things based on what it means elsewhere.

Use meaningful errors

Undefined is not an object!

Everyone’s favorite. Let’s not follow JavaScript’s example, and let’s make sure any errors our code throws have a meaningful message in them.

What makes an error message meaningful?

  • it should describe what the problem was
  • if possible, it should include any variable values or other data which caused the error
  • key point: the error should help us find out what went wrong — therefore acting as documentation on how the function should work.

Syntax

Syntax-related methods for self-documenting code can be a little bit more language specific. For example, Ruby and Perl allow you to do all kinds of strange syntax tricks, which, in general, should be avoided.

Let’s take a look at a few that happen with JavaScript.

Don’t use syntax tricks

Don’t use strange tricks. Here’s a good way to confuse people:

imTricky && doMagic();

It’s equivalent to this much more sane looking code:

if(imTricky) {
    doMagic();
}

Always prefer the latter form. Syntax tricks are not going to do anyone any favors.

Use named constants, avoid magic values

If you have special values in your code — such as numbers or string values — consider using a constant instead. Even if it seems clear now, more often than not, when coming back to it in a month or two, nobody will have any idea why that particular number was put there.

const MEANING_OF_LIFE = 42;

(If you’re not using ES6, you can use a var and it’ll work equally well.)

Avoid boolean flags

Boolean flags can make for hard-to-understand code. Consider this:

myThing.setData({ x: 1 }, true);

What is the meaning of true? You have absolutely no idea, unless you dig into the source forsetData() and find out.

Instead, you can add another function, or rename an existing function:

myThing.mergeData({ x: 1 });

Now you can immediately tell what’s going on.

Use language features to your advantage

We can even use some features of our chosen language to better communicate the intention behind some code.

A good example of this in JavaScript are the array iteration methods:

var ids = [];
for(var i = 0; i < things.length; i++) {
  ids.push(things[i].id);
}

The above code collects a list of IDs into a new array. However, in order to know that, we need to read the whole body of the loop. Compare it with using map():

var ids = things.map(function(thing) {
  return thing.id;
});

In this case, we immediately know that this produces a new array of something, because that’s the purpose of map(). This can be beneficial especially if you have more complicated looping logic. There’s a list of other iteration functions on MDN.

Another example with JavaScript is the const keyword.

Often, you declare variables where the value is supposed to never change. A very common example is when loading modules with CommonJS:

var async = require('async');

We can make the intention of never changing this even more clear:

const async = require('async');

As an added benefit, if someone ever accidentally tries to change this, we’ll now get an error.

Anti-patterns

With all these methods at your disposal, you can do a lot of good. However, there are some things you should be careful about …

Extracting for the sake of having short functions

Some people advocate the use of tiny tiny functions, and if you extract everything out, that’s what you can get. However, this can detrimentally affect how easy the code is to understand.

For example, imagine you’re debugging some code. You look in function a(). Then, you find it uses b(), which then uses c(). And so on.

While short functions can be great and easy to understand, if you’re only using the function in a single place, consider using the “replace expression with variable” method instead.

Here 15 Ways to Write Self-documenting JavaScript

Here 15 Ways to Write Self-documenting JavaScript Posted on 08-07-2016  But writing code with zero comments isn’t an option. In my more than 15 years of programming experience, I’ve never seen a codebase where comments were completely unnecessary. 5/10 296

Comment:

To comment you must be logged in members.

Files with category

  • JUnit 5 State Of The Union using java

    View: 633    Download: 0   Comment: 0   Author: none  

    JUnit 5 State Of The Union using java

    Category: Javascript
    Fields: Other

    1.5/3 review
    JUnit 5 has been under development for about 14 months now and the prototype is almost a year old. Time to summarize what happened so far, where the project stands, and where it’s going.

  • Getting Started with Dropwizard using java

    View: 736    Download: 0   Comment: 0   Author: none  

    Getting Started with Dropwizard using java

    Category: Javascript
    Fields: Other

    1.5/3 review
    Dropwizard is a framework for building RESTful web services in Java. In this tutorial we’re going to have a look at how to get started with developing a Dropwizard application by building a new service from scratch.

  • Build Query NULL Value in MySql

    View: 340    Download: 0   Comment: 0   Author: none  

    Build Query NULL Value in MySql

    Category: Javascript
    Fields: Other

    2.5/2 review
    Misunderstanding NULL is common mistake beginners do while writing MySql query. While quering in MySql they compare column name with NULL. In MySql NULL is nothing or in simple word it isUnknown Value so if you use comparison operator for NULL values...

  • Manage Your JavaScript Application State with MobX

    View: 406    Download: 0   Comment: 0   Author: none  

    Manage Your JavaScript Application State with MobX

    Category: Javascript
    Fields: Other

    2.25/2 review
    This article was peer reviewed by Michel Weststrate and Aaron Boyer. Thanks to all of SitePoint’s peer reviewers for making SitePoint content the best it can be!

  • Build Bringing Pages to Life with the Web Animations API

    View: 364    Download: 0   Comment: 0   Author: none  

    Build Bringing Pages to Life with the Web Animations API

    Category: Javascript
    Fields: Other

    3/3 review
    This article is by guest author Dudley Storey. SitePoint guest posts aim to bring you engaging content from prominent writers and speakers of the JavaScript community.

  • How to Style Google Custom Search Manually

    View: 346    Download: 0   Comment: 0   Author: none  

    How to Style Google Custom Search Manually

    Category: Javascript
    Fields: Other

    0/0 review
    Website owners very often decide on using Google’s Custom Search Engine (GCSE) for searching through their content instead of using built-in and/or custom search functionality. The reason is simple – it’s much less work, and most often it does the...

  • Test React Components Using Jest

    View: 5116    Download: 0   Comment: 0   Author: none  

    Test React Components Using Jest

    Category: Javascript
    Fields: Other

    4.5/1 review
    This article is by guest author Jack Franklin. SitePoint guest posts aim to bring you engaging content from prominent writers and speakers of the JavaScript community.

  • Programming Question Reverse String without using String function

    View: 821    Download: 0   Comment: 0   Author: none  

    Programming Question Reverse String without using String function

    Category: Javascript
    Fields: Other

    4.5/1 review
    Write a program to reverse string without using string function. You don’t have to use any in-built string library function. This problem can be solved by multiple approaches. Let’s check it.

 

File suggestion for you

File top downloads

logo codetitle
Codetitle.com - library source code to share, download the file to the community
Copyright © 2015. All rights reserved. codetitle.com Develope by Vinagon .Ltd