Categories
JavaScript Best Practices

JavaScript Best Practices — Function Length and Parameters

Cleaning up our JavaScript code is easy with default parameters and property shorthands.

In this article, we’ll look at the best practices when designing functions, including the ideal length and the number of parameters it should take.

Use Opposites Precisely

If 2 functions do opposite things, then they should be named precisely

For instance, if we have 2 functions to increment and decrement and number respectively, then they should be named as such.

They should be named increment and decrement to describe what they do.

How Long Can a Function Be?

Function length are inversely correlated to the number of errors per line of code according to Basili and Perricone study.

Another study from Shen et. al. mentioned that function size isn’t correlated with errors per line.

But structural complexity and amount of data were correlated with errors.

We should just let functions grow into their size organically. And we should only put operations together if they must be put together.

However, if a function is longer than 200 lines, then we should think we can break them up into smaller functions.

This is because if it’s longer than 200 lines, then a function would be harder to understand for most people.

Function Parameters

When we’re adding parameters into a function, we should take into account some guidelines so that we make them easier to understand and avoid mistakes.

If Several Function Use Similar Parameters, Put the Similar Parameters in a Consistent Order

If we have multiple functions that have similar parameters, then we should put them in the same order in each function.

For instance, instead of writing:

const calcVolume = (length, width, height) => {
  //...
}

const calcArea = (width, length) => {
  //...
}

We should write:

const calcVolume = (length, width, height) => {
  //...
}

const calcArea = (length, width) => {
  //...
}

This way, we won’t be confused about the order of the parameters when we pass them in.

Use All the Parameters

We should use all parameters that are in the function signature. If it isn’t used often, then we should take them out.

Unused parameters cause more errors since there’s more to think about.

Put Status or Error Variables Last

If we have status or error variables, then we should put them last since they’re output only.

For instance, we write:

const callback = (res, err) => {
  //...
}

err is output only, so it should go last.

Don’t Use Function Parameters as Working Variables

We shouldn’t mutate parameters. This way, we won’t be accidentally modifying the value outside if it’s passed by reference.

For instance, we shouldn’t have code like:

const fn = (input) => {
  input++;
  //...
}

Instead, we write:

const fn = (input) => {
  let count = input;
  count++;
  //...
}

Always assign it to a variable and then apply operations to that instead.

Limit the Number of a Function’s Parameters to About 7

The fewer parameters we have in our code the better.

It’s easier to read and harder for us to make mistakes passing them in.

If we have a dozen parameters, then anyone would get confused with the order of the parameters and the data type of each.

This is worse since JavaScript doesn’t provide any data type checking built-in at compile time.

Use Named Parameters

We can mimic named parameters by using objects as parameters and the destructuring syntax.

For instance, we can write:

const calcArea = ({
  length,
  width
}) => {
  return length * width;
}

calcArea({
  length: 1,
  width: 2
});

Then we don’t have to worry about the order that length and width are passed in and we can see what we passed in for each parameter.

Conclusion

There’re a few things to consider when we’re defining functions.

The lengthy matters since we don’t want functions that are so long that they’re hard to understand.

Also, we want to reduce the number of parameters in our function to reduce the chance of mistakes.

We also want to destructure object parameters to mimic named parameters so that we can see the name of the property we pass in.

Categories
JavaScript Best Practices

JavaScript Best Practices- Bad Variable Declarations and Better Node Code

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 how to declare variables the right way and writing better Node apps by cleaning up require calls and handling errors.

Don’t Use Restricted Names as Identifiers

We shouldn’t use restricted names like undefined , NaN , or Infinity as identifiers for variable names, functions, etc.

It confuses the user by thinking that we’re actually doing the assignment to those values when that’s not actually being done.

For instance, if we have:

var NaN = "bar";

Then that’s deceptive since most people would assume that 'bar' is set as the value of undefined .

However, when we log the value of undefined , we still get undefined .

JavaScript’s strict mode would prevent something like the code above from running.

Also, we’ll also get errors if we declare the undefined variable with let or const .

Do Not Use undefined As a Variable

Theoretically, since the JavaScript undefined value is a global variable, we may be able to overwrite it with some other value.

