7 recommendations for improving the reliability of JavaScript code

The author of the article, the translation of which we are publishing today, decided to share with readers seven recommendations on JavaScript. These recommendations, as the author would like to hope, will help to write more reliable programs.



1. Use factory functions


If anyone does not know, a factory function is an ordinary function (not a class or constructor) that returns objects. This simple concept allows us to take advantage of JavaScript's powerful features to create powerful and reliable applications.

It is important to know that a factory function is called without using a keyword new. If you call her with this keyword, she will stop behaving as she should.

▍ Why use factory functions?


Factory functions can be used to simplify instantiating an object without having to bind to classes or the keyword new.

The essence of factory functions is that they are considered as the most ordinary functions. This means that they can be used to construct objects, other functions, and even promises. That is, such functions can be combined and combined to create more powerful factory functions, which, in turn, can also be combined with other functions or objects to create even more advanced factory functions. Factory functions open up unlimited possibilities for the programmer.

Given the above and combining the use of factory functions with the recommended approaches for writing code, these functions can become powerful and convenient tools.

Here is a simple example of a factory function:

function createFrog(name) {
  const children = []
  
  return {
    addChild(frog) {
      children.push(frog)
    },
  }
}

const mikeTheFrog = createFrog('mike')

If you use factory functions for some time, you may come to understand that, in comparison with their competitors in the form of constructor functions, factory functions can increase the level of code reuse. As a result, the programmer has to write less code. Factory functions facilitate refactoring, as they are able to return arbitrary objects, and simplify work on the code base.

2. When writing constructor functions, add methods to their prototypes


If you have just recently begun to learn JavaScript, then working with a prototype object may seem to you something new. So, at the very beginning, it was with me.

Keep in mind that this technique is not suitable for classes. Classes, without additional effort on the part of the programmer, independently save the methods in their prototypes.

Here is an example constructor function:

function Frog(name, gender) {
  this.name = name
  this.gender = gender
}

Frog.prototype.leap = function(feet) {
  console.log(`Leaping ${feet}ft into the air`)
}

Why use a construct Frog.prototype.leapinstead of just writing a method leapto an object created by the constructor? For example, like this:

function Frog(name, gender) {
  this.name = name
  this.gender = gender
  
  this.leap = function(feet) {
    console.log(`Leaping ${feet}ft into the air`)
  }
}

The fact is that if a method is attached directly to a constructor property prototype, this means that this instance will be shared by all instances of the object created by the constructor.

In other words, if you rely on the previous example, which is used this.leap, it turns out that when creating multiple instances of the object Frog, each of them will have its own method leap. That is - several copies of this method will be created. In this case, this indicates the irrational use of system resources, since in all these objects there will be a copy of the same method that behaves the same everywhere. It is not necessary to create copies of such a method in each instance of the object.

As a result, this will lead to a decrease in program performance. But this is not difficult to avoid. It should be noted that the properties this.nameand this.gendershould be declared in this form, since they must belong to a specific object. If we draw an analogy with real frogs, the virtual representation of which is described using the constructor Frog, it turns out that frogs can have their own names, frogs have a different gender. As a result, to store unique information about frogs in each of the objects, it makes sense to declare the properties of the objects so that they would be used exactly at the level of object instances.

Here is an example of using this technique in the popular request package .

3. Add .type property to objects to be distinguished.


A property .typethat, by unofficial agreement, is often added to objects, has found extremely widespread use these days. If you are writing React applications, then you may have come across this property all the time. Especially - if you use Redux .

Using this approach shows itself very well in the development process, since it, among other things, allows you to create self-documenting code:

function createSpecies(type, name, gender) {
  if (type === 'frog') {
    return createFrog(name, gender)
  } else if (type === 'human') {
    return createHuman(name, gender)
  } else if (type == undefined) {
    throw new Error('Cannot create a species with an unknown type')
  }
}

const myNewFrog = createSpecies('frog', 'sally', 'female')

4. Use TypeScript


TypeScript has become widespread in the JavaScript community due to the fact that this language gives the programmer a powerful tool for safely working with types, and also allows you to detect errors even before they appear in the running code.

Using TypeScript allows you to find potential errors at the stage of compiling the code, even before the code is launched. If something is wrong in the code, a compilation notification will be displayed when it is compiled.

But type safety and early detection of errors is far from a complete list of reasons for using TypeScript in any situations. One of the great things about TypeScript is that it allows you to take advantage of the new JavaScript features before they even appear in major browsers. The fact is that TypeScript code is compiled into JavaScript code supported by both modern and not the latest browsers.

5. Write tests


If you are working on a project and are serious about this work, then you practically need to write tests. This will make the code more predictable, will make it less error prone. This will give a higher level of confidence in the quality of the code when making changes to it. In other words, if you want your code to stand the test of time, there is no better way to prepare your code for this test than writing tests. The more tests you have in your project, the more confidence you will have in the code when you deploy it in production.

If it were necessary to single out only one, the most important, positive feature of the tests, what would it be? I believe this is the fact that tests help to find errors before they get into a working program. What kind of programmer would not like to have such an opportunity? I certainly would not refuse such a thing. That is why I am writing unit tests for my projects.

If you are just going to start creating tests for your project, be aware that today there are a lot of tools and frameworks for organizing code testing. Here is some good stuff about it.

6. Write as simple functions as possible.


As we all know, JavaScript without problems allows you to create huge functions that solve many tasks at once.

If you are new to programming, then this may seem positive to you. I’ll say about myself that in the old days I felt great when I wrote hefty pieces of code that did what I needed. It mattered mainly to me. I felt more confident when I saw that my code worked without problems, not to mention the fact that my self-confidence was reinforced by the fact that I was able to write a huge block of well-working code. How naive I was then!

If you want to write code that is easy to maintain, code that is simple and not too error prone, then your best bet is to make your functions as simple and small as possible. The simpler the function, the easier it is to test it in isolation from other parts of the system.

This is especially important for those who want to use the principles of functional programming in their work. In this regard, we can recall one well-known requirement for functions: a function must solve only one problem and it needs to solve this problem very well.

7. Always remember the importance of error handling when using JSON.parse and JSON.stringify


In JavaScript programming, when passing JSON data to a method JSON.parse, it is necessary to take into account the fact that this method expects to receive, as the first argument, a correctly executed JSON code. If this method receives JSON materials with which something is wrong, it will throw an error.

The danger here is that passing an JSON.parseincorrect JSON code causes the application to stop. At work, I recently encountered a situation where one of our web projects threw errors due to the fact that one of the external packages did not fit JSON.parseinto the block try/catch. This ended in a failure of the page, and we could not get rid of the problem until the external package code was fixed. All this happened due to the fact that in the code, during its operation, an unprocessed error appeared:

SyntaxError: Unexpected token } in JSON at position 107

When processing JSON data coming into the application from external sources, one cannot hope that it will be correctly formatted. You always need to be prepared for the fact that they can meet something that will cause an error.

Summary


We hope that the recommendations given here to improve the reliability of JavaScript code are useful to you.

Dear readers! What would you recommend to those who want to write better and more reliable JavaScript code?

Source: https://habr.com/ru/post/undefined/


All Articles