IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

JSConf Berlin 2018 - Ryan Dahl liste 10 erreurs de conception sur Node.js
Et dévoile son prototype deno

Le , par Marco46

6PARTAGES

18  0 
Le 8 novembre 2009 à la JSConf de Berlin, Ryan Dahl dévoilait son prototype Node.js en version 0.1.16.


Son postulat de départ était que l'usage d'une boucle d’événements (event loop) associée à une gestion des entrées/sorties non bloquantes (non-blocking I/O) est bien plus efficace pour programmer un serveur que d'utiliser un thread par client connecté en se basant sur la différence d'architecture opposant nginx à Apache.


La boucle d'événements tient bien mieux la montée en charge, et permet d'utiliser plus efficacement les ressources de la machine.

Son prototype a été adopté très rapidement par l'industrie du web américaine, pour être aujourd'hui le coeur de l'écosystème JavaScript et la composante principale des systèmes d'information de fournisseurs de services très connus comme PayPal, Twitter ou Netflix.

Qui est Ryan Dahl

Ryan Dahl a grandi aux USA à San Diego, il n'est pas un informaticien de formation. Initialement il poursuivait un PhD en mathématiques (équivalent US du Doctorat) à l'université de Rochester.

Jugeant les maths trop difficiles à appliquer au réel, il laissait tomber ses études pour partir en Amérique du Sud, où il fut embauché comme développeur web sur une stack à base de Ruby on Rails dans une entreprise qui vendait des snowboards.

Puis il partit en Allemagne accompagnant sa petite amie, où il commença à fréquenter les conférences sur Rails et travailla en tant qu'indépendant sur différents modules pour le serveur web Nginx.

Fin 2008, à la sortie du moteur JavaScript V8 de Google il commença à jouer avec, et disposant de temps libre du fait d'une activité professionnelle en dent de scie, il se mit en tête de développer un prototype de plateforme serveur utilisant V8 et appliquant les principes appris de Nginx .

En l'espace de 6 mois, Node.js était né.

Jusqu'en 2012, Ryan Dahl travailla professionnellement sur le développement de Node.js au sein de la société Joyent à San Francisco. Puis il décida de mettre un terme à cette activité considérant que Node.js était devenu ce qu'il voulait qu'il soit au départ et que le langage Go qui venait de sortir des fours de Google était plus adapté pour le développement de serveurs.

Au cours des années suivantes il disparut des radars puis rejoint notamment le Google AI Residency Program, intéressé par les développements récents en machine learning.

Ryan Dahl est réapparu aux yeux du monde le weekend dernier ... à la JS Conf de Berlin pour une présentation nommée "Design Mistakes in Node", ce qui peut être traduit en "Erreurs de conception de Node".

JSConf Berlin 2018


Lors de sa présentation, Ryan Dahl explique qu'il s'est remis à utiliser intensivement Node.js au cours des 6 derniers mois. Pour lui, les langages dynamiques sont les plus adaptés pour des projets de calculs scientifiques et JavaScript est le meilleur langage dynamique.

Il trouve Node.js sympa à utiliser, mais est gêné par des erreurs de conception qu'il est impossible de corriger désormais, l'écosystème étant beaucoup trop gros.

Selon Ryan Dahl, Node.js souffre de 10 erreurs de conception (ses 10 regrets)

- Ne pas avoir conservé les promesses (Promises).

Elles ont été ajoutées en juin 2009, et retirées en février 2010.

Il jugeait à l'époque que les promesses ajoutaient un concept supplémentaire pour gérer l'asynchronisme alors que les callbacks étaient disponibles. Il les a retirés pour conserver une API minimaliste.

Les promesses sont la brique de base nécessaire à l'implémentation de async / await. En retirant les promesses, Ryan Dahl a donc retardé considérablement l'arrivée et la standardisation de async / await, jugée comme l'abstraction la plus simple et la plus propre pour gérer l'asynchronisme, et forcé le monde à utiliser des callbacks.

- Sécurité.

Le moteur V8 de Google est un bon bac à sable sécurisé pour l'exécution de programmes, mais node fait sauter cette sécurité en donnant par défaut l'accès à tout le système (système de fichiers, réseau, etc.).

Par défaut, un programme node ne devrait pouvoir utiliser que les ressources qu'on lui autorise. Par exemple un linter ne devrait pas pouvoir accéder au réseau ni écrire de fichiers sur le disque de l'utilisateur.

En définitive, node devrait être plus sécurisé par défaut.

- Le système de build (GYP) est trop complexe.

Dépend de Python et est utilisé pour lier les dépendances écrites dans d'autres langages (C, C++, etc.) à node.

Il le juge inutilement complexe et pense qu'il s'agit là de sa plus grosse erreur de conception.