However, we can write something like the following:

var undefined = "bar";

and not get errors if strict mode if off. No assignment was actually done, but the code runs.

Therefore, we shouldn’t use undefined as a variable name in any situation since it doesn’t do the assignment as we expected it to. If it does, then it would be scarier since we expect undefined to be undefined .

No Unused Variables

Unused variables are dead and useless code. Since they aren’t being used anywhere, they should be removed from our codebase.

Declarations like:

let x;

that isn’t referenced anywhere else should be removed.

If we declare a variable, we should either use it or remove it.

Don’t Use Variables Before it’s Defined

If we declare a variable with var , then we can use it before it’s declared because the variable declaration itself is hoisted.

For instance, we can use it as follows if we have a variable declared with var:

console.log(foo);
var foo = 1;

In the code above, we would see that foo is undefined from the console log output since the variable was hoisted, but the value assignment is still done in its original position.

This is very confusing for lots of people, so we shouldn’t use variables before they’re declared.

Better yet, we should use let and const to declare variables and constants respectively so that we don’t have about issues like this.

let and const variables and constants are block-scoped so that their scope stays inside the block.

Also, they aren’t hoisted so they can’t be referenced before they’re declared. Therefore, we’ll get an error if we try to reference it before it’s declared.

Put require() On the Top of a Module File

require should be added to the top of a module file. It’s cleaner and we get all the imported modules members all in one place.

This way, we don’t have to worry about using module members that haven’t been imported yet since if we see them all at the top, then we know that they’re imported right away.

Therefore, the following code:

const fs = require("fs");

const readFile = (fileName) => {
  const file = fs.readFileSync(fileName);
  return file;
}

readFile('foo.txt');

is better than:

const readFile = (fileName) => {
  const fs = require("fs");
  const file = fs.readFileSync(fileName);
  return file;
}

readFile('foo.txt');

Even though both are valid imports. It’s just that the first example is cleaner as we put all the require calls in one place.

Do Callback Error Handling

If a callback function has the err parameter. Then we should probably do something to check if anything is set as the value for the err parameter before proceeding.

We can handle this by writing the following:

const fs = require("fs");

const readFile = (fileName) => {
  fs.readFile(fileName, (err, data) => {
    if (err) {
      throw err;
    }
    console.log(data);
  });
}

readFile('foo.txt');

The callback we have above, we wrote:

if (err) {
  throw err;
}

to throw the err object if an error is encountered. Then we can handle it somewhere else.

Conclusion

Restricted names like undefined or NaN shouldn’t be used as identifiers for anything like variables or functions.

In Node apps, require should be on the top of the file to make the require calls easier to read since they aren’t scattered everywhere.

Finally, if we have errors in our callbacks, we should handle them.

Categories
JavaScript Best Practices

JavaScript Best Practices — Arrow Functions

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 how to define and use arrow functions in the cleanest way possible.

If an Expression Spans Multiple Lines, Then Wrap it in Parentheses to Make it More Readable

If we have an arrow function that has a long JavaScript expression that spans multiple lines, then we should wrap the expression in parentheses.

This applies to arrow functions that have no curly braces. For instance, if our arrow function returns an object, then we should write the following:

const foo = () => ({  
  a: 1  
})

In the code above, we wrapped our object expression in parentheses so that we can return the object when we call the foo function.

Wrapping the object in parentheses lets us return it instead of treating it as curly braces for the function body.

Therefore, we should wrap expressions in curly braces.

Always Include Parentheses Around Parameters for Clarity and Consistency

Arrow function signatures may skip the parentheses if the signature only has one parameter. Otherwise, we must include the parentheses.

However, even though we can skip the parentheses in the signature, we probably want to include them to make our function signature more clear and to keep the code consistent with other function definitions.

For instance, we write the following code to include the parentheses in the function signature:

const foo = (a) => a + 1

Avoid Confusing Arrow Function Syntax (=>) With Comparison Operators (<=, >=)

The fat arrow in an arrow function looks like the comparison operator since they’re both made of an equal sign and the greater or less than sign.

To make arrow functions easier to distinguish from comparison expressions, we should put parentheses around our expressions.

For instance, we can write the following code for an arrow function:

const foo = (a) => (a <= 1);

We wrapped our function body and signature with parentheses so that we know that we have an arrow function.

From the parentheses, we can also clearly see that the comparison expression is a <= 1 . If we skip the parentheses, then we’ll have a hard time distinguishing between the function code and the comparison expressions.

So if we have something like the following:

const foo = a => a <= 1;

Then it’s very hard to tell where the function arrow is and where the comparison arrow is.

For longer functions, we should also have curly braces to delimit the function body as follows:

const foo = (a) => {  
  return a <= 1;  
}

In the code above, we wrapped our function body around curly braces to make everyone clear that it’s the function body.

Enforce the Location of Arrow Function Bodies With Implicit Returns

With implicit returns of an arrow function, we have to keep the position of the expression that we’re returning is consistent. It should start in the first line of the arrow function.

However, the remaining expression can be in lines below it. For instance, we can write functions like the following code:

const foo = (a) => a + 1;  
const bar = (a) => (a + 1);  
const baz = (a) => (  
  a + 1  
)

In the code above, we have the implicit return expression in the first line. We can put it in the first line in several ways.

If we wrap the expression we return in parentheses, then we can move our expression to the second line as we have in the baz function.

However, the most important thing is to keep the start of the expression we return in the first line, which includes parentheses if added.

Conclusion

With arrow functions, we have to be careful about implicit returns. The expression we return must start from the first line.

If the expression we return spans multiple lines, then it must be wrapped in parentheses.

Also, to avoid confusion with comparison operators like greater than or less than, we should wrap comparison expressions in parentheses or if we have multiline arrow functions, we wrap the whole body with curly braces.

Categories
Vue 3

Vue 3 — Transition Between Components and Lists

Vue 3 is in beta and it’s subject to change.

Vue 3 is the up and coming version of Vue front end framework.

It builds on the popularity and ease of use of Vue 2.

In this article, we’ll look at creating transition effects between components and lists.

Transitioning Between Components

We can transition between components with the transition and component components.

The component component is used for switching between components dynamically by setting their name.

For instance, we can use it by writing:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue@next"></script>
    <style>
      .bounce-enter-active {
        animation: bounce-in 1.3s;
      }
      .bounce-leave-active {
        animation: bounce-in 1.3s reverse;
      }
      @keyframes bounce-in {
        0% {
          transform: scale(0);
        }
        50% {
          transform: scale(1.8);
        }
        100% {
          transform: scale(1);
        }
      }
    </style>
  </head>
  <body>
    <div id="app">
      <button @click="currentComponent = 'foo'">foo</button>
      <button @click="currentComponent = 'bar'">bar</button>
      <button @click="currentComponent = 'baz'">baz</button>
      <transition name="bounce" mode="out-in">
        <component :is="currentComponent"></component>
      </transition>
    </div>
    <script>
      const app = Vue.createApp({
        data() {
          return {
            currentComponent: "foo"
          };
        },
        components: {
          foo: {
            template: "<div>foo</div>"
          },
          bar: {
            template: "<div>bar</div>"
          },
          baz: {
            template: "<div>baz</div>"
          }
        }
      });
      app.mount("#app");
    </script>
  </body>
</html>

We created 3 components, foo , bar and baz .

And we to transition between them, we created 3 buttons to change the component names.

We also have the name prop and to set transition name.

And we also have the transition styles in the style tag.

When we click the buttons, we’ll see a transition effect before we see the content of the new component.

List Transitions

We can add transition effects to lists.

To do this, we can use the transition-group component.

Unlike transition , it renders the actual element.

A span is rendered by default.

We can change this with the tag attribute.

Transition modes aren’t available since we aren’t alternating between mutually exclusive elements.

Elements inside are always required to have a unique key attribute.

CSS transitions classes will be applied to inner elements and not to the container itself.

List Entering/Leaving Transitions

We can add a list enter or leave transitions with the transition-group component.

For instance, we can write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue@next"></script>
    <style>
      .list-enter-active,
      .list-leave-active {
        transition: all 1s ease;
      }
      .list-enter-from,
      .list-leave-to {
        opacity: 0;
        transform: translateY(35px);
      }
    </style>
  </head>
  <body>
    <div id="app">
      <button @click="add">Add</button>
      <button @click="remove">Remove</button>
      <transition-group name="list" tag="div">
        <p v-for="item in items" :key="item">
          {{ item }}
        </p>
      </transition-group>
    </div>
    <script>
      const app = Vue.createApp({
        data() {
          return {
            items: Array(10)
              .fill()
              .map(() => Math.random()),
            nextNum: 10
          };
        },
        methods: {
          randomIndex() {
            return Math.floor(Math.random() * this.items.length);
          },
          add() {
            this.items.splice(this.randomIndex(), 0, Math.random());
          },
          remove() {
            this.items.splice(this.randomIndex(), 1);
          }
        }
      });
      app.mount("#app");
    </script>
  </body>
</html>

We created a list from an array of random numbers.

And we added the add and remove buttons to let us add and remove items.

The transition effects are in the style tags.

The effects we added is the opacity change and vertical translation effects.

In the template, we have the transition-group component with the name prop set to list to make that the prefix of the transition class names.

tag is the tag we render for the container.

We added the key prop as required in the p element, which is rendered from the items list.

This way, Vue can tell where each item is and animate them correctly.

Finally, we have the add and remove methods to let us add and remove items from the items array.

randomIndex generates a random index to add or remove items.

Now when we click add or remove, we’ll see the transition effects applied.

Conclusion

We can transition between components and add transition effects to list items.

Categories
Vue 3

Vue 3 — Transitions

Vue 3 is the up and coming version of Vue front end framework.

It builds on the popularity and ease of use of Vue 2.

In this article, we’ll look at parts of a transition.

Timing

UI transitions have the timing to let us set the duration of the animation.

We may have different timing for transitions between different states.

If a transition has no intermediate state, then the timing is between 0.1s and 0.4s.

Easing

The easing lets us add some depth to our animation.

Without easing, the animation would be linear and uninteresting.

We want to use ease-out for entrances and and ease-in for exits.

Enter & Leave Transitions

We can use the transition wrapper component to add our enter and leave transitions.

For instance, we can add a simple transition with the transition component by writing:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue@next"></script>
    <style>
      .fade-enter-active,
      .fade-leave-active {
        transition: opacity 1s ease;
      }

      .fade-enter-from,
      .fade-leave-to {
        opacity: 0;
      }
    </style>
  </head>
  <body>
    <div id="app">
      <button @click="show = !show">
        Toggle
      </button>

      <transition name="fade">
        <p v-if="show">hello</p>
      </transition>
    </div>
    <script>
      const app = Vue.createApp({
        data() {
          return {
            show: false
          };
        }
      });
      app.mount("#app");
    </script>
  </body>
</html>

We add the transition to the p element by wrapping it with the transition component.

Then we set the name prop of it to the prefix of the classes we’ll use for styling the transition.

We set it to fade , so all the transition classes starts with fade- .

We have the fade-enter-active , fade-leave-active classes to show a fading effect.

And we have the fade-enter-from and fade-leave-to classes to make the content transparent to maker the content disappear when show is false .

Vue will detect whether the target element has CSS transitions or animations applied.

CSS transition classes will be added or removed at appropriate timings.

If no CSS transitions or animations are detected and no JavaScript hooks are provided, then ODM operations will be run on the next browser animation frame.

Transition Classes

There’re several transition classes that we can apply styles to.

v-enter-from is applied before the element is inserted and remove one frame after the element is inserted.

v-enter-active is applied before the animation is inserted and removed when the transition or animation finishes.

v-enter-to is added one frame after the element is inserted and removed when the transition or animation finishes.

v-leave-from is applied immediately when a leaving transition is triggered and removed after 1 frame.

v-leave-active is applied during the entire leaving phase.

It’s added immediately when the leave transition is triggered and removed when the transition or animation finishes.

v-leave-to is added one frame after a leaving transition is triggered and removed when the transition or animation finishes.

Conclusion

We can add transitions easily with the transition component.

Once we used that, we can add CSS style to apply the effects we want.