JavaScript lisible par l'homme: une histoire de deux experts





Tout le monde veut être un expert. Mais qu'est-ce que cela signifie? Au fil des ans, j'ai rencontré deux types de personnes appelées «experts». Un expert du premier type est une personne qui non seulement connaît tous les rouages ​​de la langue, mais utilise également tous ces rouages, que cela soit bénéfique ou non. Un expert du second type connaît également toutes les subtilités syntaxiques, mais est plus sélectif dans le choix d'un outil pour résoudre un problème, en tenant compte d'un certain nombre de facteurs, à la fois liés et non liés au code.



Imaginons quel type d'expert vous aimeriez voir dans votre équipe. Deuxièmement, non? C'est le genre de développeur qui s'efforce de produire du code lisible par l'homme, des chaînes de JavaScript que d'autres personnes peuvent comprendre et qui sont faciles à maintenir. Mais la caractéristique «lisible» est rarement déterminante - en fait, elle est généralement dans l'œil du spectateur. Alors, où cela nous mène-t-il? À quoi devons-nous nous efforcer si notre objectif est un code lisible? Y a-t-il un choix clairement bon ou mauvais dans ce cas? Cela dépend de beaucoup.



Le choix évident



Pour faciliter le travail du développeur, TC39 a ajouté de nombreuses nouvelles fonctionnalités à ECMAScript ces dernières années, y compris de nombreux modèles éprouvés empruntés à d'autres langages. L'une de ces innovations introduites dans ES2019 est la méthode Array.prototype.flat () . Il prend un argument de profondeur ou Infinity et aligne le tableau. S'il n'y a pas d'arguments, la profondeur par défaut du tableau est 1.



Avant que cet ajout n'apparaisse, la syntaxe suivante était requise pour aligner le tableau sur un seul niveau.



let arr = [1, 2, [3, 4]];
[].concat.apply([], arr);

// [1, 2, 3, 4]

      
      





En ajoutant flat (), vous pouvez décrire la même fonctionnalité avec une seule fonction expressive.



arr.flat();

// [1, 2, 3, 4]

      
      





La deuxième ligne de code est-elle plus facile à lire? Absolument oui. En fait, les deux experts seraient d'accord avec cela.



Tous les développeurs ne sont pas conscients de l'existence de flat (). Mais il n'est pas nécessaire de le savoir à l'avance, car flat () est un verbe compréhensible, à partir duquel il est clair ce qui se passe ici. C'est beaucoup plus intuitif que concat.apply ().



C'est le cas rare dans lequel vous pouvez répondre en toute confiance quelle syntaxe est la meilleure - nouvelle ou ancienne. Les deux experts, après s'être familiarisés avec les deux syntaxes, choisiront la seconde. Ils choisiront la ligne de code la plus courte, la plus claire et la plus facile à maintenir.



Mais le choix et le compromis ne sont pas toujours aussi simples.



Vérifiez les poux



Ce qui est merveilleux avec JavaScript, c'est son incroyable polyvalence. C'est pourquoi il est partout sur le Web. Que ce soit bon ou mauvais de votre point de vue est une autre question.



Mais une telle polyvalence apporte avec elle le paradoxe du choix. Le même code peut être écrit de différentes manières. Comment déterminez-vous lequel est «correct»? Une telle solution ne peut même pas être abordée si vous ne connaissez pas toutes les options disponibles et ne comprenez pas ce qu'elles n'atteignent pas.



Essayons la programmation fonctionnelle avec map () comme exemple. Je vais parcourir quelques itérations ici - elles mèneront toutes au même résultat.



Voici la version la plus concise de tous nos exemples de map (). Il a le plus petit nombre de caractères, et ils tiennent tous sur une seule ligne. Nous allons construire sur cette version.



const arr = [1, 2, 3];

let multipliedByTwo = arr.map(el => el * 2);

// multipliedByTwo  [2, 4, 6]

      
      





L'exemple suivant n'ajoute que deux caractères: des parenthèses. Avons-nous perdu quelque chose? L'avez-vous acheté? La météo oblige-t-elle toujours à utiliser des parenthèses dans une fonction qui a plus d'un paramètre? Je pense - oui, c'est le cas. Il n'y a rien de mal à les ajouter ici, mais la cohérence du code augmentera considérablement lorsque vous devrez inévitablement écrire une fonction avec de nombreux paramètres. En fait, au moment d'écrire ces lignes , Prettier s'est avéré obligé d' avoir cette restriction; là, je n'ai pas pu créer une fonction de flèche sans parenthèses.