- Le système de build (GYP) aurait pu être remplacé par les foreign function interface dès le début.

Deuxième regret concernant le système de build, il n'a pas écouté certains membres de la communauté qui proposaient une alternative jugée aujourd'hui meilleure, les foreign function interface (FFI). Il s'agit d'un mécanisme permettant d'appeler des fonctions d'une dépendance écrite et compilée dans un langage B depuis un programme écrit et compilé dans un langage A.

L'avantage principal de ce système est qu'il supprime la nécessité d'une recompilation de la dépendance à intégrer.

Quiconque a déjà utilisé une dépendance npm nécessitant une recompilation via node-gyp sous Windows connaît la douleur résultant de ce choix.
La recompilation nécessite l'installation de Python et de l'environnement de compilation complet (Compilateur C++ de Visual Studio par exemple), tout ça pour utiliser une malheureuse dépendance npm (le très utilisé browser-sync par exemple ...).

- Le package.json définit un module.

En autorisant la fonction require() à inspecter nativement le contenu des fichiers package.json et en incluant npm dans les livraisons de node, il a défini npm comme le gestionnaire de packages de facto et donc imposé l'usage d'un fichier package.json pour définir un module, ce qui n'était pas le cas avant.

Le problème de ce choix, c'est que npm est un système centralisé et contrôlé par une entité privée (npm inc) ce qui lui déplaît fortement.

-require('somemodule') n'est pas spécifique.

Il veut dire par là que l'usage de la fonction require ne suffit pas à définir comment récupérer ce module.

Ce module doit être aussi défini dans le package.json (dans la propriété dependencies) pour déterminer dans quelle version le module va être récupéré.

Ce module existe également dans le répertoire node_modules/ local au projet, il peut aussi exister globalement sur la machine.

Enfin ce module existe également dans la base de données de npm (le registre en fait).

- Le package.json permet de définir un répertoire comme étant un module.

L'existence du package.json pour définir un module permet l'existence d'un module sous forme de répertoire.

Il estime que c'est une abstraction inutile, car elle ne correspond à rien sur le web dans le sens ou une URL désigne une ressource et pas un répertoire. De plus cette abstraction tire avec elle toute sorte d'informations inutiles (la licence, l'URL du dépôt git, une description, etc. ) lorsque le but est de lier une bibliothèque à une application.

Si les modules étaient obligatoirement un fichier unique, alors il serait possible de gérer le versionning dans l'URL. Le fichier package.json pourrait être supprimé.

- node_modules/ est trop gros.

Le répertoire node_modules/ occupe beaucoup trop d'espace sur le disque.

Le principe d'avoir un répertoire contenant toutes les dépendances à l'extérieur du code source de l'application, mais à l'intérieur du répertoire du projet (donc de chaque projet) semble séduisant, mais en pratique, une simple variable d'environnement $NODE_PATH aurait suffit.

Par ailleurs ce fonctionnement dévie du fonctionnement des navigateurs.

- La possibilité de ne pas spécifier l'extension lors de l'utilisation de require('somemodule').

Mauvaise fonctionnalité, car rend l'import moins explicite. On ne sait pas s'il s'agit d'un .js, d'un .ts, ou d'autres choses.

Complexifie l'algorithme du module loader qui doit chercher dans tous les cas de figure possibles pour trouver le module à charger (cf le pseudo-code de l'algorithme dans la doc officielle pour se faire une idée !).

Là encore cela dévie de la manière dont les navigateurs fonctionnent.

- index.js.

Enfin il s'excuse pour l'existence du fichier index.js qui sert de point d'entrée par défaut, créant un cas supplémentaire pour l'algorithme de résolution des modules.

Il pensait que ce serait une bonne idée d'utiliser la même convention que pour le html (index.html qui est par convention le point d'entrée d'un site web).

Cela a ajouté une complexité inutile, en particulier après le support du package.json qui permet la définition du point d'entrée (propriété main).

En conclusion de cette liste de regrets, Ryan Dahl explique qu'il trouve que Node.js est un bon outil et que son problème avec se limite en définitive avec la manière dont node gère le code source de l'utilisateur.

Il explique ce manque par le fait que son sujet initial était de changer la manière dont les développeurs géraient les I/O, et qu'en se focalisant sur ce problème il n'a pas passé assez de temps sur ce problème fondamental de système de modules qui a été ajouté après coup parce qu'il en fallait bien un.

Son prototype deno

Ryan Dahl définit deno comme un "moteur d'exécution TypeScript sécurisé bâti sur V8" ("A secure TypeScript runtime on V8").

Le code source du prototype est disponible sur GitHub.

Objectifs :

- Sécurité.

