Dans cette vidéo, nous allons vous montrer comment on va
créer un package, une classe, décrire des tests.
La première chose à faire déjà, c'est commencer à ouvrir le système Browser.
Le système Browser, ça nous permet de browser des packages.
Là, il y a des packages.
La première chose à faire, c'est qu'on va créer un package.
On va faire "Add package" "MyCounter".
Comme il y a beaucoup de packages et qu'on ne veut pas
les voir, c'est une bonne chose de filtrer tout ça.
On a notre package "MyCounter".
Et là, on va définir une classe qu'on va appeler
"Counter" et elle a une variable d'instance count.
Le petit icône orange nous indique que le code n'est pas sauvé.
Là, on va compiler le code avec la fonction "Accept".
Et là, j'ai la classe "Counter" qui a été compilée.
Le système regarde un petit peu et nous dit qu'il y a des
commentaires de qualité, on verra ça plus tard pour le moment on s'en fiche.
Il y a un point d'exclamation rouge parce qu'on n'a pas
écrit de commentaire. Donc, on va écrire un premier
commentaire :
"I'ma simple counter".
On va mettre un petit exemple pour que lecteur comprenne
comment ça va fonctionner: Counter new,
Counter increment, Counter
count. Là, ça devrait être égal à 2.
Encore une fois, le texte n'est pas sauvé et on va le compiler.
Il est sauvegardé. On n'a plus de counter.
Maintenant, on va définir des accesseurs.
Les accesseurs, on les met généralement dans le protocole Accessing.
On va faire "count rend count".
Et de la même manière, on va faire
aNumber, on va faire un Setter.
Vous avez vu, j'ai modifié la méthode count.
Là, vous pouvez penser qu'elle est perdue mais non parce
qu'à chaque fois que je change une méthode avec un nom
différent, il en crée une nouvelle.
Là, je compile une nouvelle méthode, j'ai count.
Maintenant, on peut vraiment tester et faire notre premier petit programme.
Là, je prends Playground.
Je vais créer un counter. On se met sur une autre
ligne. Je vais lui mettre une valeur
: C count 7. Si je demande sa valeur, qu'est-ce que ça
doit me rendre ? Ça va me rendre 7.
Maintenant ce qu'on voudrait faire, c'est vraiment écrire
ça sous forme d'un test parce que là, on ne peut pas l'exécuter
et on aimerait l'exécuter automatiquement.
On va créer une classe de test.
Comment on crée une classe de test dans Pharo?
On change la super classe, on dit que ça hérite de
TestCase et on va définir une classe de
test qu'on appelle CounterTest.
Maintenant ce que je vais faire je vais la compiler.
J'ai une nouvelle classe CounterTest dans mon système.
Je vais définir une nouvelle méthode, je vais ajouter un
protocole qui s'appelle tests.
Là, je vais pouvoir définir une nouvelle méthode.
Les méthodes de tests doivent commencer par "test"
toujours et être dans une classe qui hérite de TestCase.
On va l'appeler "testCounterisSetAndRead"
par exemple. On l'a pratiquement notre test, on a déjà
presque tout écrit.
On va l'indenter un peu plus joliment.
Je crée mon counter.
Et maintenant, je vais faire "self assert
equals 7". Cette phrase-là est
exactement équivalente à "self assert C count égale 7".
C'est que c'est plus pratique, quand on fait une erreur
le retour est beaucoup plus intelligent quand on utilise la première forme.
Là, on va compiler.
Maintenant, je vais pouvoir faire exécuter mon test, mon
test est vert. Quand on a un test et qu'il est vert,
c'est un bon moment pour sauver sa production, son code.
Dans Pharo, vous allez pouvoir sauver l'image.
Là, c'est-ce que je fais, je vais sauver l'image mais ce
n'est pas satisfaisant l'image.
Je voudrais vous montrer comment vous allez sauver du
code dans un système de version.
Là, comme je ne sais pas si vous allez avoir accès à
Internet, je vais le faire dans mon cache local.
Vous voyez, j'ai ce dossier-là qui pointe
sur tous les packages, sur lesquels je peux
travailler, que j'ai chargés ou pas.
Là, ce que nous montre le système, c'est que j'ai
plusieurs packages qui ont des modifications qui n'ont pas été sauvegardées.
On s'en fiche des 2 premières, mais nous, on voit que
MyPackage a une étoile. Ça veut dire que j'ai du code
dans l'image qui n'a pas été sauvé.
Là c'est ce que je vais faire, je vais faire Save, je
vais dire voila je choisis le repository.
Je vais faire save.
Là, je vais marquer "first version with accessors and a
green test". Là,
j'accepte. Là, il m'a sauvé un package.
On va aller vérifier.
Je peux ouvrir ce dossier et si je regarde, il contient
plein de packages qui ont été chargés par le système.
Mais en particulier, si je filtre là, je retrouve bien
mon package avec ses versions.
Je vous conseille à chaque fois que vous avez ajouté une
fonctionnalité, c'est ce qu'on va faire systématiquement, de sauvegarder.
Maintenant ce qu'on va faire, on va d'abord définir un
test avant de l'implémenter.
On va écrire un test pour qu'est-ce que c'est que l'incrément
d'un
counter. "TestIncrement" qu'est-ce qu'on aimerait avoir?
On aimerait lui dire "Je
crée un counter,
je vais lui mettre une valeur par défaut,
puis je vais incrémenter 2 fois ce counter.
" Qu'est-ce que je dois vérifier ?
Je dois vérifier que le counter en question
a la bonne valeur.
Je compile. Mon test
est bien rouge puisque je n'ai pas implémenté counter,
les opérations dans compteur incrémentent et décrémentent.
Je vais ajouter "operations increment".
Qu'est-ce qu'on va faire ?
On va faire "self count 2: self count +
1". Si on utilise systématiquement les accesseurs en
interne ou pas, ça dépend, c'est une question de style.
De la même manière vu que c'est très proche, on va
définir "decrement".
Vous voyez que sur increment il y a un test, donc je peux
l'exécuter et mon test est vert.
Donc, j'ai bien 2 tests qui fonctionnent.
Si je vais dans la classe test, tous mes tests sont verts.
Qu'est-ce que je vais faire ?
Je sauvegarde. Je vais faire une nouvelle sauvegarde.
Je vais dire "Adding increment and decrement".
Là maintenant si je regarde, j'ai bien 2 versions
de mes packages.
On va écrire un test pour "decrement"
parce qu'il n'y a pas de raison.
"Decrement", par exemple je
pourrais mettre une valeur à 2 si j'en ai envie et je
décrémente 2 fois. Je dois obtenir 0.
Mon test est vert donc
je vais sauver.
Maintenant ce qu'on aimerait avoir, c'est que si je
regarde et que je fais "Counter new" et que je fais
"Print it", ça m'affiche un counter et je ne sais pas sa
valeur, donc ce n'est pas pratique.
Ce qu'on aimerait c'est modifier ce comportement.
Pour cela ce qu'on va faire on va ajouter une méthode qui
s'appelle "PrintOn", dans le protocole Printing.
Print on, c'est une méthode qui est appelée par le
système à chaque fois que l'on fait PrintStream.
On a comme argument aStream.
Qu'est-ce qu'on va faire ?
On va dire qu'on aimerait avoir un counter.
Là typiquement, j'invoque les fonctions du dessus.
Maintenant ce que je vais faire, j'aimerais
ajouter un petit
texte
par exemple "with value" et puis "self count".
Je fais ça parce que le counter c'est un nombre, donc je
dois obtenir sa représentation textuelle.
Je vais faire "cr".
Je compile.
Le système me dit que je pourrais faire mieux mais bon ce n'est pas grave.
Pour le moment on s'en fiche.
Je peux faire c'est "Counter new".
Je regarde, il me dit que c'est un counter avec comme valeur nil.
C'est normal puisque je ne l'ai pas encore initialisé.
Maintenant, on va ajouter un support à l'initialisation.
On va commencer par écrire un test et pour faire cela
je vais dire, je veux que les valeurs à la création
soient 0.
Qu'est-ce que je vais faire ?
Je vais faire "self assert".
Je vais m'assurer que "Counter new
count = 0". Là,
qu'est-ce qu'on voit ?
Mon test est faux. Pourquoi ?
Parce que si je fais ça, j'obtiens nil.
Vu que c'est une classe et que je n'accède pas à des
variables d'instance de la classe CounterTest, je peux
sélectionner l'expression et l'exécuter directement.
Maintenant, une fois que j'ai ce test qui ne passe pas,
qu'est-ce que je vais faire ?
Je vais ajouter une méthode initialize dans le protocole initialisation.
Et là qu'est-ce que je vais faire ?
Je vais faire "super initialize", au cas où, et je vais
dire "count 2 points = 0".
Cette méthode-là est invoquée à chaque fois que j'ajoute la méthode "new".
Maintenant je peux regarder avec mes tests, c'est vert.
De la même manière, si je faisais "count", j'obtiens bien 0.
Encore une fois, là on va sauvegarder: ""added printOn"
"added initialize + tests".
Donc ce qu'on peut maintenant qui est intéressant c'est
que je peux voir tout mon historique.
Je peux aussi voir et naviguer dans cet historique.
Si je clique sur "version" je peux voir la différence entre 2 systèmes.
Les changements entre la version 3 et la version 4, c'est
"initialize" "printOn" et le Test.
Si je veux la différence entre la version
2 et la version 4, j'ai tous ces
changements.
Maintenant il me reste une chose à faire, j'aimerais bien
changer un petit peu la manière dont les objets sont créés.
Je vais commencer par créer un test pour vous expliciter
ce que j'ai envie d'obtenir. Je vais définir un test
que je vais appeler "AlternateClassCreation".
Qu'est-ce qu'on a envie d'avoir ?
On va dire, moi ce que je veux, je veux garantir quoi...
que Counter withValue: 19
Si je fais increment dessus
et que je demande sa valeur, ça doit me rendre 20,
d'accord.
On va mettre une parenthèse ici, c'est mieux,voilà.
Donc, encore une fois, le test ne passe pas,
et l'assistant me dit : "tu envoies un message qui n'est pas connu".
Ce qu'il faut voir c'est que le message withValue
est envoyé non plus à un objet mais à une classe.
Donc ça veut dire que je vais devoir définir ce message là
sur la classe. Donc je sélectionne la classe.
Maintenant je passe au niveau classe et je vais ajouter
un protocole qui s'appelle instance creation
withValue: aNumber Alors qu'est-ce que je dois faire ?
La première des choses à faire ça va être,
je vais créer un counter, une variable counter,
counter, je le fais lentement hein,
self new Donc je crée un counter
et je vais faire self count: aNumber
et je vais rendre ce counter.
On peut le faire de manière plus compacte
mais pour le moment faisons-le simplement.
Donc je compile ma méthode.
Et maintenant ça veut dire que je peux envoyer des messages.
Et vous avez vu, quand je clique sur ce bouton,
je passe au niveau classe. Donc je passe du niveau classe
au niveau instance.
Donc là j'étais au niveau classe et là je reviens sur
les messages qui sont envoyés à des instances.
Qu'est-ce que ça veut dire ? ça veut dire que si je fais
Counter withValue: 18, qu'est-ce que je vais obtenir ?
Je vais obtenir une instance de la classe counter.
J'obtiens bien un counter avec value 18.
Et là je pourrais le faire decrement.
Et si je rafraichis, j'ai bien 17.
Donc maintenant si je regarde mon test,
tous mes tests passent, donc je vais encore une fois
sauvegarder et j'ai fini.
Added instance creation API and tests.
Done for now.