Migration du cœur de Duniter vers C++/TypeScript

Ok, Il y a également GNOME Builder qui a le vent en poupe.

Et serais-tu prêt à te mettre au JS de la même façon ?

Oui, tout autant.

J’arrive un peu après la bataille, mais je vais quand même donner mon opinion.
J’ai discuté récemment avec un développeur qui touche bien en node, et de notre discussion, il m’a semblé comprendre que l’une des difficultés de node est de monter en charge (en terme de nombre de programmeurs), donc cette discussion tombe plutôt bien. L’une des autres difficultés qu’a bien soulevé @cgeek est l’environnement de dev, pas vraiment facile en open-source. Et très franchement, même si l’approche non IDE est tentante (j’ai moi-même beaucoup travaillé avec vi et ça m’arrive encore souvent), il ne faut pas sous-estimer les avantages apportés par un IDE: débuggage intégré, références et doc en ligne, refactoring, complétion de code, ça fait gagner un temps fou et permet de se concentrer sur l’essentiel.
Alors le C++ est peut-être moins efficace, mais c’est une « valeur sûre », et surtout compris par une grande partie des programmeurs, assorti de pas mal d’outils libres. Si on s’en tient avec une grande rigueur, c’est de mon point de vue l’une des meilleures alternatives à considérer.
J’ai bien sûr entendu parler du Go mais je n’ai jamais pratiqué (seulement le jeu, pas sûr que ça aide beaucoup! :smiley: ). Là encore, je vois assez peu l’intérêt de passer dans un langage où il y a assez peu de programmeurs disponibles, la valeur ajoutée comparée à l’effort nécessaire me semble peut-être pas suffisante.
Au final, il me semble que le jour où il y a vraiment besoin, les programmeurs se mettront au langage s’il le faut. L’avantage d’utiliser un langage connu et typé est qu’on peut éviter de nombreuses « bourdes », qu’on fait tous quand on apprend un nouveau langage, surtout s’il n’y a pas trop de monde autour pour apporter son expertise dans des revues de code.
Bref, vous m’aurez compris, je suis plutôt C++. Même si depuis que je me suis mis à Java il y a plus de 15 ans je ne suis jamais retourné au C++… rien que le fait de s’affranchir de facto des fuites mémoire (sauf quand on programme avec les pieds) est un avantage suffisant, sans même parler des problématiques multi-plateformes. Maintenant, je suis conscient que java en terme open source, il y a mieux.

1 « J'aime »

Tout à fait d’ac. +1


Non, ne pas multiplier la complexité…


Exactement!
Pour ma part, je maitrise plutôt bien js et node, j’ai souvant mis le nez dans le code du coeur, j’ai pu lire… de là avoir une comprehenssion de l’ensemble de l’architecture, et surtout ce qui est lié à la blockchain m’a largué… Il manque des docs, diagrames et autres vues d’ensemble pour savoir par où commencer… Je me rend bien compte que c’est du taff pas passionnant, mais ça boosterait la participation des dev web, moins bas niveau justement !
(Alors oui je sais j’ai cas venir aux RML ! :slight_smile: Mais c’est trop loin pour moi à l’autre bout de la France… Sauf Montpellier, je devrait en être :wink: )

2 « J'aime »

Pourquoi ne pas simplement embrasser les derniéres syntaxes ecmascript 6 et 7 et même TypeScript qui permet le typage ? Lors de la transpilation, les erreurs sur les types sont remontés, une fois le code transpilé il n’y a plus de types, c’est du es3

1. Les outils

VS code (Licence MIT), nos cher amis de chez Microsoft on fait un effort: debuggage avec point d’arret sous NodeJS, suggestions sur les types persos, info des types des varaibles lors du survol, erreurs intégrés dans l’UI, etc…

Babel, pour transpiler ce qui a encore besoin de l’être, par ex les .js statiques des UIs, nettoyer, reformater comme on le souhaite.

electron, pour les UIs, c’est un NW.js en mieux, permet de séparer le code web du code nodejs (différents threads), avec une énorme communauté puisque c’est un projet des gars de github, et peux permettre d’être vu (donc aflux de devs) sur leur page d’apps

2. Le typage statique

Syntaxe de classes, propriétés privées, statiques, décorateurs de membres, propriétés calculées, immport/export etc…
Le tout est transpilé si et seulement si il n’y pas d’erreur de types, et le code final sans type est assuré de fonctionner.
C’est le futur javascript, les runtime acceptent de plus en plus l’es6 et 7

3. Les contributeurs potentiels connaissent plutôt C++

4. La crédibilité

Il faut dire que c’est fait en ecmasript 6 ou TypeScript, hop ça fait plus pro, seuls les “personnes qui cherchent à comprendre le fond et à maîtriser les détails” connaissent l’ecma et les specifications en early stage, le TypeScript, le fonctionnement d’une machine virtuelle js ou encore comment marche le GarbageCollector… Ce sont des afficionados de languages orientés objet, …

