Consignes pour écrire du code JavaScript propre

Si vous vous souciez du code lui-même, de la façon dont il est écrit et que vous ne vous préoccupez pas seulement de créer des programmes de travail, cela signifie que vous voulez que votre code soit propre. Un développeur professionnel écrit du code non seulement pour les ordinateurs, mais aussi pour lui-même qui a rencontré ce code à l'avenir et pour d'autres programmeurs. Le code que vous écrivez ne disparaît pas pour toujours dans les entrailles de l'ordinateur. Il vit, change et s'il est mal écrit, il peut très bouleverser quelqu'un qui devra le modifier après l'avoir écrit. Il est possible que vous soyez ce «quelqu'un».



Sur la base de ces idées, le code propre peut être défini comme du code écrit de telle manière qu'il s'explique lui-même. Ce code peut être facilement compris par les gens, il sera facile de le modifier ou de l'étendre.

Code et questions WTF


L'essence des questions WTF, comme «WTF est-ce?» Se résume à une surprise et un ressentiment extrêmes. En russe, ces sentiments peuvent être exprimés par la question «Que diable?». «Merde», selon la situation, pourrait bien céder la place à quelque chose de complètement non imprimable. Combien de fois avez-vous déjà ajouté du code à quelqu'un et posé des questions similaires?

