Intérêt du typage dynamique fort en JavaScript

JavaScript est déjà un langage typé dynamiquement à la base, mais on ne peut pas considérer que JavaScript ait un typage fort ; les erreurs de types sont encore sources de nombreux bugs dans les applications JavaScript.

Il y a TypeScript de Microsoft ou Flow de Facebook qui sont apparus dans ce sens pour essayer d’éliminer ces erreurs, mais c’est du typage statique. Ces solutions ne permettent pas de valider les types des données à l’exécution, seulement à la compilation. De ma propre expérience, le typage statique est insuffisant pour prévenir la majorité des bugs issus d’erreurs de types. Cela vient du fait que dans le cadre d’applications JavaScript, nous reposons énormément sur des sources non prédictibles de données : saisies utilisateur, dépendances externes (CDN, npm, bower), web services et API externes… Le typage statique ne permet pas de contrôler la validité de ces données puisqu’elles arrivent à l’exécution.

C’est pour ça que je travaille depuis maintenant huit mois sur une bibliothèque JavaScript baptisée Object Model chargée d’apporter un typage dynamique fort en JavaScript. Cela permet d’identifier bien plus rapidement la source d’un problème grâce aux exceptions générées. Object Model est aussi bien plus simple à maîtriser que TypeScript: pas de nouveau langage, pas de phase de compilation, il se présente simplement sous la forme d’une micro-bibliothèque JavaScript.

J’aurais voulu connaître votre avis sur l’intérêt du typage dynamique VS typage statique. Je cherche aussi des testeurs pour mettre à l’épreuve cette bibliothèque et recueillir votre feedback. Merci

2 « J'aime »

Je ne suis pas développeur JS mais Java et je pense que le besoin est réel puisque même Java a appliqué une logique similaire. En effet Java est un langage au typage statique mais ceci n’a pas empêché la création de la JSR 303: Bean validation dans le but de valider les données entrantes.

Bonne chance pour ce projet ! Je ne me porterais pas béta testeur vu que je fais rarement du JS désolé :)

L’idée est pas mal, d’autant qu’utiliser des proxies rend la librairie assez transparente. J’y vois un intérêt au niveau des fonctions : pouvoir changer la signature d’une fonction et détecter les régressions directement via les tests unitaires. Par contre au niveau des objets, c’est plus le contrat que le type qui a un intérêt (en tout cas en ce qui me concerne).

A l’occaz je pense que je ferais le test, mais peut être plus pour décrire les contrats que j’attends sur certaines parties de mon code.

Beau boulot en tout cas ! :)

Merci de ton retour. Est-ce que le système actuel d’assertions pourrait répondre au besoin de vérification de contrat, ou vois-tu d’autres choses à rajouter ?

C’est plutôt la signature des services / fonctions qui m’intéressent dans mon cas, par exemple pour ne pas avoir de “lying test” lors d’un changement d’api. Faut que je code un peu pour me faire une idée, je te dirais à ce moment là ;-).

Object Model, c’est un peu la même chose que Flow ?

Comme expliqué dans mon premier post, Flow est du typage statique tandis qu’Object Model est du typage dynamique

Personnellement, je n’ai jamais senti le besoin d’avoir un static typing en JS, ça n’est pas vraiment le type d’erreur auquel je fais généralement face.

Mais je suppose qu’une des remarques qui pourra t’être faite, c’est que c’est bien beau d’être informé de l’erreur au moment de l’exécution et non de la compilation, mais n’est-ce pas déjà trop tard ? Le but de Flow est d’anticiper un maximum d’erreur avant que le code ne soit envoyé en production. Une fois en prod, côté client, que peut-on vraiment faire ?

Il y a certainement des cas d’usages, comme il doit y en avoir pour flow. Simplement je ne les ai pas rencontrés.

En revanche, je manque cruellement d’une bonne librairie JS qui me permettrait de gérer correctement mes modèles (attributs, méthodes, héritage etc.). Aussi si ta lib adresse aussi ce problème, cela peut m’intéresser ! :-)

1 « J'aime »

A l’exécution ne signifie pas en production. Si tu envoies ton code en production sans jamais l’avoir exécuté, tu risques d’avoir des problèmes ^^

Tout comme Flow, Object Model présente un intérêt en phase de développement et de recette : le typage et les contraintes donnent un code plus explicite et la remontée d’exceptions accélère le débogage. Avec Flow tu dois lancer une analyse statique du code projet, tandis qu’avec Object Model ces vérifications sont faites automatiquement pendant l’exécution du code. Ça revient plus ou moins au même si tu as une suite de tests unitaires exécutée à chaque build par exemple. Mais l’avantage est que tu testeras ton code “en conditions réelles”, en déroulant les scénarios applicatifs et en ayant joint les sources externes ou imprévisibles de données (typiquement les API). Une fois en production, on peut envisager de remplacer Object Model par un mock ne faisant aucune validation pour gagner en perf et réduire la taille du code.

Si tu n’as jamais eu une exception de type “undefined is not a function” ou “cannot read property on null”, ou encore un cast bizarre de Number en String qui donne un résultat à quinze décimales à l’utilisateur, alors effectivement tu n’en as peut-être pas besoin. J’ai codé cette bibliothèque parce que je voyais ce genre d’erreurs régulièrement dans mes projets pros et qu’il fallait une solution pour gagner en fiabilité et en temps de débogage.

Concernant la gestion de modèles, Object Model peut servir à ça vu qu’il gère la chaîne prototypale et l’héritage de façon simple. Mais si ne comptes pas utiliser le typage, je te conseille plutôt stampit d’Eric Elliott. Ce mec connaît son sujet.

Oui, je suis d’acc ça permet de détecter les erreurs en dev/testing, ça c’est cool.
Mais le problème de la prédictibilité des données externes a surtout lieu en prod, quand on est branché sur des APIs sur lesquelles on n’a pas la main.

J’ai bien-sûr eu à faire à des “undefined is not a function”, mais je n’ai pas eu le sentiment que la solution résidait dans un typing fort. Mais n’ayant pas essayé, il est fort possible que je passe à côté d’une grande aide à la progammation. Ahalala, la difficulté d’intégrer de nouveaux outils dans son workflow.

En tout cas, c’est un chouette projet. Simplement, je tends plus à essayer de “fonctionnaliser” mon JS plutôt que de l’“objectiser”. En gros, si je devais ajouter des outils par dessus JS, j’irai chercher du côté des features offertes par Clojurescript.

Et quand tu seras mûr, n’hésite pas à ajouter ton projet à ce document : https://github.com/jashkenas/coffeescript/wiki/List-of-languages-that-compile-to-JS

Bon hacking !

Il ne s’agit pas d’un langage compilant en JS, c’est une simple bibliothèque. Les getter/setter ES5 font des merveilles, et ça sera encore mieux avec l’arrivée des Proxies.

Je ne comprend pas ce que c’est que “typage dynamique fort”? Dans mon esprit, ce serait juste éviter la conversion implicite ?

Il n’y a pas de définition exacte de ce qu’est le typage fort, mais en gros, c’est la garantie que le type attribué à une variable décrive correctement son contenu en toutes circonstances. Par exemple, si tu déclares un nombre entier N, alors il est impossible d’attribuer à N une valeur qui ne serait pas un nombre entier. Dans le cas d’Object Model, une validation est effectuée à chaque assignation/modification d’une instance de modèle (le modèle étant la description typée des instances, un peu comme la notion de classe mais en restant dynamique). Si la validation échoue, une exception est levée avec un message explicite. Concernant la notion de typage dynamique, c’est plus simple à expliquer. On parle de typage statique quand la majorité des vérifications de type sont effectuées au moment de la compilation. Au contraire, on parle de typage dynamique quand ces vérifications sont effectuées pendant l’exécution. Ça signifie également que le typage peut évoluer pendant l’éxécution, c’est-à-dire que tu peux modifier un modèle selon l’état du programme.