La communauté javascript++ grandi d’heure en heure ! :slight_smile:

Et puis c’est la classe d’être LE projet de blockchain fait en majorité en full web !!

5. La vitesse d’exécution

Là je sais pas trop… Il parait que Node est un champion du multi-threading, clustering et micro-tasking…

4 « J'aime »

Duniter est déjà en ECMAScript 6, encore que certaines subtilités de syntaxe ne seront déployées qu’avec Node.js 8, tout juste sorti. J’attends un peu de stabilité pour taper dans cette version de Node, qui demandera des ajustements de build pour Duniter.

Pour TypeScript, je dois encore faire quelques tests avec Duniter. Notamment je dois pouvoir déboguer aisément le JavaScript généré par TypeScript, le must serait de déboguer directement le TS grâce aux sources maps. Mais dans le principe, je crois que je vais basculer petit à petit Duniter dessus. Surtout que cela peut se faire progressivement, avec la compatibilité TS <-> JS.

Ça m’a l’air prometteur en effet ! Voilà peut-être un super outil libre :slight_smile: Je l’essaye ce jour sur mon Ubuntu. Merci du tip !

Je vais donc réétudier son cas :slight_smile:

En fait on a pas vraiment de contrainte à ce niveau là, vu qu’on livre Node.js / Nw.js dans Duniter. Donc on peut mettre la tout dernière mouture de JS si on veut.

Tout ce qui requiert de l’utilisation intense de CPU (comme la signature numérique ou la preuve de travail), Node.js est juste mauvais. Je le fais en C++ via les addons Node.js, c’est largement plus rapide (un ordre 10 ou 100).

Bon, aujourd’hui ce sera journée R&D :slight_smile:

Avec Babel, tu peux transpiler du code non supporté vers du code supporté… En pratique ça permet d’utiliser toutes les syntaxes avancés de es7+ et TypeScript dès maintenant, tout en faisant marcher sur telle ou telle version de node/browser. Le principe de Babel et les spécification ecmascript, c’est que toute nouvelle syntaxe doit être transposable en bon vieux js (es3) par un transpiler…
C’est modulaire, donc tu peut par exemple juste effacer les types, ou bien ne transformer que les functions asynchrones en generator et laisser la syntaxe classe…

Oui, Babel et tsc (TypeScript) générent des sources maps… Mais c’est valable que pour les navigateur qui ont un debugger qui lit les sourcemaps! Je ne pense pas que le runtime nodejs lui sache lire des sourcemaps.
Par contre VS Code lui (qui est en fait une app electron) sait faire du debug nodejs avec point d’arrêt et pas à pas …
Dans le cas d’un serveur DUniter qui serait un runtime electron, il y’a le devtools de webkit et donc lecture des sourcemaps, pas à pas etc (seul petit hic: il faut ouvrir le devtools au lancement de l’appi sinon on ne passera pas sur les breakpoints).


Un grand intérêt du TypeScript, c’est que les types ne sont pas obligatoires, il n’y a donc rien à faire pour passer le code actuel dans tsc (transpiler TypeScript), ça marchera mais bien sur sans aucun check de type. Il peut y avoir des types et classes que dans certains modules.

N’hésites pas à me poser des questions, je connais bien les différences vu que j’ai commencé par NW.js (formely nodewebkit) pour ça simplicité et pour le mix de runtime justement, et puis je suis passé sur electron dès qu’il m’a fallu des fonctionnalité plus poussés, nottament la gestion des process, faire des extensions au devtools et la séparation du code nodejs / webkit qui est mieux au final sur les gros projet…
(Je penses par exemple qui est assez facile d’intégrer Cesium dans une fenêtre ouverte par le coeur)
Et puis au final la communauté electron avance tellement plus vite !!!
Avoir la possibilité d’un devtools qui fait éditeur de css/js en live avec enregistrement auto, voire transpilation, c’est top pour les UIs !

Oui je connais déjà Babel, mais j’ai trouvé son utilisation assez délicate, parfois pour un apport assez minime au niveau syntaxe. Par exemple le async/await, ce n’est pas vraiment primordial avec Node.js 6 + des librairies comme co.

Par contre TypeScript apporte vraiment un gros plus.

Je viens de tester avec VS Code et WebStorm, les deux savent parfaitement déboguer le TS grâce aux source maps, même avec Node.js. C’est vraiment est très bon point ! Je dois vérifier encore 2-3 choses, mais je crois que je vais basculer sur VS Code plutôt que WebStorm. D’abord parce qu’il fonctionne très très bien, et en plus est sous licence libre et est très léger.

Duniter est principalement une application Node.js, pas une application Nw.js / Electron. Ce dernier ne fait qu’enrober Duniter afin d’offrir une expérience « application de bureau ». Donc il faut principalement pouvoir déboguer en exécution Node.js. Ce qui est le cas visiblement :slight_smile:

Oui c’est un très bon point. La migration peut être progressive.

Qu’entends-tu par là ?

Dans mon cas, Duniter est une application Node.js qui fait notamment tourner la WebUI sur un serveur web sur localhost:9220, et Nw.js va la chercher comme un navigateur web. C’est ce type de séparation dont tu parles ?

1 « J'aime »

Voir section 1 içi

Tu peut faire tourner duniter avec electron, sans fenêtre tu aura pareil que nodejs. Et si tu doit ouvrir une fenêtre (comme la webui) c’est le code coté nodejs qui ouvre la fenêtre, qui affiche localhost:9220 ou bien un html static, ou bien un site distant.
La communication entre process node et process webkit ce fait par messaging inter-process (très bien intégré, tu peut avoir un mirroir d’object entre les process, ou bien envoyer un message à toutes les fenetres).
En gros tu mixe pas le code nodejs et web front… plutôt tu réutilise ton code nodejs, en rajoutant la possibilité d’ouvrir des fenêtre avec le content web qui proviens d’ailleurs, d’un module express par ex, ou un service web d’un autre process.
Les process node et webkit son séparés (sandboxing), mais c’est le process nodejs qui orchestre le tout.
Tu peux par exemple ouvrir une fenêtre webui, une autre cesium, et même par exemple ouvrir une fenetre d’alerte intrusion lors d’un event du coeur… ou encore donner la possibilité aux noeud spé d’avoir des fenetre d’UI…
Dans le cas d’un serveur headless (sans systeme de fenêtre, juste la ligne de commande), le code devrait marcher avec nodejs seulement, modulo quelques IF savoir si on est ds un electron ou un nodejs pour la partie UI qui ne fera rien.

Pour info : je commence dès à présent une tentative de migration en douceur vers TypeScript, sur une branche Git à part « ts ».

Pour le moment les essais sont concluants : la rétro-compatibilité est assurée en termes d’interaction TS/JS, et aussi le compilateur TS m’envoie régulièrement balader, signe que je fait bel et bien des erreurs de code dont je ne me rends pas compte.

Je vais tenter d’aller le plus loin possible dans cette migration, pour voir à quel point cela devient profitable pour Duniter et ses développeurs.

6 « J'aime »

Voilà, j’ai fait un 1er commit : https://github.com/duniter/duniter/commits/ts

Constat#1

Je n’ai touché qu’à une partie du code, et pourtant je note des gains significatifs de performance. Ce n’était pas prévu.

Constat#2

Je peux désormais faire bénéficier le code de la syntaxe async/await. Ainsi le code peut passer de ceci :

class DuniterBlockchain {

  methodeA() {
    const that = this
    return co(function*() {
      yield that.operationAsynchrone1()
      yield that.operationAsynchrone2()
      yield that.operationAsynchrone3()
    })
  }
}

à cela :

class DuniterBlockchain {

  async methodeB() {
    await this.operationAsynchrone1()
    await this.operationAsynchrone2()
    await this.operationAsynchrone3()
  }
}

Constat#3

Le compilateur TS me hurle régulièrement dessus, et me fait remarquer mes erreurs. C’est très structurant, on se sent beaucoup plus en sécurité pour développer, l’imagination est libérée.

Constat#4

L’éditeur de code lui aussi est libéré, je note qu’il va plus vite (il perd certainement moins de temps à deviner la nature de telle ou telle variable), me propose une auto-complétion plus appropriée et m’aide même à générer du code très rapidement, comme ce peut être le cas en Java.

Il devient notamment plus efficace pour renommer des variables à la volée, dans tous les fichiers et de façon contextuelle (pas un bête chercher/remplacer, non, c’est bien la variable qui est renommée, pas juste le mot).

Constat#5

Je n’ai pas encore repéré de bug dans Duniter ! :smiley: Par contre je me repère mieux dans le code et remarque des choses vraiment alambiquées parfois.

Alors on va voir la suite, mais je suis dores et déjà conquis par le côté très structurant du TypeScript : les nouveaux développeurs auront moins l’appréhension de laisser des bugs.

10 « J'aime »

Je viens d’installer VScode.
Ça me semble être un bon outil pour développer en TypeScript.

2 « J'aime »

Idem je viens de faire mumuse avec vscode et c’est trop bien :grinning:
Moi qui débugais à coup de console.log() je vais enfin pouvoir utiliser un vrai débogueur nodejs sur un outil libre, et l’intégration de git aussi c’est trop bien merci @devingfx pour cette découverte :slight_smile:

2 « J'aime »

Arg vous me faites baver. Va falloir que j’installe ça aussi… :slight_smile:

2 « J'aime »

Ça fonctionne vraiment très bien ! Productivité garantie ! (cela dit j’ai l’inertie de mon WebStorm avec lequel je suis vraiment très efficace … mais la frontière est vraiment mince ! et en plus VSCode est libre …)

1 « J'aime »

Comment gérer l’étape de transcompilation ?
Un simple yarn upgrade s’occupe de ça ?

Juste un yarn depuis la branche ts.

Remarque de la FSF sur VSC

3 « J'aime »