Lorsqu'ils se posent des questions WTF sur le code de quelqu'un d'autre, les programmeurs se demandent ce que c'est (WTF c'est ça?), Ce que l'auteur du code a essayé de faire (WTF avez-vous fait ici?), Pourquoi est-ce que telle ou telle construction est présente dans le code (WTF est cela pour?)

Voici une image selon laquelle le seul indicateur fiable de la qualité du code est le nombre de questions WTF par minute.


À gauche, un bon code. À droite, c'est mauvais

Mais sérieusement, afin de vous aider à réfléchir au code propre, nous citons Robert Martin, connu sous le nom d'Oncle Bob: «Même un mauvais code de programme peut fonctionner. Cependant, si le code n'est pas «propre», il interférera toujours avec le développement du projet. »

Voyons maintenant quelques directives pratiques pour écrire du code propre. Nous utiliserons JavaScript ici, mais ces recommandations peuvent être appliquées au développement dans d'autres langues.

1. Contrôles stricts de l'égalité


Essayez d'utiliser === au lieu de == .

 //     == -       .     ,   ,   ,   -    . 0 == false // true 0 === false // false 2 == "2" // true 2 === "2" // false //  const value = "500"; if (value === 500) { console.log(value); //     } if (value === "500") { console.log(value); //    } 

2. Variables


Nommez les variables pour que leurs noms révèlent leur essence, leur rôle dans le programme. Avec cette approche, il sera pratique de les rechercher dans le code, et quiconque verra ce code pourra plus facilement comprendre la signification des actions qu'ils effectuent.
Mauvais:

 let daysSLV = 10; let y = new Date().getFullYear(); let ok; if (user.age > 30) { ok = true; } 

Bon:

 const MAX_AGE = 30; let daysSinceLastVisit = 10; let currentYear = new Date().getFullYear(); ... const isUserOlderThanAllowed = user.age > MAX_AGE; 

Pas besoin d'ajouter des mots supplémentaires aux noms de variables qui ne sont pas nécessaires.

Mauvais:

 let nameValue; let theProduct; 

Bon:

 let name; let product; 

Vous ne devez pas forcer une personne qui lit le code à se souvenir de l'environnement dans lequel la variable est déclarée.

Mauvais:

 const users = ["John", "Marco", "Peter"]; users.forEach(u => { doSomething(); doSomethingElse(); // ... // ... // ... // ... //    ,    WTF- "   `u`?" register(u); }); 

Bon:

 const users = ["John", "Marco", "Peter"]; users.forEach(user => { doSomething(); doSomethingElse(); // ... // ... // ... // ... register(user); }); 

Vous n'avez pas besoin de fournir des noms de variables avec des informations redondantes sur le contexte dans lequel ils sont utilisés.

Mauvais:

 const user = { userName: "John", userSurname: "Doe", userAge: "28" }; ... user.userName; 

Bon:

 const user = { name: "John", surname: "Doe", age: "28" }; ... user.name; 

3. Fonctions


Utilisez des noms descriptifs longs pour les fonctions. Étant donné qu'une fonction est une description d'une certaine action, son nom doit être un verbe ou une phrase qui décrit pleinement l'essence de la fonction. Les noms des arguments doivent être sélectionnés de manière à décrire correctement les données qu'ils représentent. Les noms de fonction doivent indiquer au lecteur de code ce que font exactement ces fonctions.

Mauvais:

 function notif(user) { //  } 

Bon:

 function notifyUser(emailAddress) { //  } 

Évitez d'utiliser de longues listes d'arguments. Idéalement, les fonctions devraient avoir deux arguments ou moins. Moins une fonction a d'arguments, plus il sera facile de la tester.

Mauvais:

 function getUsers(fields, fromDate, toDate) { //  } 

Bon:

 function getUsers({ fields, fromDate, toDate }) { //  } getUsers({ fields: ['name', 'surname', 'email'], fromDate: '2019-01-01', toDate: '2019-01-18' }) 

Utilisez les arguments par défaut, en leur donnant la préférence sur les constructions conditionnelles.

Mauvais:

 function createShape(type) { const shapeType = type || "cube"; // ... } 

Bon:

 function createShape(type = "cube") { // ... } 

Une fonction devrait résoudre un problème. Efforcez-vous de vous assurer qu'une fonction n'exécute pas beaucoup d'actions.

Mauvais:

 function notifyUsers(users) { users.forEach(user => {   const userRecord = database.lookup(user);   if (userRecord.isVerified()) {     notify(user);   } }); } 

Bon:

 function notifyVerifiedUsers(users) { users.filter(isUserVerified).forEach(notify); } function isUserVerified(user) { const userRecord = database.lookup(user); return userRecord.isVerified(); } 

Utilisez Object.assign pour définir les propriétés des objets par défaut.

Mauvais:

 const shapeConfig = { type: "cube", width: 200, height: null }; function createShape(config) { config.type = config.type || "cube"; config.width = config.width || 250; config.height = config. height || 250; } createShape(shapeConfig); 

Bon:

 const shapeConfig = { type: "cube", width: 200 //   'height'   }; function createShape(config) { config = Object.assign(   {     type: "cube",     width: 250,     height: 250   },   config ); ... } createShape(shapeConfig); 

N'utilisez pas de drapeaux comme paramètres. Leur utilisation signifie que la fonction effectue plus d'actions qu'elle n'aurait dû effectuer.

Mauvais:

 function createFile(name, isPublic) { if (isPublic) {   fs.create(`./public/${name}`); } else {   fs.create(name); } } 

Bon:

 function createFile(name) { fs.create(name); } function createPublicFile(name) { createFile(`./public/${name}`); } 

Ne polluez pas la portée mondiale. Si vous devez développer un objet existant, utilisez les classes ES et les mécanismes d'héritage au lieu de créer des fonctions dans la chaîne prototype d'objets standard.

Mauvais:

 Array.prototype.myFunc = function myFunc() { //  }; 

Bon:

 class SuperArray extends Array { myFunc() {   //  } } 

4. Constructions conditionnelles


Essayez de ne pas nommer les variables booléennes pour qu'il y ait négation dans leurs noms. Il en va de même pour les fonctions qui renvoient des valeurs booléennes. L'utilisation de telles entités dans des constructions conditionnelles rend difficile la lecture du code.

Mauvais:

 function isUserNotBlocked(user) { //  } if (!isUserNotBlocked(user)) { //  } 

Bon:

 function isUserBlocked(user) { //  } if (isUserBlocked(user)) { //  } 

Utilisez le formulaire court pour les constructions conditionnelles. Cette recommandation peut sembler banale, mais elle mérite d'être mentionnée. Utilisez cette approche uniquement pour les variables logiques et si vous êtes sûr que la valeur de la variable ne sera pas undefined ou null .

Mauvais:

 if (isValid === true) { // - ... } if (isValid === false) { // - ... } 

Bon:

 if (isValid) { // - ... } if (!isValid) { // - ... } 

Évitez autant que possible les constructions logiques. Utilisez plutôt le polymorphisme et l'héritage.

Mauvais:

 class Car { // ... getMaximumSpeed() {   switch (this.type) {     case "Ford":       return this.someFactor() + this.anotherFactor();     case "Mazda":       return this.someFactor();     case "McLaren":       return this.someFactor() - this.anotherFactor();   } } } 

Bon:

 class Car { // ... } class Ford extends Car { // ... getMaximumSpeed() {   return this.someFactor() + this.anotherFactor(); } } class Mazda extends Car { // ... getMaximumSpeed() {   return this.someFactor(); } } class McLaren extends Car { // ... getMaximumSpeed() {   return this.someFactor() - this.anotherFactor(); } } 

5. Classes ES


Les classes sont apparues en JavaScript relativement récemment. Ils peuvent être appelés sucre syntaxique. Ce qui se passe lors de l'utilisation des classes est basé sur des prototypes d'objets, comme précédemment. Mais le code qui utilise les classes est différent. En général, si possible, les classes ES doivent être préférées aux fonctions constructeurs normales.

Mauvais:

 const Person = function(name) { if (!(this instanceof Person)) {   throw new Error("Instantiate Person with `new` keyword"); } this.name = name; }; Person.prototype.sayHello = function sayHello() { /**/ }; const Student = function(name, school) { if (!(this instanceof Student)) {   throw new Error("Instantiate Student with `new` keyword"); } Person.call(this, name); this.school = school; }; Student.prototype = Object.create(Person.prototype); Student.prototype.constructor = Student; Student.prototype.printSchoolName = function printSchoolName() { /**/ }; 

Bon:

 class Person { constructor(name) {   this.name = name; } sayHello() {   /* ... */ } } class Student extends Person { constructor(name, school) {   super(name);   this.school = school; } printSchoolName() {   /* ... */ } } 

Organisez les méthodes afin qu'elles puissent être enchaînées. De nombreuses bibliothèques utilisent ce modèle, comme jQuery et Lodash. Par conséquent, votre code sera plus compact que sans utiliser ce modèle. Le fait est qu'à la fin de chaque fonction de la classe, vous devez retourner this . Cela vous permettra de combiner les appels de ces fonctions en chaînes.

Mauvais:

 class Person { constructor(name) {   this.name = name; } setSurname(surname) {   this.surname = surname; } setAge(age) {   this.age = age; } save() {   console.log(this.name, this.surname, this.age); } } const person = new Person("John"); person.setSurname("Doe"); person.setAge(29); person.save(); 

Bon:

 class Person { constructor(name) {   this.name = name; } setSurname(surname) {   this.surname = surname;   //  this           return this; } setAge(age) {   this.age = age;   //  this           return this; } save() {   console.log(this.name, this.surname, this.age);   //  this           return this; } } const person = new Person("John")   .setSurname("Doe")   .setAge(29)   .save(); 

6. Quoi de mieux ne pas faire


Quiconque souhaite que son code soit propre doit essayer de ne pas le répéter. Le but est d'éviter les situations dans lesquelles vous devez écrire le même code. De plus, vous n'avez pas besoin de laisser les fonctions inutilisées et les fragments de programme qui ne sont jamais exécutés dans la base de code.

Un code en double peut apparaître pour diverses raisons. Par exemple, un projet peut avoir une paire de fonctions légèrement différentes. La nature de ces différences ou du manque de temps oblige le programmeur, par exemple, à créer deux fonctions indépendantes contenant du code presque identique. Dans une telle situation, se débarrasser du code en double, c'est faire abstraction des différences et travailler avec elles à un niveau supérieur.

Parlons maintenant du code inutilisé. C'est du code qui est présent dans la base de code mais qui ne fait absolument rien. Cela se produit, par exemple, quand à un certain stade de développement, il est décidé qu'il n'y a plus de sens dans un certain fragment du programme. Afin de vous débarrasser de ces fragments de code, vous devez examiner attentivement la base de code et les supprimer. Il est plus facile de se débarrasser d'un tel code au moment où il est décidé qu'il n'est plus nécessaire. Plus tard, vous pouvez oublier à quoi il a servi. Cela compliquera grandement le combat avec lui.

Si vous retardez la lutte contre le code inutile, le programme ressemblera à ce qui est illustré dans la figure suivante.


Parfois, mon code ressemble à ce balcon. Je ne sais pas quelle tâche il est en train de résoudre, mais j'ai peur de me débarrasser de lui

Résumé


Ici, nous n'avons discuté que d'une petite partie des actions qui peuvent être prises pour améliorer le code. L'auteur de ce document estime que les principes discutés ici sont souvent oubliés. Les programmeurs essaient de les suivre, mais, pour diverses raisons, n'y parviennent pas toujours. Peut-être qu'au tout début du projet, tout le monde se souvient de l'importance d'un code propre, le programme est donc soigné. Ensuite, à mesure que les délais se rapprochent, ils oublient souvent la pureté du code, en ne prêtant attention qu'à ce qui est marqué TODO ou REFACTOR. À ces moments, le client du projet insistera pour que le projet soit terminé à temps et non pour que son code soit propre.

Très souvent, nous publions des documents sur le problème de l'écriture de code JavaScript de haute qualité. Si vous êtes intéressé par ce sujet, voici quelques liens.


Nous espérons que ce que vous avez appris en lisant cet article et ce que vous pouvez trouver dans d'autres publications vous aideront dans votre quête pour écrire du code JavaScript propre.

Chers lecteurs! Avez-vous déjà posé des questions WTF lors de la lecture du code de quelqu'un d'autre?



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


All Articles