let multipliedByTwo = arr.map((el) => el * 2);
      
      







Vas-y. Nous avons ajouté des accolades et une instruction return. Cela commence maintenant à ressembler à une définition de fonction traditionnelle. À l'heure actuelle, cela peut sembler être un mot-clé, tant que toute la logique de la fonction tire un canon sur les moineaux. Mais, si la fonction contient plus d'une ligne, cette syntaxe supplémentaire sera certainement nécessaire. Supposons-nous que nous n'aurons pas d'autres fonctions de plus d'une ligne? Cela semble douteux.



let multipliedByTwo = arr.map((el) => {

  return el * 2;

});

      
      





Ensuite, nous avons complètement supprimé la fonction de flèche. Nous utilisons la même syntaxe qu'avant, mais maintenant nous préférons le mot-clé function. Ceci est intéressant car il n'y a pas de scénario dans lequel cette syntaxe ne fonctionnerait pas; pour n'importe quel nombre de paramètres ou de chaînes, nous n'aurons aucun problème, donc ici nous sommes forts en uniformité. Ce code est plus long que notre première définition, mais est-il vraiment si mauvais? Comment cela nuit-il à un nouveau programmeur ou à quelqu'un qui n'est pas qualifié en JavaScript, mais dans un autre langage? Quelqu'un avec une bonne connaissance de JavaScript serait-il dérouté par cette syntaxe lors de la comparaison?



let multipliedByTwo = arr.map(function(el) {

  return el * 2;

});

      
      





Enfin, nous arrivons à la dernière option: ne transmettre qu'une fonction. Et timesTwo peut être écrit en utilisant n'importe quelle syntaxe que nous aimons. Encore une fois, il n'y a pas de scénario dans lequel le fait de passer le nom de la fonction se révèle être un problème pour nous. Mais prenons du recul et réfléchissons à la question de savoir si un tel code pourrait dérouter qui que ce soit. Si vous ne faites que commencer avec cette base de code, est-il clair pour vous que timesTwo est une fonction, pas un objet? Certainement, map () servira d'indice ici, mais un tel détail peut être manqué. Que diriez-vous où timesTwo est déclaré et initialisé? Est-il facile de le trouver? Est-ce clair ce qu'il fait et comment cela affecte le résultat? Toutes ces considérations sont importantes.



const timesTwo = (el) => el * 2;

let multipliedByTwo = arr.map(timesTwo);

      
      





Comme vous pouvez le voir, il n'y a pas de réponse évidente ici. Mais choisir les bonnes options lors de la création de votre base de code n'est possible que si vous comprenez toutes les options et leurs limites. En particulier, vous savez que vous avez besoin de parenthèses, de parenthèses et de mots-clés de retour pour rendre votre code cohérent.



Il y a un certain nombre de problèmes à résoudre lors de l'écriture de code. Les problèmes de performances sont généralement les plus courants. Mais lors de la comparaison de fragments de code fonctionnellement identiques, le choix doit être fait en tenant compte des personnes qui devront lire ce code.



Peut-être que le plus récent n'est pas toujours meilleur



Nous avons donc examiné un exemple très prononcé dans lequel les deux experts préféreraient la nouvelle syntaxe, même si elle n'est pas bien connue. Nous avons également examiné un exemple qui pose beaucoup de questions mais ne fournit pas beaucoup de réponses. Passons maintenant au code que j'ai écrit plus tôt ... et supprimé. Ce code a fait de moi un expert du premier type lorsque j'ai résolu le problème avec une construction syntaxique peu connue, négligeant ainsi mes collègues et la commodité de maintenir notre base de code.



L'affectation de destruction vous permet de décompresser des valeurs d'objets (ou de tableaux). Cela ressemble généralement à quelque chose comme ça.



const {node} = exampleObject;
      
      







Ici, sur une ligne, une variable est initialisée et assignée à une valeur. Mais ce n'est peut-être pas le cas.



let node

;({node} = exampleObject)

      
      





Dans la dernière ligne de code, la valeur est affectée à une variable en utilisant la déstructuration, mais la variable est déclarée une ligne vers le haut. Cela se fait souvent, mais beaucoup ne se rendent pas compte que cela est possible.



Examinons de plus près ce code. Le point-virgule gênant est imposé ici, et c'est dans le code où le point-virgule n'est pas utilisé pour terminer les lignes. Ici, la commande est placée entre parenthèses et des accolades sont ajoutées; ce qui se passe ici est totalement incompréhensible. Il est difficile de lire cette ligne, car en tant qu'expert, je n'avais absolument pas le droit d'écrire un tel code.



