Comment écrire un protocole de manière précise et compréhensible par un humain?

Personnellement je trouve qu’un DSL (Domain Specific Language) est bien plus confortable. L’IDE peut nous avertir dès la frappe si la syntaxe est correcte ou non, et on dispose de tous les avantages de navigation / édition du code que celui de notre code source.

Exemple de DSL :

givenFakeBlockchain()
  .withInitialWoT(alice, bob)
  .certificationAt(1, bob, alice)
.when()
  .block(1)
  .then()
     .assertCertificationExists(bob, alice);

Tandis que pour Cucumber on peut écrire un test grammaticalement incorrect, tant qu’on ne lance pas on n’est pas averti. Cela oblige à bien connaître la grammaire développée, là où une connaissance de surface suffit pour le DSL (guidage par l’IDE via l’autocomplétion / erreurs détectées à l’analyse du code).

En revanche, le coût côté DSL est de devoir le développer, ce qui est un peu plus fastidieux au début.

2 Likes

Dans les 1ères versions du protocole, j’avais écrit dans un langage humain. Le problème était l’ambiguïté.

Là, le protocole n’est plus, ou sinon beaucoup moins, ambigu. Par contre des commentaires seraient les bienvenus, c’est le cas à quelques endroits. Exemple :

Functionally: a user has only 1 status change allowed per block.

Quant à dire que les tests fonctionnels (Cucumber) rendront le protocole plus lisible par les humains, je n’y crois pas. Tout au mieux permettront-ils de mieux l’illustrer, mais ils ne remplaceront pas une bonne vieille définition façon commentaire en langage humain.

Je disais ça en rigolant, mais je n’ai pas trouvé de réponse à ma question initiale : pourquoi y a-t-il des identités ayant plus de 100 certifications émises ? Il y a probablement un problème dans DataJune mais je n’ai pas compris où. Est-ce que les certifications vers des identités révoquées comptent dans le stock ?

1 Like

Je suis d’accord, je préférerais appeler directement les fonctions de test plutôt que de passer par des regex. J’ai d’ailleurs eu un cas d’ambiguïté de regex avec cucumber.

Bien que cette discussion ait émergé suite à une plaisanterie, je pense qu’il est important de la traiter. La question est donc :

Comment décrire un protocole en respectant les critères suivants :

  • pas d’ambiguïté
  • facilement compréhensible par un humain

Pour moi, la version actuelle de la RFC est un cauchemar à lire, je n’arrive pas à y trouver des réponses à mes questions. J’ai à chaque fois fini par abandonner. Si je suis un cas isolé, ce point ne compte pas.

Avec Duniter v2, ce qui se rapproche le plus de spécifications sont les tests cucumber, mais ils souffrent du problème d’une grammaire dédiée, dans l’implémentation de laquelle peut se nicher des erreur :

À propos d’un DSL

Comment pourrait-on apporter ça à Duniter v2 ?

Ah désolé, je n’avais pas relevé :slight_smile:

Je vais répondre sur l’autre fil.

Je n’ai pas mis d’énergie à faciliter sa lecture, même si j’avais commencé avec les commentaires “Functionally:” que j’ai fini par arrêter afin d’avancer plus vite. Si j’en avais mis sur toutes les règles, je pense que ç’aurait été plus facile à lire.

Néanmoins il y a aussi des effets induits de règles sur d’autres, typiquement du genre qui te fait poser la question “Est-ce que les certifications vers des identités révoquées comptent dans le stock ?”.

Pour ces effets, je ne sais pas si j’aurais écris un commentaire dans le protocole car, à ce jour, je n’ai pas de moyen de lister exhaustivement ces effets induits. Éventuellement tu aurais pu y répondre tout seul en te référant aux commentaires des règles et faisant le lien toi-même, mais bon ce serait mieux que l’on trouve une méthode permettant de les révéler automatiquement.

Je dis ça car, au-delà de Duniter v1, j’aimerais bien que l’on dispose d’un tel système pour Duniter v2.

Car autant je pense pouvoir contribuer à Duniter v2, autant je ne suis pas sûr que ce soit une bonne idée que je fonce à nouveau tête dans le guidon alors que j’estime faire partie de ceux qui peuvent faciliter le terrain pour les contributeurs. Et plus encore, si je peux lister exhaustivement les règles et leurs effets alors je suis aussi capable d’indiquer si l’on couvre chaque cas par au moins un test. Ce qui serait vraiment un bel apport pour la qualité du code (je trouve).

Non je ne pense pas :slight_smile: moi-même quand j’y retourne parfois, j’ai du mal à m’y retrouver. Et Eloïs irait certainement dans ton sens aussi.

Écrire un DSL ? C’est assez simple en fait. Je saurais le faire, j’en ai déjà écrit un de zéro. Par contre je sais le faire d’au moins 2 façons en Java, et avec Rust il y a sûrement moyen de faire d’une 3ème façon plus évoluée qu’en Java. Faudrait que je creuse :slight_smile:

Pour décrire rapidement à quoi ressemble un DSL tel que je le connais, celui-ci suit la philosophie Given-When-Then (point commun avec Cucumber) :

  • Given : étape où l’on définit les données du test
  • When : étape où l’on exécute des scénarios
  • Then : assertions

Par contre, le DSL a ceci de spécifique qu’il est une unique instruction, plus précisément c’est une expression où chaque fonction renvoie un nouveau type correspondant à un chemin du DSL. C’est grâce à cette mécanique que le chemin est balisé par le compilateur (et que l’IDE en tire parti).

1 Like

Je pense qu’il est tout à fait possible de faire un système de test très simple en Rust, qui utilise directement les fonctions qu’on a déjà définies pour cucumber (la partie parsage en moins).

Par exemple :

Test::new()
    .given_balance(Alice, G1(42))
    .when_transfer(Alice, Bob, Ud(3))
    .then_balance(Alice, CG1(1200)) // centi-G1
    .then_balance(Bob, G1(30))
3 Likes

Oui c’est exactement ça que fait le DSL de toute façon ! Ce code n’est pas perdu. Seul celui de parsing est à jeter si cucumber n’est pas utilisé.

1 Like

Le but des tests cucumber n’est pas et n’a jamais été de servir de spécification, alors n’allez pas trop vite en besogne svp, je ne compte pas les supprimer.

Le but des tests cucumber et de permettre l’écriture de scénario pur des gens qui ne sont pas développeurs, et qui n’ont pas forcément d’IDE, ça pourrait se faire directement dans l’interface web de gitlab, je travaille justement à modifier le workflow git de manière a ce que ça devienne possible.

@tuxmain et @cgeek si vous voulez ajouter des tests end2end directement en Rust façon DSL, c’est une contribution bienvenue, mais ça viendra en plus des tests cucumber, pas en remplacement. De toute façon il n’y a jamais trop de tests :slight_smile:

Quant aux spécifications, ça n’a rien à voir avec les tests, et doit faire l’objet de document·s à part.
Si quelqu’un veut se lancer dans des spécifications qui décrivent le comportement de l’existant, c’est une contribution bienvenue également, même si ça me semble encore beaucoup trop tôt, car une grosse partie du protocole va encore fortement changer, notamment toute la partie sur les frais et quotas, ainsi que la priorisation des transactions, plusieurs gros sujets qui impactent complètement le workflow d’une transaction. Sans parler de la gouvernance onchain qui reste à définir, et bien d’autres choses.

Là en priorité j’ai besoin d’aide sur les nombreuses issues déjà définie sur le gitlab: Issues · nodes / rust / Duniter v2S · GitLab

Je pense qu’on doit d’abord avancer sur l’implémentation, expérimenter sur la ĞDev, et faire plusieurs cycles d’itérations pour trouver qu’est-ce qu’on veut comme comportement. En tout cas c’est à ça que je vais consacrer le peu de temps libre que je peux dégager pour la Ğ1, après chacun reste libre de travailler sur ce qu’il veut :slight_smile:

1 Like

Oui c’est sûr, on peut avoir des test cucumber et DSL en parallèle, pas de soucis.

Ceci dit les testeurs non-développeurs qui écriraient des tests cucumber vont devoir apprendre une grammaire et l’utilisation d’un outil (fût-ce GitLab), alors ouvrir un IDE n’est pas une marche beaucoup plus difficile. En tout cas pour avoir bossé avec un testeur non-développeur, celui-ci ouvrait quand même un Eclipse pour coder ses tests et les lancer.

Bref, oui, les deux approches restent compatibles.

2 Likes

Personnellement je trouve qu’il est plus difficile de travailler avec des regex qu’avec la syntaxe fonctionnelle de Rust, qui est aussi mieux supportée par les éditeurs (avec coloration syntaxique et formatage).

Le piège de ces langages proches du « langage naturel » est qu’on nous fait croire qu’on peut écrire en anglais, mais non, un espace en trop ou deux regex en conflit et c’est mort, et dur à débugger, parce que l’interpréteur n’est pas capable de suggérer des corrections dans ce langage.

Si on veut que des non-développeurs (qui ne lisent pas de regex) puissent écrire des tests, il faudrait aussi qu’on documente tous les given/when/then disponibles. Voire qu’on ajoute des regex en français, car certains contributeurs ne sont pas à l’aise en anglais.

1 Like

Je vois un autre très gros avantage des tests cucumber par rapport aux tests en rust, c’est la possibilité de modifier le scénario de test sans recompiler.

Le long temps de compilation du Rust ne me gêne pas quand je travaille sur le code de prod, mais quand je travaille sur les tests je trouve ça très gênant, car c’est généralement là que j’ai besoin de retours très rapides sur mes modifications.

C’est pour ça que personnellement je ne suis pas fan de tests end2end en rust, l’idéal serait d’avoir des tests end2end en typescript, en utilisant la lib polkadot/api.

C’est ce que je préconise, et que j’avais commencé à faire d’ailleurs :slight_smile:

2 Likes