samedi 14 mars 2009

Un outil pour générer tous mes messages

Comme vous le savez peut-être, réécrire tout le temps (presque) le même code m'ennuie à n'en plus finir. Or, à chaque fois qu'il me fallait écrire la petite classe qui représente un paquet d'informations à passer entre le client et le serveur, je me retrouve à écrire presque la même chose! Quelques inclusions, un constructeur par défaut, un constructeur qui prend toutes mes données, un empaqueteur de données et son inverse, et quelques getters.

Une solution possible aurait été d'utiliser de grandes maps de boost::variant. Pourquoi ne pas l'avoir fait, moi, le chantre du code dynamique? Peut-être l'envie d'avoir de bons getters, et de ne pas s'embêter avec tous les types qu'il aurait fallu mettre dans le variant. Bref, c'est fait.

Je me suis donc décidé à prendre exemple sur le wsdl, et écrire un petit générateur de code pour me décharger de toute cette ennuyeuse paperasse, à partir d'un fichier de description de l'interface.

Ce qui fut dit fut fait, et je suis maintenant l'heureux auteur d'un petit programme en Ocaml tout bête mais qui va me permettre de me concentrer sur le contenu plutôt que de m'embêter avec la syntaxe.

Passons par exemple la définition suivante:


<messages>
<message name="PingMsg">
<item name="data" type="std::string"/>
</message>
<message name="RadioMsg">
<item name="callsign" type="std::string"/>
<item name="message" type="std::string"/>
<item name="system" type="bool"/>
</message>
<message name="LoginMsg">
<include file="Ids.h"/>
<item name="login" type="std::string"/>
<item name="password" type="std::string"/>
<item name="avatarId" type="AvatarId"/>
</message>
</messages>


L'on remarquera le node include dans la définition du LoginMsg, qui permet d'ajouter des inclusions supplémentaires pour les types non standard, en l'occurence mon AvatarId.

L'on passe à la moulinette, et voilà le travail:


$ wc -l *Msg.{h,cpp}
26 LoginMsg.h
21 PingMsg.h
25 RadioMsg.h
47 LoginMsg.cpp
31 PingMsg.cpp
47 RadioMsg.cpp
197 total


La génération de code avec Ocaml est toujours un plaisir, la bibliothèque standard est bourrée de fonctions particulièrement utiles dans ce contexte: String.uppercase, String.capitalize, String.concat, et l'ensemble du programme tient pour l'instant en 117 lignes. Bien entendu, la génération du code est extrêmement rapide, je doute avoir un jour suffisamment de messages pour qu'elle ne paraisse plus instantanée.

Pour les curieux, le code est , mais attention, c'est très lourdement adapté à mes besoins, et donc probablement pas réutilisable en l'état.

Aucun commentaire: