Comment éviter les «erreurs de langage dynamiques» typiques?

42

J'ai récemment consacré quelques heures à JavaScript car je souhaitais tirer parti de la base d'utilisateurs massive. En faisant cela, j'ai remarqué un motif que la plupart des gens attribuent aux langages dynamiques. Vous faites fonctionner les choses très rapidement, mais une fois que votre code a atteint une certaine taille, vous perdez beaucoup de temps avec les erreurs de frappe, d'orthographe et de refactoring en général. Erreurs qu'un compilateur m'épargnerait normalement. Et ne me laissez pas chercher des erreurs dans la logique quand je viens de faire une faute de frappe dans un autre module.

Compte tenu de l'incroyable langage JavaScript et des autres langages à typage dynamique qui ont suivi, je suis convaincu que quelque chose ne va pas dans mon approche. Ou est-ce juste le prix que vous devez payer?

Pour le dire de façon plus concise:

  • Comment abordez-vous un projet JavaScript (ou tout autre langage dynamique) avec ~ 2000 LOC?
  • Existe-t-il des outils pour m'empêcher de commettre ces erreurs? J'ai essayé flow by Facebook et JSHint, ce qui aide un peu, mais n'attrape pas de fautes de frappe.
TomTom
la source
2
Même s'il existe des moyens d'atténuer les coûts, il y a des coûts .
Dcastro
29
J'essaierais d'écrire votre programme dans un langage typé de manière statique qui compile en javascript, tel que Typescript, Scala.js ou Elm.
Dcastro
6
tests, tests, tests et rapports de couverture.
njzk2
7
~ 2000 LOC est un petit projet. Il devrait facilement s'intégrer à ce qu'un langage dynamique fait facilement et bien. Si vous avez des difficultés avec ce type de projet de taille, vos compétences en programmation posent un problème plus fondamental que tout ce qui concerne les langages dynamiques en particulier.
Jack Aidley
5
@ JackAidley En désaccord. OP est utilisé pour se concentrer sur les problèmes de haut niveau et non pour déterminer si un identifiant est orthographié correctement. C'est la compétence de programmation. Il est possible de s’assurer que l’orthographe est correcte au moyen d’une niveleuse et / ou d’un outil.
Mucaho

Réponses:

37

Plus précisément, en JavaScript, vous pouvez utiliser TypeScript à la place. Il offre certaines des choses dont vous parlez. Citant le site:

Les types permettent aux développeurs JavaScript d'utiliser des outils et des pratiques de développement hautement productifs, tels que la vérification statique et le refactoring de code, lors du développement d'applications JavaScript.

Et ce n'est qu'un sur-ensemble de JS, ce qui signifie qu'une partie de votre code existant fonctionnera parfaitement avec TS:

TypeScript part de la même syntaxe et de la même sémantique que des millions de développeurs JavaScript connaissent aujourd'hui. Utilisez le code JavaScript existant, incorporez les bibliothèques JavaScript populaires et appelez du code TypeScript à partir de JavaScript.

VinArrow
la source
11
... et TypeScript correspond essentiellement à Ecmascript 6.
Robert Harvey
11
Euh, cette citation fait mal. Cela montre simplement que Microsoft a toujours été une entreprise de langages statiques qui ne comprend tout simplement pas les langages dynamiques. "Les types permettent… le refactoring de code"? Vraiment? Le service des relations publiques de Microsoft réalise-t-il que la refactorisation du code en tant que pratique a été inventée en Smalltalk (un langage dynamique) et existait même avant en Forth (un langage sans typage)? Que le tout premier outil de refactoring automatisé faisait partie d'un IDE Smalltalk, avant même que les langages statiques aient des IDE? Que les IDE Smalltalk modernes disposent d’outils de refactoring au moins aussi puissants sinon plus que Java, C # et C ++? Allons y.
Jörg W Mittag
5
TypeScript est un excellent langage en lui-même. Pourquoi devez-vous essayer de le pousser avec une telle absurdité?
Jörg W Mittag
29
@ Jörg Je ne connais pas suffisamment Smalltalk, mais chaque IDE pour JavaScript ou Python que j'ai vu se trouve à des kilomètres de ce qu'un bon IDE pour Java ou C # peut faire. De plus, certaines choses sont tout simplement impossibles à faire dans un langage dynamique (certains des refactorings les plus populaires en réalité): Disons que vous avez une fonction publique foo(x) { return x.bar;}ou quelque chose du genre. Comme il n'y a pas d'informations de type et que la fonction est publique (par conséquent, vous ne pouvez pas connaître tous les appelants), il vous est impossible de déterminer si bar doit être renommé baz si vous renommez une classe.
Voo
10
Cette réponse indique que la solution aux "erreurs de langage dynamique" consiste à ne pas utiliser du tout un langage dynamique.
bgusach
19