let node

node = exampleObject.node

      
      





Ce code résout le problème. Cela fonctionne, ce qui est fait est clair et mes collègues le comprendront sans chercher nulle part. Quant à la syntaxe destructive, je ne devrais pas l' utiliser simplement parce que je le peux .



Le code n'est pas tout



Comme nous l'avons vu, la décision d'Expert-2 est rarement demandée si l'on procède uniquement à partir du code; cependant, il est facile de discerner le code que chaque expert doit écrire. Le fait est que les machines doivent lire le code et que les gens doivent l'interpréter. Par conséquent, vous devez prendre en compte des facteurs qui ne sont pas uniquement liés au code!



Travailler dans une équipe de développement JavaScript aura une approche différente de la sélection de code que de travailler dans une équipe multilingue, dont les membres sont moins plongés dans les subtilités linguistiques.



Comparons l'opérateur d'expansion et concat () à titre d'exemple.



L'opérateur de propagation a été ajouté à ECMAScript il y a quelques années et est maintenant très courant. C'est une sorte de syntaxe d'aide avec laquelle vous pouvez faire beaucoup de choses. En particulier, concaténez un certain nombre de tableaux.



const arr1 = [1, 2, 3];

const arr2 = [9, 11, 13];

const nums = [...arr1, ...arr2];

      
      





Avec tout le potentiel de l'opérateur d'extension, son symbole ne va pas de soi. Donc, si vous ne savez pas ce que cela fait, cela ne vous aidera pas beaucoup. Alors que les deux experts sont tout à fait capables de calculer que l'équipe JavaScript-pros familière avec la syntaxe, l'expert-2, peut-être, pense qu'il est possible de dire la même chose de l'équipe multilingue de programmeurs. Par conséquent, Expert-2 peut préférer la méthode concat () car il s'agit d'un verbe informatif qui peut probablement être compris à partir du contexte du code.



Cet extrait de code donne le même résultat numérique que l'exemple ci-dessus avec l'opérateur d'extension.



const arr1 = [1, 2, 3];

const arr2 = [9, 11, 13];

const nums = arr1.concat(arr2);

      
      





Ceci est juste un exemple pour montrer comment les facteurs humains affectent la sélection de code. La base de code à laquelle les personnes de différentes équipes ont accès peut être régie par des normes plus strictes qui ne suivent pas nécessairement toutes les innovations syntaxiques intéressantes. Ensuite, vous devez vous éloigner du code source principal et prendre en compte d'autres facteurs concernant votre boîte à outils qui peuvent compliquer ou faciliter la vie des personnes travaillant sur ce code. Il existe du code qui peut être structuré pour être difficile à tester . Il y a du code qui vous mènera dans un coin et vous ne pourrez pas augmenter ou ajouter de nouvelles fonctionnalités . Il y a du code où les performances souffrent, tous les navigateurs ne sont pas pris en charge ou mal avec l'accessibilité . Expert-2 prend en compte tous ces facteurs dans ses recommandations.



Expert-2 prend également en compte le facteur de dénomination. Mais soyons honnêtes, même les experts dans la plupart des cas ne font pas face à la dénomination.



Conclusion



Le véritable expert n'est pas quelqu'un qui applique tous les grincements de la spécification, mais quelqu'un qui connaît suffisamment bien la spécification pour déployer rationnellement la syntaxe et prendre des décisions réfléchies. Un expert qui atteint ce niveau peut préparer de nouveaux experts.



Qu'est-ce que cela signifie pour ceux d'entre nous qui se considèrent comme un expert ou qui aspirent au moins à devenir un expert? Cela signifie qu'il y a de nombreuses questions à vous poser lorsque vous écrivez du code. Évaluez correctement les développeurs qui constituent votre public cible. Le meilleur code que vous puissiez écrire est un code qui résout un problème complexe, mais qui est par définition compréhensible pour ceux qui liront votre base de code.



Oui, c'est très difficile. Et il n'y a souvent pas de réponse unique. Mais vous devriez penser à ce qui précède lorsque vous écrivez chacune de vos fonctions.






Nos machines virtuelles peuvent être utilisées pour le développement de Javascript expert.



Inscrivez-vous en utilisant le lien ci-dessus ou en cliquant sur la bannière et bénéficiez d'une remise de 10% pour le premier mois de location d'un serveur de toute configuration!






All Articles