UP | HOME

Projet d'architecture logicielle - Un langage embarqué pour dessiner des diagrammes de types

Table of Contents

On souhaite définir un langage embarqué dédié au dessin de diagrammes de types, comme celui-ci.

Concrètement, on imagine le scénario suivant. Le point de départ est une application Java, formée d'interfaces et de classes. Dans une fonction principale, on souhaite définir en programmant un diagramme de types, à partir de la définition de ces types. Ce diagramme représente non seulement le contenu des types, mais aussi leurs relations, d'héritage, d'implémentation ou d'agrégation. A partir de sa définition en Java, il doit être possible d'engendrer plusieurs représentations, en particulier une au format SVG ("Scalable Vector Graphics"), interprétable par un navigateur.

La conception d'un tel langage embarqué se décompose donc en deux phases :

Le langage dédié au dessin est dit embarqué parce que la seconde phase repose sur l'interfaçage avec un langage existant, ici Java. Pour un langage qui n'est pas embarqué, cette seconde phase correspond à une compilation ou à une interprétation : le langage dédié est dit alors compilé ou interprété.

Spécification

Le langage

Pour la définition du langage, nous nous inspirons du langage UML. Pour dessiner un diagramme, on retient quelques fonctionnalités fondamentales, dont voici la description.

  • ajouter un type

    Cette fonctionnalité permet d'ajouter un type au diagramme en spécifiant sa position si nécessaire.

  • décrire un type

    Cette fonctionnalité permet de décrire un type, non seulement son contenu mais aussi ses relations.

  • insérer un diagramme

    Cette fonctionnalité permet d'insérer un diagramme limité par un contour à l'intérieur d'un autre diagramme.

  • étiqueter un diagramme

    Cette commande permet de placer une étiquette à une position donnée à l'intérieur d'un diagramme.

Le langage doit aussi permettre de personnaliser le dessin, par exemple :

  • l'épaisseur de trait,
  • les couleurs,
  • la forme des boîtes représentant les types,
  • la forme des flèches représentant les relations.

Le placement peut être fait explicitement ou calculé par un algorithme de placement.

Enfin, il doit être possible de contrôler l'exécution des instructions, à l'aide d'opérateurs de contrôle.

  • Séquence

    Cet opérateur permet d'exécuter une première instruction, puis une seconde.

  • Alternative

    Cet opérateur permet de choisir des instructions à exécuter suivant une condition booléenne. Il correspond à l'instruction classique if … then … else ….

  • Boucle

    Cet opérateur permet de répéter un certain nombre de fois des instructions. Le nombre peut être fixé a priori (for) ou déterminé a posteriori par une condition (boucles while).

L'interprétation

Une fois que le langage est défini, il est nécessaire de définir son interprétation. Alors qu'un script écrit dans le langage permet de définir logiquement un diagramme de types, l'interprétation permet de traduire le diagramme en un représentation concrète. Une interprétation est constituée de deux phases, une phase de traduction pendant laquelle un script écrit dans le langage est traduit dans un autre langage dédié à la représentation, et d'une phase d'exécution pendant laquelle un moteur de rendu produit le rendu final à partir de la traduction du script. Plusieurs sortes d'interprétations sont envisageables, puisque différentes traductions et différents moteurs de rendu sont envisageables.

Interprétations

  • Notation textuelle : une version affichable ou imprimable du script de dessin
  • Représentation en SVG

Moteur de rendu

  • Console (interne)
  • Interface graphique (interne)
  • Navigateur (externe) via un fichier

Au final, au moins deux interprétations doivent être réalisées. L'une des interprétations doit correspondre à la production d'un fichier au format SVG, afin de permettre une visualisation dans un navigateur.

Modularité

L'implémentation du langage de dessin et de son interprétation doit être ouverte aux extensions suivantes, tout en étant fermée aux modifications.

  • L'extension du langage par une nouvelle fonctionnalité ou une nouvelle structure de contrôle
  • L'ajout d'une nouvelle interprétation

Agenda et livrables

  • Projet à mener en deux sprints de quinze jours (sans compter la semaine de la Toussaint)
    • Rendu intermédiaire : 14 novembre, 20 heures
    • Rendu final : 28 novembre, 20 heures
  • Utilisation pour le code source d'un dépôt public avec un gestionnaire de version
    • Recommandé : Github
    • Me fournir l'adresse du dépôt à sa création.
  • Pour chaque rendu, code commenté et documenté
    • Commentaires pour faciliter la compréhension du code
    • Documentation au format Javadoc (au moins pour les interfaces publiques)
    • Prévoir un fichier "readme".
    • Définir une fonction principale permettant de tester les capacités de dessin et décrire son appel dans le fichier "readme".
  • Pour chaque rendu, rapport de présentation de l'application présentant les points suivants - Quatre à six pages
    • La définition du langage de dessin
    • L'interprétation du langage (ou les interprétations)
    • L'architecture logicielle
      • Schéma général
      • Principes modulaires suivis, patrons de conception utilisés, accompagnés des motivations pour les choix réalisés
      • Méthode pour étendre le langage et ajouter une interprétation
    • Un guide d'utilisation

Commentaires

Voici quelques remarques, conseils et suggestions en vrac.

  • Pour obtenir la description d'un type à partir de son nom, on utilise l'introspection. Cf. le tutoriel sur le site d'Oracle.
  • Il est recommandé d'utiliser des hiérarchies pour les interfaces.
  • L'architecture comporte deux couches : une couche haute correspondant au langage à concevoir, une couche basse correspondant à l'interprétation.
  • Certains patrons de conception ("design patterns") semblent particulièrement adaptés pour ce projet (attention : certains choix peuvent être exclusifs).
    • Composite : pour représenter les scripts du langage
    • Interpréteur : pour représenter une interprétation
    • Visiteur : pour représenter une fonction appliquée à un script (comme une interprétation)
    • Guide de méthode ("method template") : pour représenter un script puis son interprétation
    • Etc.
  • Comment représenter un script ? On peut le représenter par un texte dans un fichier, puis l'analyser pour produire un arbre de syntaxe abstraite. Un arbre de syntaxe abstraite représente le script sous une forme structurée, arborescente, faisant abstraction des détails syntaxiques. Il s'implémente typiquement par une structure de données de type Arbre en Java. Il n'est pas demandé de suivre cette voie, correspondant à une compilation, pour réaliser ce projet. Il est au contraire demandé d'embarquer directement le langage de dessin dans le langage Java, ce qui permet d'éviter les phases d'analyse lexicale et syntaxique des scripts textuels. On représente alors directement le script par du code Java, suivant une architecture à définir, par exemple par un arbre, ou par une fonction paramétrée par les primitives de dessin. On pourra s'inspirer de la méthode décrite dans l'article Embedded Typesafe Domain Specific Languages for Java (2008).
  • N'hésitez pas à poser des questions sur le forum. Vous pouvez aussi passer me voir, après avoir pris rendez-vous par mail.

Version history: v1: 2016-10-24; v2: 2016-11-10 [*dates].
Comments or questions: Send a mail.
The webpage content is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.