"Finalisation du DSL"
Quentin Ducasse.
-Bonjour à tous.
On se retrouve pour cette partie 3
du Redo de la semaine 3.
Je commence par une précision
sur ce que j'ai fait dans la dernière vidéo.
J'avais bien prévenu dans la première vidéo
que pour tester un phénomène aléatoire,
il fallait passer par la répétition,
que j'ai oubliée dans le test "roll" de la vidéo précédente.
Donc, je vous conseille évidemment de rajouter une répétition
sur l'assertion de fin, ce qu'on peut trouver ici.
C'est une erreur que j'ai faite tout à l'heure.
Maintenant, on va s'intéresser
à faire fonctionner le langage qu'on aimerait avoir,
"1 D4 + 2 D6", on aimerait que ça nous renvoie une poignée de dés
qui contient un dé 4 et deux dés 6.
On peut remarquer qu'on va devoir définir une méthode sur les entiers,
parce que la méthode "D6" va s'appliquer sur "2"
et la méthode "D4" va s'appliquer sur "1".
On va dans la classe "entiers".
Je tape "Integer", je le surligne et je presse Cmd+B.
Un System Browser s'ouvre avec les entiers
et on va pouvoir définir notre méthode ici.
Donc, on va commencer par "D20".
On va faire comme tout à l'heure, on crée une poignée de dés.
"handle := DieHandle new." Voilà.
Maintenant, on va devoir ajouter à cette poignée
autant de dés 20 que l'entier qui peut être écrit avant.
Par exemple, si j'ai l'expression "2 D20",
je veux ajouter deux dés 20 à ma poignée de dés.
Comment fait-on ça ? On va dire :
"self timesRepeat: [ handle addDie: (Die withFaces: 20) ]."
Qu'est-ce que ça va faire ?
Ça va répéter autant de fois que l'entier sur lequel on l'applique
l'ajout de dés à 20 faces.
Et on va rendre la poignée de dés.
On va sauvegarder ça. OK.
On a un bouton qui n'est pas présent, qui est ici.
"extension".
Ça veut dire que plutôt que de venir polluer le package "Numbers"
qui fait partie de "Kernel", un package important du système,
avec notre méthode "D20", on va la replacer dans notre package.
On peut faire ça de plusieurs manières : on fait clic droit,
on va dans les Refactorings et on fait "Move to package",
ou on peut cocher la case "extension", ici,
rechercher notre package "Dice", cliquer dessus, OK.
On peut voir que la méthode est maintenant écrite en gris.
Si on se dirige dans l'autre System Browser,
on peut voir la classe "Integer" qui est apparue,
avec la méthode "D20".
C'est exactement ce qu'on voulait.
On va écrire un test là-dessus
et on va l'appeler "testSimpleCreation".
On va vérifier que "self assert: 2 D20 diceNumber equals: 2".
Ça va vérifier que la méthode "D20" appliquée à "2"
va bien créer une poignée de dés qui contient deux dés.
On sauvegarde.
On lance le test, il est vert. C'est très bien.
Maintenant, on va pouvoir créer les autres méthodes,
"D10", "D4", "D6".
On ne va pas récrire tout ça à chaque fois.
On va écrire une méthode plus générale
qu'on va appeler "D: aNumber".
Ce que ça va faire, c'est exactement ça,
sauf qu'ici, on va avoir le fameux nombre qu'on lui passe,
"aNumber".
Avec ça, on va pouvoir faire le dé 6, par exemple.
Au lieu de devoir récrire tout ceci,
on va simplement rendre : "^ self D: 6".
On peut sauvegarder.
Maintenant, le dé 4 dont on va avoir besoin, "D4".
On va rajouter le dé 10 et le dé 12.
On aura les dés les plus intéressants.
On va même pouvoir remplacer notre dé 20
par notre méthode beaucoup plus simple.
"^ self D: 20".
On peut sauvegarder. C'est bien, on a tout ce qu'il faut.
Mais on ne peut toujours pas exécuter cette expression.
On peut exécuter cette partie qui va nous rendre une poignée de dés,
cette partie qui va nous rendre une autre poignée de dés,
mais on ne peut pas exécuter l'intégralité,
parce qu'on n'a pas défini la méthode "+"
entre les deux poignées de dés.
Pour ce faire, on va aller dans la classe "DieHandle"
et on va définir le "+" : "aDieHandle".
Que va-t-il se passer, avec la méthode "+" ?
Ce qu'on veut, c'est avoir une poignée de dés finale
dont la collection "dice"
va correspondre à la combinaison des deux collections.
On va avoir notre "handle",
qu'on va pouvoir définir tout de suite
comme étant une nouvelle poignée de dés.
Maintenant, on va itérer à la fois sur la collection de dés de "self"
et sur celle de l'argument.
On va commencer par "self" : "self dice do:"...
On va itérer sur chaque élément. "[ each | handle addDie: each ]."
Qu'est-ce que cette méthode va faire ?
On va itérer sur la collection de dés de la poignée qui reçoit ce message
et on va ajouter chaque dé de la collection
à la poignée résultat "handle".
Ensuite, on va faire la même chose sur l'argument qui est passé
"aDieHandle dice do: [ :each | handle addDie: each ]."
Et à la fin, on renvoie notre poignée de dés.
On peut sauvegarder ça.
Voilà. On va écrire un test là-dessus.
Donc, on va vérifier que "(1D4 + 2D20) diceNumber equals: 3"
et on va l'appeler "testSumming".
Cmd+S. Je l'exécute.
On peut voir que le test n'a pas fonctionné.
Par contre, ce n'est pas normal, on va devoir regarder pourquoi.
Ce "DieHandle class", c'est une erreur,
parce qu'on a oublié "new", ici,
donc on s'attaquait à la classe "DieHandle" directement.
C'était une erreur. On sauvegarde.
"Yes". "Proceed". Notre test est vert.
On peut réexécuter tous les tests. On voit que tous nos tests passent.
On voit que si on inspecte ça,
grâce à la méthode qu'on a définie qui nous donne un plus joli rendu,
on peut voir qu'on a bien notre poignée de dés
avec un dé 4, deux dés 6.
Maintenant, si on veut lancer tous ces dés,
on peut appliquer la méthode "roll" simplement sur cette poignée de dés.
"Roll". J'imprime. 13, 5, 9.
On va avoir un résultat entre 3 et...
Tout simplement, on peut regarder.
Il suffit de lancer la méthode "maxValue".
Entre 3 et 16.
Donc, on peut "roll" encore et vérifier qu'on ne dépasse pas 16.
On peut voir que notre méthode d'addition a l'air de fonctionner.
Notre méthode de roll aussi.
Et on a développé un petit langage qui nous permet de lancer des dés
et de réussir notre partie de "Donjons et Dragons".
C'est la fin de ce Redo de la semaine 3.
Et pour finir proprement,
on va aller sauvegarder notre package "Dice".
On se dirige dans Iceberg.
On a toujours le "Uncommitted changes" qui est apparent.
On clique dessus. Commit.
Et on va mettre :
"Added die creation from integers and operations on DieHandle".
Commit.
Et voilà, c'est donc la fin de ce Redo de la semaine 3.