Par défaut, un script ne doit pas avoir les droits d'utiliser le réseau et d'accéder en écriture au système de fichier. L'utilisateur du script doit accorder explicitement ces droits via des options d'exécution (--allow-net et --allow-write). Cela permet aux utilisateurs d'utiliser des scripts utilitaires écrits par des inconnus (comme des linters) sans se poser de question.

Les fonctions natives du système ne doivent pas pouvoir être liées au moteur d'exécution JavaScript. Tout doit passer par un système de message (send et recv). Cela simplifie tout et permet de facilement auditer le système.


Le lien entre le processus deno et V8 est réalisé au moyen de protobuff.

deno est actuellement écrit en go, mais ce n'est pas forcément un choix définitif, il envisage également de le faire en Rust voire en C++.

L'idée générale est donc d'obtenir une sécurité d'exécution comparable à celle du navigateur, mais côté serveur. En effet dans votre navigateur vous exécutez quotidiennement du code dont vous ignorez totalement la source, mais comme celui-ci est exécuté dans un processus qui n'a accès à rien cela pose moins de problèmes de sécurité.

- simplifier le système de modules.

Aucune compatibilité recherchée avec node et le répertoire node_modules.

Les imports sont obligatoirement des fichiers sous forme d'URL (relatives ou absolues) :

Code javascript : Sélectionner tout
1
2
3
  
import { test } from "https://unpkg.com/deno_testing@0.0.5/testing.ts" 
import { log } from "./util.ts"

Le code externe est téléchargé à la première exécution et mis en cache. Il n'est téléchargé à nouveau que si l'utilisateur le demande explicitement via le flag --reload.

L'extension du fichier est obligatoire.

On peut "vendorer" ses dépendances en spécifiant manuellement un répertoire de cache différent. Par "vendorer", il veut dire utiliser une sorte de répertoire node_modules/ si on tient à avoir ses dépendances externes en local. Avant l'existence de node et des différents outils construits dessus, il était courant dans les projets web de créer un répertoire vendor/ pour y placer ses dépendances.

- TypeScript out of the box.

Ryan Dahl adore TypeScript. Il est donc supporté nativement sans besoin d'aucune configuration. Actuellement son prototype embarque TypeScript 2.8.

TypeScript n'étant qu'un superset de JavaScript, il est possible d'ignorer totalement TypeScript si on ne l'aime pas. Il suffit de ne pas l'utiliser.

Le support de TypeScript out of the box pose des problèmes de performances au démarrage du programme, probablement liés à la transpilation, mais il pense pouvoir y remédier dans un futur proche.

- Livrer un seul exécutable avec un minimum de dépendances.

Pardonne-moi cher lecteur, j'avoue humblement ne pas avoir compris du tout cette partie. Il liste les dépendances utilisées par son binaire deno via l'utilitaire ldd, mais la même commande appliquée à node donne à peu près le même résultat. Je ne vois donc pas bien en quoi il s'agit d'une amélioration, si quelqu'un de plus calé que moi sur le sujet lit la news je serais heureux de l'amender !

- Utiliser les avantages de 2018.

Utilisation d'un bundler pour convertir la source et ses dépendances en un livrable unique.

Actuellement les projets node sont généralement déployés et exécutés tels quels depuis leur source, il n'y a pas de phase de transformation en livrable contrairement aux projets frontend. Ryan Dahl semble apprécier le bundler Parcel.

Lors de l'écriture de Node.js, beaucoup des API (comme http) ont dû être écrites entièrement. Ce n'est plus nécessaire actuellement et il veut utiliser l'existant en Go, Rust ou C++ pour gérer cette partie de l'API.

- Buts divers.

Ryan Dahl pense qu'une promesse non gérée (une promesse sans clause catch) devrait tuer le processus immédiatement à l'exécution, ce qui n'est pas le cas dans node.

Il pense que l'API de deno devrait se conformer à l'API des navigateurs sans redéfinir son propre nommage. Le code produit serait donc beaucoup plus facilement compatible avec les navigateurs.

Sources :
- Vidéo de sa présentation à la JSConf 2018 de Berlin (slides).


- Vidéo de sa présentation de Node.js à la JSConf 2009 de Berlin (slides).


- Interview de Ryan Dahl par le podcast Mapping the Journey datée du 31 août 2017.
- "I hate almost all software", site de Ryan Dahl, octobre 2011.

Et vous ?

Êtes-vous d'accord avec l'analyse de Ryan Dahl à propos des problèmes de Node.js ?
Comptez-vous suivre l'évolution de son prototype ?
Pensez-vous que deno connaîtra le même destin que node ?

Une erreur dans cette actualité ? Signalez-nous-la !

Avatar de sitexw
Membre régulier https://www.developpez.com
Le 11/06/2018 à 14:21
Lourd ! Le projet Deno à l'air vraiment prometteur.
0  0