Je t’invite à regarder la documentation pour mieux comprendre ce dont il s’agit.

Et dans la sémantique de ton programme… ça veut dire que le programme plante quand il est dans un cas non geré par le système type (en admettant ses décorations)?
Donc quelle différence as-t-on avec un programme “non dynamiquement typé fortement” ?

Tu veux parler des runtime errors comme les NullPointerException de Java par exemple ? On peut remercier la JVM pour ça, car tous les langages statiquement typés n’en proposent pas ou alors les erreurs remontées sont moins claires. D’où la définition donnée ci-dessus: “On parle de typage statique quand la majorité des vérifications de type sont effectuées au moment de la compilation”. Ceci dit, même si certaines erreurs sont remontées au runtime, on est loin de la flexibilité offerte par le typage dynamique.

Je suis arrivé au Javascript après 20 ans C, C++ et C# et les aspects dynamiques de ce langage m’ont fait prendre conscience du gâchis de temps et d’effort humain en essayant de programmer dans un système avec un système de typage statique et rigide. Il y a évidemment des avantages au typage fort mais les inconvénients sont beaucoup plus importants. Javascript est un langage de maître, c’est un langage programmable, c’est programmable parce qu’il est dynamique ne le dénaturer pas sous prétexte qu’il n’est pas adapté aux programmeurs débutants. Je sais je suis sévère mais il n’y a pas que moi : “Until real software engineering is developed, the next best practice is to develop with a dynamic system that has extreme late binding in all aspects”. Alan Kay (celui qui à inventé le terme Orienté Objet) et qui s’en excuse presque ici.

Où veux-tu en venir ? Je suis d’accord avec toi sur les limitations du typage statique et rigide, c’est précisément pourquoi cette bibliothèque fait du typage dynamique et non statique comme ses concurrents (TypeScript pour n’en citer qu’un). Je crois que tu as lu un peu trop vite mon post…

Effectivement tu as raison, j’ai lu trop vite ton post :-(

J’ai regardé plus posément. C’est vrai que ton typage est dynamique et que tu évite certains problème du typage statique, mais comme tu le présente c’est un typage fort quand même et ça n’évite pas les écueils du typage fort.
D’une manière générale ta librairie invite à penser et coder OO (à la sauce “statique”, comme en C# et Java), ce qui n’ai pas le style inhérent de programmation en Javascript. Tu feras le bonheur de tout ceux qui sont pour le retour de la notion de classe en Javascript, ils sont nombreux.

Néanmoins personnellement je trouve que l’approche OO est une erreur historique. J’ai tendance à penser que quand on code on doit être concentré sur le flux d’exécution du programme et donc focaliser son attention sur ses fonctions leurs grains, leurs entrées, leurs sorties, les échanges client/serveur, plutôt que la nature « statique » de son modèle.

Là où je verrais un intérêt pour ta librairie c’est de permettre de définir le modèle de donnée en Javascript dans ce cas il aurait plutôt sa place du côté du serveur, cela dit je ne pense pas qu’un modèle objet soit adapté pour décrire un modèle de données non plus.

1 « J'aime »

Je suis totalement contre la notion de classe en JavaScript, pour preuve un des derniers articles que j’ai publié : http://sylvainpv.developpez.com/traductions/javascript/idees-fausses-heritage/ ; en revanche j’aime beaucoup la notion de prototype.

Dire que l’orienté objet n’est pas le style inhérent de programmation en JavaScript est très discutable quand on sait qu’il a été conçu pour ressembler à Java. Mais bon je ne rentrerais pas dans ce débat là, ça risquerait de polluer fortement le topic. Si tu veux discuter davantage de ce sujet, je t’invite à créer ton propre topic.

1 « J'aime »
Human Coders - Le centre de formation recommandé par les développeur·se·s pour les développeur·se·s