Certaines approches peuvent aider:

Tests unitaires

Écrire des tests unitaires si possible. S'en remettre à des tests manuels ou à la recherche de bogues dans la nature est un hasard.

Utiliser des cadres

Plutôt que de rouler vous-même et de risquer l’introduction de bogues, utilisez les cadres établis, si possible.

Préfère CSS / langages de haut niveau

Vous pouvez céder la fonctionnalité à CSS ou à tout autre langage de haut niveau dans lequel vous écrivez.

Refactor

Refactoriser pour réduire la quantité de code. Moins de code = moins d’endroits où les choses vont mal.

Réutilisation

Réutilisez le code existant là où vous le pouvez. Même si le code ne correspond pas exactement, il peut être préférable de copier, coller et modifier plutôt que d'écrire quelque chose de nouveau.

IDEs

Les IDE modernes ont généralement au moins un support Javascript. Certains éditeurs de texte utilisent également Javascript.

Robbie Dee
la source
5
Bien que vrais, vos conseils s’appliquent essentiellement à tous les langages de programmation et visent principalement à corriger les erreurs logiques plutôt que celles qui proviennent de langages dynamiques.
Edmz
1
"vos conseils s’appliquent fondamentalement à tous les langages de programmation" . Tout à fait vrai - de la même manière que nous passons de projets de passe-temps à des solutions complètes pour les grandes entreprises, ce qui nécessite un nombre croissant de règles, de la même manière - plus le javascript est écrit, plus il a besoin de discipline si les choses ne vont pas. se dégager rapidement. Eric Lippert le décrit très bien.
Robbie Dee
4
"Préférez les langages CSS / de haut niveau" - je ne comprends pas vraiment ce que cela signifie par rapport à JavaScript: voulez-vous déplacer des éléments (comme de l'animation, peut-être?) Dans des feuilles de style plutôt que du code JS? Quel est le lien entre CSS et les langages de haut niveau?
AnotherDave
@anotherdave Une grande partie de ce qui était jadis le domaine de Javascript peut maintenant être réalisée en CSS3. Certaines fonctionnalités pourraient également être déplacées vers un langage de niveau supérieur qui serait soumis à des contrôles plus stricts.
Robbie Dee
4
@ anotherdave Une grande partie de ce que les gens essaient de faire avec JavaScript est superficielle et inappropriée. Des bibliothèques fournissant des outils linguistiques standard, des frameworks fournissant peu d'éléments HTML standard, un code répliquant les fonctionnalités de base telles que les ancres, l'émulation MVC, le style, la réimplémentation DOM, l'abstraction AJAX, le rendu d'objets triviaux (réimplémentation de SVG), des fonctions de polyfilling non avantage pour l'utilisateur… Vous devez minimiser le montant de JS que vous écrivez. Si vous pouvez le faire sans JS, faites-le sans JS.
bjb568
2

Un outil qui n’a pas encore été mentionné est la recherche de texte simple, locale ou dans l’ensemble du projet .

Cela semble simple, mais lorsque vous incluez des expressions régulières, vous pouvez effectuer un filtrage de base à avancé, par exemple, rechercher des mots situés dans la documentation ou dans le code source.

C’est un outil efficace pour moi (en plus des analyseurs statiques) et, compte tenu de la taille de votre projet de 2k LOC, qui n’est pas particulièrement volumineuse à mon avis, devrait faire des merveilles, espérons-le.

mucaho
la source
2
grepva un long chemin. À moins que vous ne fassiez pas des choses dynamiques trop étranges, cela fait l'affaire. Cependant, cela semble très manuel si vous êtes habitué aux IDE pour les langages à typage statique.
bgusach
1

Je suis actuellement en train de refactoriser plusieurs milliers de lignes de code sur un grand projet AngularJS. L'un des plus gros soucis est de déterminer le contrat exact d'une fonction donnée. J'ai parfois fini par lire la documentation de l'API parce que des éléments de la réponse brute de l'API étaient affectés à des variables passant par 6 couches de code avant d'être modifiées et renvoyées par 6 autres couches de code.

Mon premier conseil est de concevoir par contrat . Prenez des entrées spécifiques, générez des sorties spécifiques, évitez les effets secondaires et documentez ces attentes à l'aide de TypeScript ou au moins de JSDoc.

Mon deuxième conseil est de mettre en place autant de contrôles que possible. Nous suivons la norme AirBnB et utilisons eslint sur l’ensemble de notre code base. Les crochets de validation vérifient que nous respectons toujours la norme. Nous disposons naturellement d'une batterie de tests unitaires et de tests d'acceptation, et tous les commits doivent être examinés par un pair.

Passer d'un éditeur de texte (Sublime Text) à un IDE approprié (WebStorm) a également rendu beaucoup plus facile l'utilisation du code en général. WebStorm utilisera JSDoc pour donner des conseils sur les types de paramètres attendus et déclencher une erreur si vous fournissez un type incorrect ou si vous utilisez la valeur de retour de manière incorrecte.

En JavaScript, de nouvelles fonctionnalités telles que les symboles et les getter / setters peuvent aider à imposer un certain niveau de qualité en ajoutant des assertions à une affectation de variable (par exemple, assurez-vous que l'entier est dans la plage ou que l'objet de données possède certains attributs).

Malheureusement, je ne pense pas qu'il existe une véritable solution pour prévenir les erreurs de langage dynamiques, mais seulement une série de mesures pouvant aider à réduire leur fréquence.

Nicolas Bouliane
la source
0

Ma réponse à la question «Comment abordez-vous un projet JavaScript (ou tout autre langage dynamique d'ailleurs) avec ~ 2000 LOC?»

Je développe des applications de formulaire PDF. J'aborde mon projet de développement de logiciel JavaScript (quelle que soit la taille du code source) en utilisant les éléments de réseau et les annotations de Petri. La méthode n'est liée à aucune technologie de langage de programmation particulière. Ainsi, il peut être utilisé pour d'autres «langages de programmation».

Je crée un diagramme de la logique d'application. Pour que le diagramme ne soit pas encombré, j'ajoute la plupart de mes annotations à un formulaire que j'utilise avec le diagramme. Les entrées du formulaire incluent des références à des propriétés ou à des fonctions. Ensuite, j'écris le code source en fonction des informations du diagramme et des entrées du formulaire. La méthode est systématique car chaque code source écrit est directement mappé à partir du diagramme et des entrées du formulaire. Le code source peut être facilement vérifié car je suis également conforme aux conventions de nommage et de codage lors de l'écriture du code.

Par exemple, j'ai choisi une convention selon laquelle toutes les fonctions sont des prototypes. Si les performances deviennent un problème, il peut être amélioré en déclarant les fonctions dans le constructeur. Pour certaines propriétés, j'utilise des tableaux. Encore une fois, si les performances deviennent un problème, vous pouvez les améliorer en utilisant des références directes.

J'utilise aussi eval. Cela peut considérablement réduire la taille du code source. En raison de problèmes de performances, j'utilise eval au début ou la partie d'initialisation de mon application; Je ne l'utilise jamais dans la «logique d'exécution» - c'est une autre convention de codage que je suis.

John Frederick Chionglo
la source