26 mai 2026
Je suggérerais ces refactorings, dans cet ordre.
1. Séparer le moteur Logo de l’affichage
Aujourd’hui, les instructions modifient directement l’état global de
turtle.
Par exemple Move.cpp calcule la
nouvelle position puis appelle turtle::drawLine(). Ça
mélange : - logique Logo ; - état de la tortue ; - rendu SFML ; - export
SVG.
Le mieux serait d’avoir une classe TurtleState ou
DrawingContext indépendante de SFML :
class TurtleState {
double x;
double y;
double direction;
bool penDown;
std::vector<Line> lines;
};Puis SFML et SVG ne feraient qu’afficher/exporter les lignes produites.
2. Supprimer les variables globales de
Turtle.cpp
Actuellement, turtleX, turtleY,
turtleDir, turtlePenDown, lines,
window, etc. sont globaux.
C’est simple, mais ça rend le programme difficile à tester et à faire
évoluer. Une classe TurtleRenderer ou
SfmlTurtleView permettrait de mieux contrôler le cycle de
vie.
3. Clarifier la responsabilité de
Program
Program.cpp fait beaucoup de
choses : - parse le programme principal ; - parse les fonctions ; -
parse les blocs repete; - construit les instructions.
À terme, je créerais un vrai Parser, distinct de
Program.
Program deviendrait juste un conteneur d’instructions et
de fonctions, tandis que Parser serait responsable de lire
les tokens.
4. Rendre l’exécution moins dépendante des iterators
L’exécution repose sur des InstructionList::iterator. Ça
marche, mais c’est fragile dès qu’on veut déplacer, copier ou sérialiser
des programmes.
Une alternative plus simple à maintenir : - stocker un index
d’instruction courant (size_t currentIndex) ; - garder un
pointeur/référence vers le Program courant ; - représenter
un contexte par { Program*, index }.
Ce serait aussi plus facile à déboguer.
5. Améliorer les erreurs de parsing
ParseError dépend d’un iterator vers un token. Quand
l’erreur arrive en fin de fichier, certains chemins peuvent être
fragiles.
Le lexer pourrait produire des tokens avec position :
struct Token {
TokenType type;
std::string text;
int line;
int column;
};Les messages deviendraient beaucoup plus utiles :
Erreur ligne 4, colonne 12 : nombre attendu après avance.
6. Ajouter une validation des appels de fonction
Actuellement, un appel à une fonction inexistante peut finir en crash dans FunctionCall.cpp.
Il faudrait soit : - vérifier l’existence au parsing ; - soit lever une erreur claire à l’exécution.
7. Encapsuler les blocs de contrôle
FunctionCall et Repeat utilisent tous les
deux la pile d’exécution. On pourrait créer une abstraction plus claire
pour les instructions qui ouvrent un sous-programme.
Pas forcément à faire tout de suite, mais utile si tu ajoutes ensuite
: - si; - tantque; - variables ; - paramètres
de fonctions.
8. Ajouter des tests sans SFML
Comme le cœur du programme dépend de SFML, les tests sont compliqués. Après séparation moteur/rendu, tu pourrais tester :
repete 4 [avance 100 droite 90]
et vérifier que le moteur produit 4 lignes formant un carré, sans ouvrir de fenêtre.
Le plus rentable à court terme : commencer par séparer
TurtleState du rendu SFML/SVG. C’est le refactoring qui
débloque presque tous les autres.