Laboratoire de raffinement
Ce laboratoire est fait en deux parties, la première en Nit, pour jouer avec le raffinement de classes, et la seconde en Java pour essayer de reproduire dans un langage à objets habituel.
Le thème est de faire un petit convertisseur Logo vers SVG en séparant les préoccupations.
Afin de ne pas tout écrire, on vous donne à disposition un code incomplet qu’il faudra étendre.
Étape 1: Programmation graphique
Le langage Logo permet de faire de la programmation graphique amusante.
Dans ce laboratoire, on considère des programmes Logos très simples composé seulement des 3 instructions forward
, turn right
et repeat
.
La structure d’un programme Logo est donnée dans le fichier logo.nit.
Pour simplifier la création d’un objet programme logo, on fournit une API fluide via la classe LogoWriter
et la fonction logo
.
- Lisez et comprenez le module logo.nit
- Implémentez la méthode
to_s
de LogoProg et LogoRepeat - Vérifiez que votre programme fonctionne en exécutant le module
logo
$ nit logo.nit
REPEAT 5 [FD 50 RT 144]
REPEAT 4 [FD 50 RT 90] FD 50 RT -135 FD 35 RT -90 FD 35 RT 225
Aide 1: for item in coll do ...
pour itérer sur une collection
Aide 2: for i in [0..len[ do ...
pour itérer len
fois.
Aide 3: "A {b} C {d}"
est équivalent à "A " + b.to_s + " C " + d.to_s
.
Aide 4: [a,b,c].join("x")
est équivalent à "{a}x{b}x{c}"
.
Étape 2: La tortue entre lentement en scène
Nous avons des programmes Logo, mais nous pouvons rien en faire pour l’instant.
Il suffit d’ajouter une tortue et d’implémenter les services qui déplacent la tortue. Comme en Nit il est possible de raffiner des classes existantes, il suffit d’implémenter les services qui vont bien, directement dans les raffinements des classes.
Dans le module turtle.nit, on vous fournit une classe Turtle
et on raffine la classe Logo
.
- Lisez et comprenez le module turtle.nit
- Implémentez les méthodes
apply
des sous-classes deLogo
- Vérifiez que votre programme fonctionne en exécutant le module
turtle
$ nit turtle.nit
(50.0,0.0;0.0)
(10.0,20.0;90.0)
(55.0,55.0;180.0)
Étape 3: Une visite inattendue
Le patron de conception Visiteur permet de séparer un algorithme d’une structure de données.
Il est intéressant dans les langages à objets classiques car il permet de définir de nouveaux traitements sur une structure de données existante complexe que l’on ne veut/peut pas modifier.
Dans ce laboratoire, la structure de données considérée est la classe Logo
et ses sous-classes.
Elle est complexe car elle est hétérogène (plusieurs catégories d’instructions) et récursive (à cause de l’instruction repeat).
Comme en Nit il est possible de raffiner les classes existantes dans un module différent, le visiteur est moins utile. La preuve: c’est exactement ce que l’on a fait à l’étape précédente où on a ajouté le comportement apply
aux classes existantes.
Toutefois, le visiteur a un autre avantage, il permet de factoriser le code de parcours de la structure de données. En effet, si on regarde les classes LogoProg
et LogoRepeat
on se rend compte que le comportement sera très semblable d’un algorithme à l’autre: il suffit pour s’en convaincre de regarder le code de apply
.
Également, lorsque qu’un algorithme doit visiter les éléments, il faut généralement maintenir un état spécifique à l’algorithme. En programmation à objets, il est raisonnable de maintenir cet état dans un objet spécifique qui est passé en paramètre dans les méthodes des éléments. Cet objet est un bon candidat pour devenir un visiteur.
Le module visitor.nit
introduit la structure abstraire d’un visiteur.
Notez que grâce au raffinement on peut introduire l’instrumentation du visiteur dans un sous-module sans toucher aux classes originales.
Notez aussi que visitor.nit
ne dépend pas de turtle.nit
.
Dans cette étape nous allons implémenter le calcul d’une boite englobante un programme Logo. Pour ce faire il faut visiter les instructions d’un programme en mettant à jour la position de la tortue et en grossissant la boite englobante. Une bonne conception indiquerait de créer un visiteur qui agrège ces deux informations.
- Lisez et comprenez les modules visitor.nit et bound.nit.
- Finissez l’implémentation de ces deux modules. En particulier de la classe
BoundVisitor
. - Vérifiez que votre programme fonctionne en exécutant le module
bound
$ nit bound.nit
(0.0,0.0)--(10.0,0.0)
(0.0,-18.164)--(50.0,29.389)
(0.0,-24.749)--(50.0,50.0)
Aide 1: Dans visitor.nit
, inspirez-vous de apply
pour implémenter visit_all
.
Aide 2: Dans bound.nit
, vous pouvez raffiner la classe Logo
et ses sous-classes pour ajouter du service.
Étape 4: Dessinons
Maintenant que nous maîtrisons les visiteurs, il ne reste qu’à générer le SVG.
Le module canvas.nit
indépendant fournit un moyen simpliste de générer du SVG.
- Lisez et comprenez les modules canvas.nit et trace.nit.
- Finissez d’implémenter
trace.nit
. - Vérifiez que votre programme fonctionne en exécutant le module
trace
$ nit trace.nit
Aide: initialisez la tortue en (250.0,100.0) pour quelle soit au milieu du canevas SVG.
Étape 5: Un coup en haut, un coup en bas
On imagine que les modules précédents sont fournis par un tiers, on ne peut pas les modifier. Toutefois on veut pouvoir les faire évoluer pour les adapter à de nouveaux besoins.
On va donc créer un nouveau module pen.nit
qui va importer tous les modules précédents (en fait seul trace
suffit) et spécialiser ou raffiner les classes existantes.
L’objectif est de créer deux nouvelles instructions «pen up» (PU) et «pen down» (PD) qui permettent de lever ou poser le crayon afin de pouvoir déplacer la tortue sans tracer sur le canevas lorsque le crayon est levé.
- Implémentez tout ce qu’il faut dans pen.nit
- Vérifiez que votre programme fonctionne en exécutant le module
pen
$ nit pen.nit
PU FD -200 PD REPEAT 7 [REPEAT 4 [FD 50 RT 90] FD 50 RT -135 FD 35 RT -90 FD 35 RT 225 PU FD 60 PD]
Indice: pour commencer, raffinez la classe Turtle
pour rajouter un état indiquant si le crayon est levé ou posé.
Étape 6: Vous prendrez-bien un peu de café?
Réimplémentez ce programme en Java (ou en C#) en essayant de séparer au mieux les préoccupations.
- Créer une hiérarchie de classes Logo (sans tortue) mais instrumentée avec une classe abstraire
Visitor
. - Créez un visiteur particulier qui génère du SVG.
- De façon indépendante (sans modifier les classes Logo existantes, ni le visiteur abstrait) introduisez les deux nouvelles instructions pen up et pen down.
- Quels sont les irritants de langages comme Java ou C# en terme de modularité et d’évolution de code ?