In [1]:
%reload_ext mocodo
Mocodo 3.2.1 loaded.
In [2]:
from IPython import display
from pathlib import Path

Introduction

Mocodo est un logiciel d'aide à l'enseignement et à la conception des bases de données relationnelles.

  • En entrée, il prend une description textuelle des entités et associations du modèle conceptuel de données (MCD).
  • En sortie, il produit son diagramme entité-association en SVG et son schéma relationnel (MLD#MLD_:_modèle_logique_des_données)) en SQL, $\mathrm\LaTeX$, Markdown, etc.

Ci-dessous, un exemple d'utilisation sous Jupyter Notebook. L'appel du programme est en première ligne, sur un texte d'entrée donné lignes suivantes. Le cas est adapté de l'article fondateur de Peter Chen, The entity-relationship model—toward a unified view of data (ACM Trans. Database Syst. 1, 1, March 1976, pp. 9–36). En sortie, le MCD (diagramme conceptuel) et le MLD (schéma relationnel) correspondants :

In [3]:
%%mocodo --mld --colors ocean --shapes copperplate --relations diagram markdown_data_dict

Ayant-droit: nom ayant-droit, lien
Diriger, 0N Employé, 01 Projet
Requérir, 1N Projet, 0N Pièce: qté requise
Pièce: réf. pièce, libellé pièce
Composer, 0N [composée] Pièce, 0N [composante] Pièce: quantité

DF1, _11 Ayant-droit, 0N Employé
Employé: matricule, nom employé
Projet: num. projet, nom projet
Fournir, 1N Projet, 1N Pièce, 1N Société: qté fournie

Département: num. département, nom département
Employer, 11 Employé, 1N Département
Travailler, 0N Employé, 1N Projet
Société: num. société, raison sociale
Contrôler, 0N< [filiale] Société, 01 [mère] Société

(I) ..Pièce, ->Requérir, --Fournir, Projet
I 0,N 0,1 Diriger 1,N 0,N Requérir qté requise 0,N 0,N Composer quantité 1,1 0,N DF 1,N 1,N 1,N Fournir qté fournie 1,1 1,N Employer 0,N 1,N Travailler 0,N 0,1 Contrôler Ayant-droit nom ayant-droit lien Pièce réf. pièce libellé pièce Employé matricule nom employé Projet num. projet nom projet Département num. département nom département Société num. société raison sociale
Ayant-droit ( #matricule, nom ayant-droit, lien )
Composer ( #réf. pièce composée, #réf. pièce composante, quantité )
Département ( num. département, nom département )
Employé ( matricule, nom employé, #num. département )
Fournir ( #num. projet, #réf. pièce, #num. société, qté fournie )
Pièce ( réf. pièce, libellé pièce )
Projet ( num. projet, nom projet, #matricule )
Requérir ( #num. projet, #réf. pièce, qté requise )
Société ( num. société, raison sociale, #num. société mère )
Travailler ( #matricule, #num. projet )

L'appel précédent a également construit le dictionnaire des données:

In [4]:
display.Markdown("mocodo_notebook/sandbox_data_dict.md")
Out[4]:
  • nom ayant-droit
  • lien
  • quantité
  • num. département
  • nom département
  • matricule
  • nom employé
  • qté fournie
  • réf. pièce
  • libellé pièce
  • num. projet
  • nom projet
  • qté requise
  • num. société
  • raison sociale

Ainsi que le diagramme relationnel, qui peut être visualisé par un nouvel appel:

In [5]:
%mocodo --input mocodo_notebook/sandbox.mld --colors desert
Ayant-droit #matricule nom ayant-droit lien Requérir #num. projet #réf. pièce qté requise Pièce réf. pièce libellé pièce Composer #réf. pièce composée #réf. pièce composante quantité Employé matricule nom employé #num. département Projet num. projet nom projet #matricule Fournir #num. projet #réf. pièce #num. société qté fournie Département num. département nom département Travailler #matricule #num. projet Société num. société raison sociale #num. société mère

Installation du programme

Installation complète (recommandé)

  • Installez la distribution Anaconda, qui contient Python 3, Jupyter Notebook et bien plus encore.
  • Exécutez ensuite sous un terminal la ligne suivante pour installer Mocodo ainsi que sa « commande magique » (utilisable sous Jupyter notebook) :

      python -m pip install mocodo
  • Si vous souhaitez générer des figures en PDF ou en PNG :

      python -m pip install cairosvg

Vérification

Toujours sous un terminal, tapez:

mocodo

Si votre système se plaint que cette commande n'existe pas, localisez le fichier mocodo et ajoutez à votre PATH le chemin du répertoire contenant:

Pour mettre la « commande magique » mocodo à disposition d'un notebook donné, évaluez dans celui-ci la cellule suivante:

%reload_ext mocodo

Techniquement, %load_ext mocodo suffit, mais cette forme vous épargnera un message d'erreur si vous réévaluez ultérieurement la cellule.

Pour tester, évaluez une cellule avec:

In [6]:
%%mocodo
MISSION: accomplie
MISSION accomplie

Pour charger automatiquement mocodo à chaque ouverture d'un notebook (ce qui dispense d'évaluer %load_ext mocodo) :

  • exécuter sous un terminal :

          ipython profile create
  • éditer le fichier créé (p. ex.: ~/.ipython/profile_default/ipython_config.py) pour remplacer les lignes suivantes :

          ## A list of dotted module names of IPython extensions to load.
          #c.InteractiveShellApp.extensions = []
    
    

    par celles-ci :

          ## A list of dotted module names of IPython extensions to load.
          c.InteractiveShellApp.extensions = [
              "mocodo",
          ]

Installation minimale

  • Si vous êtes sous macOS ou Linux, vous avez déjà Python 3. Dans le cas contraire, vous devrez probablement l'installer.
  • Une fois Python installé, tapez sous un terminal:

    python -m pip install mocodo

Vous ne bénéficierez pas de Jupyter Notebook, mais vous pourrez utiliser Mocodo en ligne de commande.

Utilisation

Vous pouvez utiliser Mocodo :

  • à distance, sans rien installer, avec Mocodo online;
  • en local, comme n'importe quel programme Python;
  • dans un document Jupyter Notebook (à l'instar de cette documentation).

Utiliser Mocodo online

Faites pointer votre navigateur sur www.mocodo.net : vous pouvez commencer à taper votre MCD. Appuyez à tout moment sur le bouton de génération pour visualiser le diagramme conceptuel et en déduire les relations. Une fois que le résultat vous convient, appuyez sur le bouton de téléchargement pour récupérer une archive ZIP contenant tous les fichiers d'entrée et de sortie spécifiés.

Mocodo online est conçu pour une utilisation occasionnelle et/ou interactive, et son interface vise avant tout à la simplicité. Vous n'avez donc accès qu'aux options essentielles du programme. Si vous en voulez davantage, tant en termes de paramétrage que de calcul ou de fonctionnalités, installez Mocodo sur votre machine.

Utiliser Mocodo en ligne de commande

Au plus simple

Tout a été fait pour faciliter au maximum la prise en main. Ainsi, pour peu que vous sachiez lancer une console (cmd sous Windows, Terminal sous macOS), il vous suffit d'y entrer:

mocodo

Invoqué sous cette forme, le script récupère le texte d'entrée du MCD dans le répertoire courant sous le nom de sandbox.mcd. Si ce fichier n'existe pas, il y sera automatiquement créé avec un MCD d'exemple. Par la suite, vous n'aurez qu'à le garder ouvert sous un éditeur de texte, afin de le modifier selon vos besoins avant de relancer la commande.

Liste des arguments

La commande mocodo admet de nombreux arguments optionnels. Voici la traduction en français de la liste affichée par l'argument --help. Destinée à servir de référence, elle peut être sautée sans inconvénient à la première lecture. Nous avons ajouté des liens vers des exemples d'utilisation dans ce document ; notez cependant que les %% ou % qui préfixent la « commande magique » mocodo doivent être omis de la ligne de commande.

Options sur Mocodo lui-même

  • --help. Affiche un message d'aide, puis termine.
  • --version. Affiche le numéro de version, puis termine.
  • --language CODE. Outrepasse la localisation automatique des messages avec le code de langage donné (p. ex., fr, en, ...) (défaut: langue du système).
  • --restore. Recrée une version originelle des fichiers sandbox.mcd et params.json dans le répertoire d'entrée, puis termine (défaut: False).

Entrée-sortie

  • --params_path PATH. Le chemin du fichier de paramètres. S'il est omis, utilise params.json dans le répertoire d'entrée. Si ce fichier n'existe pas, utilise les paramètres par défaut (défaut: params.json).
  • --input PATH. Le chemin du fichier d'entrée. Les fichiers de sortie seront par défaut générés dans le même répertoire (défaut: sandbox.mcd).
  • --output_dir PATH. Le répertoire où générer les fichiers de sortie (défaut: le répertoire où se trouve le fichier d'entrée).
  • --encodings [STR [STR ...]]. Un ou plusieurs encodages à essayer successivement pour lire le fichier d'entrée (défaut: utf8, puis encodage historique de la plateforme).
  • --pdf. Génère une version PDF de la sortie graphique (requiert CairoSVG).
  • --png. Génère une version PNG de la sortie graphique (requiert CairoSVG).
  • --print_params. Affiche le contenu du fichier de paramètres, puis termine (défaut: False).
  • --reuse_geo. Utilise le fichier de géométrie généré lors de la précédente exécution.
  • --uid_suffix Permet de distinguer les éléments interactifs entre plusieurs SVG d'un même diagramme.

Aspect de la sortie graphique

  • --df STR. Acronyme à encercler dans une dépendance fonctionnelle (défaut: DF).
  • --card_format STR. Chaîne de format pour les cardinalités minimale et maximale (défaut: {min_card},{max_card}).
  • --strengthen_card STR). Chaîne pour les cardinalités relatives (défaut: _1,1_).
  • --flex FLOAT. Infléchit les pattes rectilignes dont les cardinalités sont susceptibles de collision (défaut: 0.75).
  • --colors PATH. Palette de couleurs à utiliser lors de la génération du dessin. Nom (sans extension) d'un fichier du répertoire colors, ou chemin vers un fichier personnel (défaut: bw).
  • --shapes PATH. Spécification des polices, des dimensions, etc. Nom (sans extension) d'un fichier du répertoire shapes, ou chemin vers un fichier personnel (défaut: dépendant de votre système).
  • --scale SCALE. Facteur d'échelle multiplicatif (défaut: 1.0).
  • --adjust_width SCALE. Facteur multiplicatif appliqué à la largeur des libellés (défaut: 1.0).
  • --hide_notes. Ignore le survol des éléments annotés (défaut: False).
  • --detect_overlaps. Lève une erreur en présence de chevauchement de pattes horizontales ou verticales.

Sortie relationnelle

  • --relations [NAME [NAME ...]]. Un ou plusieurs gabarits pour les schémas relationnels générés. Cf. répertoire relation_templates (défaut: html text).
  • --disambiguation {numbers_only,notes}. Méthode de désambiguïsation des attributs migrants homonymes (défaut: notes).
  • --title STR. Nom de la base (utilisé pour la sortie SQL) (défaut: Sans titre).
  • --guess_title. Utiliser le nom de l'entité la plus référencée comme titre (défaut: False).

Modifications du texte d'entrée

  • --arrange [{bb,ga}]. Met en page le diagramme, soit par séparation et évaluation (branch and bound), soit avec un algorithme génétique (genetic algorithm), puis termine (défaut: None).
  • --timeout SECONDS. Limite la durée du calcul de la mise en page (défaut: None).
  • --verbose. Affiche des détails oiseux lors du réarrangement (défaut: False).
  • --flip {h,v,d}. Affiche une version retournée horizontalement / verticalement / diagonalement du texte d'entrée, puis termine (défaut: None).
  • --fit [INT]. Reformate le texte d'entrée dans la ième plus petite grille possible, puis termine (défaut: None).
  • --obfuscate [PATH]). Affiche une version du texte d'entrée vidée de sa sémantique, puis termine. Cf. répertoire lorem (défaut: None).
  • --obfuscation_max_length INT). Longueur maximale des mots de substitution (défaut: None).
  • --obfuscation_min_distance INT). Distance de Damerau Levenshtein minimale entre deux mots de substitution (défaut: 3).
  • --seed FLOAT. Valeur du germe du générateur aléatoire (défaut: None).

Réarrangement par séparation et évaluation

Sous-options accessibles avec l'option --arrange=bb.

  • --call_limit INT. Nombre maximal d'appels pour une boîte de départ donnée (défaut: 10000).
  • --min_objective INT. Meilleur objectif esthétique pour la mise en page (défaut: 0).
  • --max_objective INT. Pire objectif esthétique pour la mise en page (défaut: 15).
  • --organic. Réarrangement non limité à la grille originelle (défaut: False).

Réarrangement par algorithme génétique

Sous-options accessibles avec l'option --arrange=ga.

  • --population_size INT. Nombre d'individus à faire évoluer (défaut: 1000).
  • --crossover_rate RATE. Taux de croisement, entre 0 et 1 (défaut: 0.9).
  • --mutation_rate RATE. Taux de mutation, entre 0 et 1 (défaut: 0.06).
  • --sample_size INT. Taille de l'échantillon pour les tournois (défaut: 7).
  • --max_generations INT. Nombre maximal de générations (défaut: 300).
  • --plateau INT. Nombre maximal de générations consécutives sans amélioration (défaut: 30).

Options spécifiques aux Notebooks

Ignorées lors de l'appel en ligne de commande.

  • --mld. Affiche le schéma relationnel en HTML dans la sortie de la cellule (défaut: False).
  • --no_mcd. N'affiche pas le diagramme conceptuel dans la sortie de la cellule (défaut: False).
  • --replace. Remplace le contenu de la cellule par le résultat de son évaluation (défaut: False).

Paramétrage à long terme

Pour éviter d'avoir à invoquer Mocodo répétitivement avec une longue kyrielle d'options, vous pouvez mettre celles-ci une fois pour toutes dans un fichier params.json situé dans le répertoire de lancement de Mocodo. La commande:

mocodo --restore

... le fait pour vous avec un fichier de paramètres vide, i.e. , un fichier-texte réduit aux deux caractères {} (attention, elle rétablit aussi le fichier sandbox.mcd à son contenu par défaut). Vous êtes encouragés à modifier ce fichier de paramètres selon vos goûts et vos besoins. De la sorte, le style de vos MCD pourra être maintenu à moindre frais à travers tous vos documents. En cas de besoin, vous pourrez toujours ponctuellement passer outre ces réglages en en précisant d'autres en ligne de commande. Plus précisément, chaque paramètre est déterminé:

  1. par sa valuation en ligne de commande;
  2. à défaut, par sa valuation dans le fichier de paramètres indiqué par --params_path;
  3. à défaut d'une telle indication, par sa valuation dans le fichier params.json du répertoire courant;
  4. à défaut, par une valeur défaut éventuellement dépendante de votre système.

Si vous lancez Mocodo avec l'option --print_params, la valeur courante de l'ensemble des paramètres sera affichée. Vous pouvez envoyer la sortie dans un fichier params.json et la modifier à votre gré pour une prise en compte lors du lancement suivant.

Utiliser Mocodo sous Jupyter Notebook

Invocation

Elle nécessite l'installation de l'extension notebook mocodo, laquelle doit en outre être rechargée à chaque ouverture (%reload_ext mocodo, cf. première cellule du présent document). On a ainsi déclaré une « commande magique » mocodo qui sera invoquée en la préfixant:

  • de %% pour prendre toutes les lignes suivantes de la cellule comme texte d'entrée du MCD ;
  • de % si l'on récupère l'entrée ailleurs (avec --input), ou qu'on n'en a pas besoin (p. ex., --help ou --print_params).

À part ça, la syntaxe est généralement la même qu'en ligne de commande, ce qui devrait faciliter le passage de l'un à l'autre.

Principes de fonctionnement

Il peut être utile de comprendre ce qui se passe en coulisses lorsque l'on invoque la commande magique sur une cellule:

  • dans le répertoire courant est créé au besoin un sous-répertoire mocodo_notebook;
  • le texte d'entrée y est sauvegardé sous le nom de sandbox.mcd;
  • la commande est lancée sur ce fichier avec tous les paramètres donnés par l'utilisateur. Cela signifie que tous les fichiers générés le seront au même endroit sous les noms de sandbox.svg, sandbox.html, etc.;
  • si la commande a produit un dessin, celui-ci est affiché en sortie (sauf avec l'option --no_mcd); avec l'option --mld, le schéma relationnel est également affiché au-dessous (au format HTML);
  • si elle n'a pas produit de dessin, mais une nouvelle version du texte d'entrée (options --arrange, --flip, --obfuscate, ...), Mocodo est automatiquement relancé sur celle-ci, permettant de visualiser le diagramme et/ou le schéma relationnel correspondants.

Tous les fichiers peuvent être lus dans le répertoire mocodo_notebook (commande magique %load, mise en commentaire dans ce notebook pour éviter de recharger le fichier à chaque exécution).

Exemples d'invocation

Les trois exemples de l'introduction illustrent plusieurs de ces techniques usuelles:

%%mocodo --mld --colors ocean --shapes copperplate --relations diagram markdown_data_dict

... invoque le programme en demandant l'affichage du diagramme conceptuel (implicitement), du schéma relationnel (avec --mld), des changements de style (avec --colors et --shapes) et la production d'un diagramme relationnel (--relations diagram) et d'un dictionnaire de données (markdown_data_dict). Le contenu de celui-ci est rechargé et visualisé à l'aide de la commande suivante:

%load mocodo_notebook/sandbox_data_dict.md

Tandis que le diagramme relationnel (MLD) est tracé en relançant Mocodo dessus:

%mocodo --input mocodo_notebook/sandbox.mld --colors desert

Modification in situ d'une cellule

Nouveauté de la version 2.0.20 (contribution de Thomas Giro). Avec les options --arrange, --flip et --obfuscate le résultat de l'évaluation de la cellule est un nouveau MCD, normalement affiché au-dessous. Ajoutez l'option --replace pour substituer ce MCD au contenu de la cellule. Réévaluez alors celle-ci pour tracer le MCD résultant, ou annulez la dernière opération pour revenir au contenu originel.

Par exemple, l'évaluation de la cellule suivante:

In [7]:
%%mocodo
PRODUIT: Réf. produit, Libellé, Prix unitaire
INCLURE, 1N COMMANDE, 0N PRODUIT: Quantité
COMMANDE: Num commande, Date, Montant
PASSER, 0N CLIENT, 11 COMMANDE
CLIENT: Réf. client, Nom, Prénom, Adresse
1,N 0,N INCLURE Quantité 0,N 1,1 PASSER PRODUIT Réf. produit Libellé Prix unitaire COMMANDE Num commande Date Montant CLIENT Réf. client Nom Prénom Adresse

... remplacerait celle-ci par celle-là:

In [8]:
%%mocodo
PRODUIT: Réf. produit, Libellé, Prix unitaire
INCLURE, 1N COMMANDE, 0N PRODUIT: Quantité
COMMANDE: Num commande, Date, Montant
PASSER, 0N CLIENT, 11 COMMANDE
CLIENT: Réf. client, Nom, Prénom, Adresse
1,N 0,N INCLURE Quantité 0,N 1,1 PASSER PRODUIT Réf. produit Libellé Prix unitaire COMMANDE Num commande Date Montant CLIENT Réf. client Nom Prénom Adresse

Paramétrage à long terme

Si vous voulez éviter de préciser à chaque fois les mêmes arguments (par exemple un changement de couleurs), vous pouvez placer un fichier params.json dans le répertoire mocodo_notebook. Mocodo peut même vous aider à le faire en exécutant la cellule suivante:

In [9]:
# You may edit and run the following lines
import json, pathlib
params = """
{
  "adjust_width": 1,
  "arrange": null,
  "call_limit": 10000,
  "card_format": "{min_card},{max_card}",
  "colors": "bw",
  "crossover_rate": 0.9,
  "df": "DF",
  "disambiguation": "notes",
  "encodings": [
    "utf8",
    "macroman"
  ],
  "fit": null,
  "flex": 0.75,
  "flip": null,
  "guess_title": false,
  "hide_notes": false,
  "input": "mocodo_notebook/sandbox.mcd",
  "language": "fr",
  "max_generations": 300,
  "max_objective": 15,
  "min_objective": 0,
  "mld": false,
  "mutation_rate": 0.06,
  "no_mcd": false,
  "obfuscate": null,
  "obfuscation_min_distance": 3,
  "organic": false,
  "output_dir": "mocodo_notebook",
  "pdf": false,
  "plateau": 30,
  "png": false,
  "population_size": 1000,
  "print_params": false,
  "relations": [
    "html"
  ],
  "replace": false,
  "restore": false,
  "reuse_geo": false,
  "sample_size": 7,
  "scale": 1,
  "seed": null,
  "shapes": "copperplate",
  "strengthen_card": "_1,1_",
  "timeout": null,
  "title": "Sans titre",
  "verbose": false
}
"""
try:
    json.loads(params)
except:
    raise RuntimeError("Invalid JSON. Check your syntax on https://jsonlint.com.")
pathlib.Path("mocodo_notebook/params.json").write_text(params.strip(), encoding="utf8");

Son évaluation remplace son propre contenu par des lignes de code similaires à:

In [10]:
# You may edit and run the following lines
import json, pathlib
params = """
{
  "adjust_width": 1,
  "arrange": null,
  "call_limit": 10000,
  "card_format": "{min_card},{max_card}",
  "colors": "bw",
  "crossover_rate": 0.9,
  "df": "DF",
  "disambiguation": "notes",
  "encodings": [
    "utf8",
    "macroman"
  ],
  "fit": null,
  "flex": 0.75,
  "flip": null,
  "guess_title": false,
  "hide_notes": false,
  "input": "mocodo_notebook/sandbox.mcd",
  "language": "fr",
  "max_generations": 300,
  "max_objective": 15,
  "min_objective": 0,
  "mld": false,
  "mutation_rate": 0.06,
  "no_mcd": false,
  "obfuscate": null,
  "obfuscation_max_length": null,
  "obfuscation_min_distance": 3,
  "organic": false,
  "output_dir": "mocodo_notebook",
  "pdf": false,
  "plateau": 30,
  "png": false,
  "population_size": 1000,
  "print_params": false,
  "relations": [
    "html"
  ],
  "replace": false,
  "restore": false,
  "reuse_geo": false,
  "sample_size": 7,
  "scale": 1,
  "seed": null,
  "shapes": "copperplate",
  "strengthen_card": "_1,1_",
  "timeout": null,
  "title": "Sans titre",
  "verbose": false
}
"""
try:
    json.loads(params)
except:
    raise RuntimeError("Invalid JSON. Check your syntax on https://jsonlint.com.")
pathlib.Path("mocodo_notebook/params.json").write_text(params.strip(), encoding="utf8");

Modifiez la variable params à votre gré en respectant la syntaxe JSON (attention en particulier au dernier couple clé-valeur, qui n'est pas terminé par une virgule). Exécutez la cellule pour créer un fichier de nom et emplacement adéquats (notez que la valeur de --print_params a été passée à false pour vous éviter de le faire à la main).

Description d'un MCD

Besoins élémentaires

Entités, associations, attributs, identifiants, cardinalités

In [11]:
%%mocodo
CLIENT: Réf. client, Nom, Prénom, Adresse
PASSER, 0N CLIENT, 11 COMMANDE
COMMANDE: Num commande, Date, Montant
INCLURE, 1N COMMANDE, 0N PRODUIT: Quantité
PRODUIT: Réf. produit, Libellé, Prix unitaire
0,N 1,1 PASSER 1,N 0,N INCLURE Quantité CLIENT Réf. client Nom Prénom Adresse COMMANDE Num commande Date Montant PRODUIT Réf. produit Libellé Prix unitaire

La syntaxe ne devrait pas poser problème :

  • une entité est définie par : - son nom,
    • deux-points,
    • sa liste d'attributs séparés par des virgules ;
  • une association est définie par :
    • son nom,
    • virgule,
    • les cardinalités et l'entité distinguée par sa première patte,
    • virgule,
    • les cardinalités et l'entité de sa deuxième patte,
    • etc.,
    • deux-points,
    • sa liste d'attributs séparés par des virgules.

À noter :

  • le premier attribut d'une entité est considéré par défaut comme son identifiant, et donc souligné;
  • pour les associations sans attributs, le deux-points est facultatif;
  • la première ligne:
      %%mocodo
    
    ... ne fait pas partie de la description. Dans ce document, elle permet de faire appel à une « commande magique », qui lance Mocodo sur les lignes qui la suivent. Sauf sous Jupyter Notebook, vous pouvez l'omettre dans votre texte d'entrée. De façon générale, la ou les premières lignes d'un MCD qui commencent par le symbole de pourcentage (%) sont ignorées. Cela permet de placer en en-tête un commentaire qui pourra être préservé lors des éventuels réarrangements ultérieurs.
  • Les accents présents dans votre fichier d'entrée sont correctement gérés pourvu que vous ayez enregistré celui-ci dans l'encodage attendu par Mocodo en entrée: c'est par défaut Unicode UTF-8. Une tolérance existe: si Mocodo échoue à décoder votre fichier avec utf8, il se rabattra sur le codec d'Europe de l'Ouest associé historiquement à votre plateforme: iso-8859-15 pour Windows et Linux, mac-roman pour macOS. Si les accents n'apparaissent pas correctement, vous aurez encore trois solutions:
    1. soit (fortement conseillé), ré-enregistrer votre fichier en UTF-8 au lieu d'un encodage historique;
    2. soit (ponctuellement), passer l'encodage de votre fichier en argument avec --encodings;
    3. soit (à long terme), modifier dans params.json la liste des encodages pris en charge.

Dépendances fonctionnelles entre entités

Lorsque l'une des cardinalités maximales d'une association binaire est 1 (ou à défaut 0), on désigne parfois cette association sous le nom de dépendance fonctionnelle. Certains auteurs la figurent par un cercle portant le symbole DF : cela leur évite de se creuser la tête pour trouver un nom à une association qui disparaîtra corps et bien au moment du passage au relationnel. Enfin, une flèche peut indiquer le sens de la dépendance :

In [12]:
%%mocodo
CLIENT: Réf. client, Nom, Prénom, Adresse
DF, 0N> CLIENT, 11 COMMANDE
COMMANDE: Num commande, Date, Montant
INCLURE, 1N COMMANDE, 0N PRODUIT: Quantité
PRODUIT: Réf. produit, Libellé, Prix unitaire
0,N 1,1 DF 1,N 0,N INCLURE Quantité CLIENT Réf. client Nom Prénom Adresse COMMANDE Num commande Date Montant PRODUIT Réf. produit Libellé Prix unitaire

Si on a plusieurs dépendances fonctionnelles à représenter, on devra suffixer le DF par un chiffre de 0 à 9 (cf. cet exemple).

Associations réflexives

Elles sont quelquefois appelées associations circulaires ou unaires, et dans tous les cas associent un type d'entité à lui-même.

In [13]:
%%mocodo
HOMME: Num. SS, Nom, Prénom
ENGENDRER, 0N HOMME, 11 HOMME
0,N 1,1 ENGENDRER HOMME Num. SS Nom Prénom

Placement sur plusieurs rangées

L'ordre et la séparation des lignes de la description permet de spécifier à coût zéro un plongement grossier, mais qui s'avère en général suffisant:

  • les boîtes (entités et associations) définies sur des lignes consécutives sont tracées sur une même rangée;
  • un saut de ligne indique une nouvelle rangée.
In [14]:
%%mocodo
SCELERISQUE LOREM: blandit, elit, ligula
EROS, 11 SCELERISQUE LOREM, 1N PELLENTESQUE IPSUM: metus, congue

NIBH, 1N SCELERISQUE LOREM, 11 PELLENTESQUE IPSUM
PELLENTESQUE IPSUM: tincidunt, bibendum, consequat, integer
1,1 1,N EROS metus congue 1,N 1,1 NIBH SCELERISQUE LOREM blandit elit ligula PELLENTESQUE IPSUM tincidunt bibendum consequat integer

Les boîtes sont placées aux intersections d'une grille invisible assurant que leurs centres soient alignés aussi bien horizontalement que verticalement. C'est ce qui en général est le plus satisfaisant esthétiquement, mais d'autres retouches peuvent être opérées manuellement dans le fichier de sortie.

Le plongement fait l'objet d'une « compression » horizontale et verticale. Par exemple, ci-dessus, il y a un espace horizontal négatif entre le bord droit de l'entité de gauche et le bord gauche de l'entité de droite.

Besoins plus avancés

Identifiants composites

Préfixer d'un tiret bas (_) les second, troisième, etc. attributs pour les inclure à l'identifiant.

In [15]:
%%mocodo
GRATTE-CIEL: latitude, _longitude, nom, hauteur, année de construction
GRATTE-CIEL latitude longitude nom hauteur année de construction

Flèches sur les pattes

Suffixer d'un chevron (< ou >) les cardinalités de la patte concernée. La direction indiquée se lit en partant de l'association et en allant vers l'entité.

In [16]:
%%mocodo
Peut recevoir, 1N> Groupe sanguin, 1N< Groupe sanguin
Groupe sanguin: type de sang
Appartient, 11> Personne, 0N Groupe sanguin
Personne: Num. SS, Nom, Prénom, Sexe
Engendre, 0N< Personne, 22> Personne
1,N 1,N Peut recevoir 1,1 0,N Appartient 0,N 2,2 Engendre Groupe sanguin type de sang Personne Num. SS Nom Prénom Sexe

La position de la flèche sur la patte peut être réglée individuellement dans l'objet ratio du fichier de géométrie généré (par défaut, sandbox_geo.json) ou sous l'onglet Retouches de la version en ligne. La valeur correspondante peut varier de 0.0 (flèche cachée sous la boîte d'origine) à 1.0 (par défaut, pointe de la flèche au contact du bord de la boîte de destination, compte non tenu de l'arrondi s'il s'agit d'une association).

Styles

Plusieurs styles prédéfinis sont distribués avec l'application. Un style se définit comme la combinaison d'une palette de couleurs (répertoire colors) avec un dictionnaire de polices et de dimensions (répertoire shapes). Un changement d'échelle d'un facteur multiplicatif positif peut être précisé avec l'argument --scale.

Vous pouvez bien sûr créer vos propres styles en vous inspirant des fichiers fournis. Si vous êtes particulièrement content d'un style, soumettez-le pour inclusion dans une prochaine distribution.

Nouveauté de la version 3.0. Une approximation de la largeur des caractères des différentes polices a été pré-calculée sous macOS. Il est possible qu'elle soit inexacte, en particulier sous Windows ou Linux. Dans ce cas, en particulier, les traits de soulignement n'atteindront pas ou excéderont la largeur des libellés soulignés. Vous pouvez contourner le problème en appliquant un facteur multiplicatif avec l'argument --adjust_width).

Types de données

Chaque attribut peut être assorti de notes entre crochets. Ignorées au niveau du tracé du MCD, elles sont interprétées comme des types de données lors de la génération d'un code-source SQL.

Format des cardinalités

Par défaut, les cardinalités sont séparées par une virgule.

Nouveauté de la version 2.1. On peut maintenant opter pour un format quelconque:

In [17]:
%%mocodo --card_format={min_card}/{max_card}
CLIENT: Réf. client, Nom, Prénom, Adresse
PASSER, 0N CLIENT, 11 COMMANDE
COMMANDE: Num commande, Date, Montant
INCLURE, 1N COMMANDE, 0N PRODUIT: Quantité
PRODUIT: Réf. produit, Libellé, Prix unitaire
0/N 1/1 PASSER 1/N 0/N INCLURE Quantité CLIENT Réf. client Nom Prénom Adresse COMMANDE Num commande Date Montant PRODUIT Réf. produit Libellé Prix unitaire

Rectification automatique des cardinalités mal formées

Certaines fautes de frappe fréquentes (inversion des cardinalités minimale et maximale, lettre « O » au lieu du chiffre « 0 ») sont silencieusement rectifiées, d'autres non (lettres « l » ou « I ») :

formes erronées forme rectifiée
O1, o1, 10, 1O, 1o 01
ON, oN, NO, No, N0 0N
On, on, no, nO, n0 0n
N1 1N
n1 1n

Les cardinalités (N,N), qui selon une certaine école dénotent une cardinalité minimale supérieure à 1, sont laissées telles quelles.

In [18]:
%%mocodo
CLIENT: Réf. client, Nom, Prénom, Adresse
PASSER, oN CLIENT, 11 COMMANDE
COMMANDE: Num commande, Date, Montant
INCLURE, lN COMMANDE, ON PRODUIT: Quantité
PRODUIT: Réf. produit, Libellé, Prix unitaire
0,N 1,1 PASSER l,N 0,N INCLURE Quantité CLIENT Réf. client Nom Prénom Adresse COMMANDE Num commande Date Montant PRODUIT Réf. produit Libellé Prix unitaire

Symbole de dépendance fonctionnelle

Il est possible d'activer l'encerclement d'un autre sigle que DF. C'est ce sigle qui devra alors apparaître en entrée, par exemple:

In [19]:
%%mocodo --df=CIF
CLIENT: Réf. client, Nom, Prénom, Adresse
CIF, 0N CLIENT, 11 COMMANDE
COMMANDE: Num commande, Date, Montant
INCLURE, 1N COMMANDE, 0N PRODUIT: Quantité
PRODUIT: Réf. produit, Libellé, Prix unitaire
0,N 1,1 CIF 1,N 0,N INCLURE Quantité CLIENT Réf. client Nom Prénom Adresse COMMANDE Num commande Date Montant PRODUIT Réf. produit Libellé Prix unitaire

Comme le cercle est alors un peu plus grand, on peut vouloir régler (a priori une fois pour toutes) le ratio défini dans l'objet shapes du fichier appelé par défaut sandbox_geo.json):

"df_text_height_ratio" : 1.00,

Création de plusieurs entités ou associations de même nom

Normalement on doit choisir des noms différents pour toutes les boîtes (entités et associations) du MCD, à l'exception des associations de dépendance fonctionnelle figurées par un sigle. On a vu que dans ce cas, il suffisait d'ajouter à leur nom un chiffre de 0 à 9 : celui-ci n'apparaîtra pas en sortie.

Cette possibilité vaut pour n'importe quelle boîte, y compris les triangles dénotant l'héritage (p. ex. /1\ ou /XT2\).

Seul le dernier chiffre est concerné. Cela limite à 10 le nombre d'entités ou associations homonymes, mais peut être utile si vous avez besoin, pour une raison ou une autre, qu'un suffixe numérique apparaisse dans le nom d'une boîte. Il suffit alors d'ajouter encore un chiffre à celui-ci.

In [20]:
%%mocodo
Agent 0070: bar
DF42, 11 Agent 0070, 1N Agent1
Agent1: bar
1,1 1,N DF4 Agent 007 bar Agent bar

La création de boîtes homonymes servira typiquement à « distribuer » une entité DATE réduite à son identifiant date, mais associée à de nombreuses entités qui n'ont rien à voir entre elles. Sachant qu'une telle entité est amenée à disparaître lors du passage au relationnel, il n'y a aucun inconvénient à en créer plusieurs, et cela peut avoir l'avantage de faciliter (ou même de rendre possible) l'obtention d'une bonne mise en page.

Par exemple, la mise en page du MCD suivant est indûment complexifiée par le haut degré de l'entité DATE.

In [21]:
%%mocodo
:
Rhoncus: dolor a, bibendum, euismod, consectetuer, leo
Porttitor, 1N Rhoncus, 1N Curabitur
:
:

Ultricies, 11 Rhoncus, 0N Egestas
Imperdiet, 0N Egestas, 0N Curabitur, 0N DATE
Curabitur: blandit, suscipit
Mollis, 0N Curabitur, 0N Curabitur
:

:
Egestas: vivamus, semper, aliquam
Pharetra, 0N Curabitur, 0N DATE, 0N Vitae justo: massa
Vitae justo: lobortis, purus
adipiscing, 0N Curabitur, 0N Vitae justo, 0N DATE

:
:
DATE: date
:
:
1,N 1,N Porttitor 1,1 0,N Ultricies 0,N 0,N 0,N Imperdiet 0,N 0,N Mollis 0,N 0,N 0,N Pharetra massa 0,N 0,N 0,N adipiscing Rhoncus dolor a bibendum euismod consectetuer leo Curabitur blandit suscipit Egestas vivamus semper aliquam Vitae justo lobortis purus DATE date

Ajouter une autre entité DATE (sous le nom de DATE2) permettra à Mocodo de calculer une mise en page à la fois plus agréable à l'œil et plus compacte (à savoir, $4\times3$ au lieu de $5\times4$). La sémantique est inchangée.

In [22]:
%%mocodo
Egestas: vivamus, semper, aliquam
DATE: date
Pharetra, 0N Curabitur, 0N DATE, 0N Vitae justo: massa
Vitae justo: lobortis, purus

Ultricies, 11 Rhoncus, 0N Egestas
Imperdiet, 0N Egestas, 0N Curabitur, 0N DATE
Curabitur: blandit, suscipit
adipiscing, 0N Curabitur, 0N Vitae justo, 0N DATE2

Rhoncus: dolor a, bibendum, euismod, consectetuer, leo
Porttitor, 1N Rhoncus, 1N Curabitur
Mollis, 0N Curabitur, 0N Curabitur
DATE2: date
0,N 0,N 0,N Pharetra massa 1,1 0,N Ultricies 0,N 0,N 0,N Imperdiet 0,N 0,N 0,N adipiscing 1,N 1,N Porttitor 0,N 0,N Mollis Egestas vivamus semper aliquam DATE date Vitae justo lobortis purus Curabitur blandit suscipit Rhoncus dolor a bibendum euismod consectetuer leo DATE date

Extensions du modèle

Entités faibles (ou identification relative)

Préfixer d'un tiret bas (_) une cardinalité (1,1) pour indiquer que l'entité distinguée est faible. Dans le diagramme, les identifiants (ou discriminants) d'une telle entité seront soulignés en pointillés, tandis que le (1,1) sera souligné d'un trait plein.

In [23]:
%%mocodo
ŒUVRE: Cote œuvre, Titre, Date parution
DF, 1N ŒUVRE, _11 EXEMPLAIRE
EXEMPLAIRE: Num. exemplaire, État du livre, Date d'achat
1,N 1,1 DF ŒUVRE Cote œuvre Titre Date parution EXEMPLAIRE Num. exemplaire État du livre Date d’achat

Nouveauté de la version 2.1. Traditionnellement, l'identification relative est dénotée par des parenthèses autour des cardinalités. Cette notation (ou toute autre) peut maintenant être obtenue avec l'option --strenghten_card:

In [24]:
%%mocodo --strengthen_card (R)1,1
ŒUVRE: Cote œuvre, Titre, Date parution
DF, 1N ŒUVRE, _11 EXEMPLAIRE
EXEMPLAIRE: Num. exemplaire, État du livre, Date d'achat
1,N (R)1,1 DF ŒUVRE Cote œuvre Titre Date parution EXEMPLAIRE Num. exemplaire État du livre Date d’achat

Une association ne peut renforcer plus d'une entité faible. Ainsi, une erreur se produit si l'on remplace le 1N par _11:

In [25]:
%%mocodo
ŒUVRE: Cote œuvre, Titre, Date parution
DF, _11 ŒUVRE, _11 EXEMPLAIRE
EXEMPLAIRE: Num. exemplaire, État du livre, Date d'achat
Mocodo Err.22 - Identification relative réciproque autour de « DF ».

Visualisation des contraintes sur les associations

Nouveauté de la version 3.2. Certains utilisateurs avancés de Mocodo ont besoin d'exprimer au niveau conceptuel les contraintes sur associations introduites par Merise 2. Jusqu'ici, ils devaient utiliser un éditeur graphique pour ajouter « à la main » les éléments correspondants. Ils peuvent dorénavant le faire sous Mocodo. Attention, la prise en charge de ces extensions est purement visuelle : le passage au niveau relationnel et/ou physique les ignorera.

Des ronds

D'un point de vue purement visuel, donc, une telle contrainte est figurée par un petit rond portant jusqu'à trois lettres:

In [26]:
%%mocodo
(): 20, 45
(Z): 30, 30
(ZZ): 50, 15
(ZZZ): 80, 10

:

:
    
:

:

Lorem ipsum: lorem, ipsum
Z ZZ ZZZ Lorem ipsum lorem ipsum

La syntaxe nécessite quelques explications.

  1. Au contraire des boîtes (entités et associations), les contraintes ne sont pas... contraintes par la grille sous-jacente : la mise en page du MCD n'en tient absolument pas compte. Celui de cet exemple a donc dû être « aéré » pour leur faire de la place : ainsi, les quatre paragraphes réduits à un deux-points ont inséré quatre rangées au début de la grille.
  2. Le couple de nombres qui termine chaque définition de contrainte correspond aux pourcentages de la largeur et de la hauteur (respectivement) du diagramme où centrer cette contrainte. Si les deux sont identiques, un seul peut être fourni.
  3. De tout cela, il résulte que le positionnement des contraintes est plutôt de l'ordre de la retouche : ne vous en occupez pas tant que les boîtes risquent de bouger.
  4. Les clauses de définition les contraintes peuvent apparaître n'importe où. Notez cependant que tout réarrangement automatique les enverra systématiquement à la fin du texte-source.

De la même manière qu'avec les cardinalités, on peut insérer un court texte entre crochets qui apparaîtra au survol de la contrainte.

In [27]:
%%mocodo
() [adipiscing elit]: 20, 45
(Z) [sed do eiusmod]: 30, 30
(ZZ) [tempor incididunt] : 50, 15
(ZZZ) [ut labore]: 80, 10

:

:
    
:

:

Consectetur: lorem ipsum, dolor sit amet
Z ZZ ZZZ Consectetur lorem ipsum dolor sit amet

Des traits

Les contraintes sont normalement liées par des traits pleins (--) ou pointillés (..) à un certain nombre de boîtes (entités ou associations). Une flèche (> ou <) peut être ajoutée ou substituée à l'une et/ou l'autre des extrémités d'un trait.

In [28]:
%%mocodo
(A) --Lorem, ..Ipsum, -Dolor: 30, 10
(B) ->Dolor, <-->Sit, -->Amet: 69, 10

:

:

Lorem: lorem, ipsum
Ipsum, XX Lorem, XX Dolor
Dolor: dolor, sit
Sit, XX Dolor, XX Amet
Amet: consectetur, adipiscing
A B Ipsum Sit Lorem lorem ipsum Dolor dolor sit Amet consectetur adipiscing

Exemple

Voici un exemple plus réaliste, adapté de la Fig. 7.37 de Merise, deuxième génération (Dominique Nanci et Bernard Espinasse, 4e éd., 2001) :

In [29]:
%%mocodo
:::::
Dépôt: num dépôt, surface

:
Louer, 11 Commande, 0N Dépôt
:::
Stocker, 1N Dépôt, 1N Article: quantité

Commande: num. commande, date
Composer, 1N Commande, 0N Article
:::
Article: réf. article, prix

(I) ->Stocker, ..Dépôt, ..Article, --Composer, --Louer
I 1,1 0,N Louer 1,N 1,N Stocker quantité 1,N 0,N Composer Dépôt num dépôt surface Commande num. commande date Article réf. article prix

Notez que les ratios de positionnement sont manquants. Dans ce cas, le moteur de plongement fait coïncider le centre de chaque contrainte avec le barycentre des boîtes qu'elle met en jeu. Le positionnement ainsi défini a plus de chances de rester correct si le MCD évolue.

Boîtes fictives et traits invisibles

On peut tirer parti de ce mécanisme en intégrant (fictivement) d'autres boîtes à la définition de la contrainte, ou même en en répétant certaines. Dans ces deux cas, bien entendu, le trait devra être rendu invisible (il suffit de l'omettre). Par exemple, intégrer l'entité Commande et répéter l'association Stocker permet de réduire la largeur du MCD sans compromettre sa lisibilité. Ci-dessous, on a en outre indenté la définition de la contrainte pour la placer sur un second calque :

In [30]:
%%mocodo
:::
Dépôt: num dépôt, surface

:
Louer, 11 Commande, 0N Dépôt
:
Stocker, 1N Dépôt, 1N Article: quantité

Commande: num. commande, date
Composer, 1N Commande, 0N Article
:
Article: réf. article, prix

  (I) ->Stocker, ..Dépôt, ..Article, --Composer, --Louer, Commande, Stocker
I 1,1 0,N Louer 1,N 1,N Stocker quantité 1,N 0,N Composer Dépôt num dépôt surface Commande num. commande date Article réf. article prix

Redisons-le : à l'heure actuelle (19h05), seul l'aspect graphique des contraintes est implanté. L'éventuel aspect relationnel de certains types de contrainte est déjà pris en charge par Mocodo, mais d'une autre manière. C'est ce que nous allons voir dans les deux sections suivantes.

Agrégation (ou pseudo-entité)

Problématique

Le MCD ci-dessous a (au moins) un défaut :

In [31]:
%%mocodo --mld
Date: Date
Réserver, 1N Client, 1N Chambre, 0N Date: Durée
Chambre: Numéro, Prix

Client: Id. client
1,N 1,N 0,N Réserver Durée Date Date Chambre Numéro Prix Client Id. client
Chambre ( Numéro, Prix )
Réserver ( Id. client, #Numéro, Date, Durée )

Il n'empêche pas les « sur-réservations » : deux clients peuvent réserver la même chambre pour la même nuit. En effet, deux réservations sont complètement identifiées avec les mêmes date et numéro de chambre dès lors que le nom du client est différent.

Solution possible

La notion d'agrégation vient à la rescousse. Elle permet d'agréger les entités DATE et CHAMBRE, ainsi que l'association RÉSERVER, en une « pseudo-entité » qui sera alors considérée comme associée à l'entité CLIENT.

Syntaxiquement, il suffit de préfixer la cardinalité de CLIENT d'une barre oblique (avant la version 3, cela se faisait en préfixant le nom de l'entité et non sa cardinalité) :

In [32]:
%%mocodo --mld
Date: Date
Réserver, /1N Client, 1N Chambre, 0N Date: Durée
Chambre: Numéro, Prix

Client: Id. client
1,N 1,N 0,N Réserver Durée Date Date Chambre Numéro Prix Client Id. client
Chambre ( Numéro, Prix )
Réserver ( #Numéro, Date, Id. client, Durée )

Cette visualisation elle-même est une nouveauté de la version 3. Notez que la représentation traditionnelle demanderait à insérer une association DF entre CLIENT et RÉSERVER, ce qui donnerait ceci :

In [33]:
display.SVG("traditional_cluster.svg")
Out[33]:
1,N 1,N 0,N 1,1 Réserver Durée 1,N DF Date Date Chambre Numéro Prix Client Nom

... mais permettre l'association d'une entité et d'une association demanderait à apporter au code de Mocodo des changements conséquents, pour un bénéfice qui ne nous saute pas forcément aux yeux.

Autre solution : CIF

Cette situation s'exprime également à l'aide de la notion de contrainte sur associations, et plus précisément de contrainte d'intégrité fonctionnelle. À partir de la version 3.2, on pourra donc choisir d'écrire :

In [34]:
%%mocodo --mld
Date: Date
Réserver, /1N Client, 1N Chambre, 0N Date: Durée
Chambre: Numéro, Prix

:
    
Client: Id. client

(CIF) [Même date, même chambre => un seul client] --Chambre, --Date, ->Client, ..Réserver: 20, 75
CIF 1,N 1,N 0,N Réserver Durée Date Date Chambre Numéro Prix Client Id. client
Chambre ( Numéro, Prix )
Réserver ( #Numéro, Date, Id. client, Durée )

Lorsque Mocodo rencontre une définition de CIF dans le texte-source, il désactive par politesse sa visualisation des pseudo-entités. Mais c'est toujours le /1N Client qui permet d'obtenir le schéma relationnel attendu : pensez à le mettre.

Autre solution : entité faible

Notez qu'on peut se passer de la notion d'agrégation dès lors que l'on a celle d'entité faible. Le même MCD pourrait se représenter ainsi :

In [35]:
%%mocodo
Date: Date
DF1, 0N Date, _11 Réserver
Réserver: _Durée
DF2, 0N Chambre, _11 Réserver
Chambre: Numéro, Prix
  
DF3, 11 Réserver, 1N Client

Client: Id. client
0,N 1,1 DF 0,N 1,1 DF 1,1 1,N DF Date Date Réserver Durée Chambre Numéro Prix Client Id. client

Compléments

Sous Mocodo, l'agrégation est traitée comme un cas particulier de ce que nous appelons une réduction de clé primaire. Le mécanisme est décrit ici).

Rien ne nous empêche par exemple de créer un agrégat réduit à une seule entité :

In [36]:
%%mocodo
LACUS: blandit, elit
LIGULA, 0N LACUS, /1N EROS: metus
EROS: congue, nibh, tincidunt
0,N 1,N LIGULA metus LACUS blandit elit EROS congue nibh tincidunt

Pour en revenir à la représentation graphique :

  • Apparaissent en pointillés la ou les pattes par lesquelles les identifiants vont migrer en perdant leur caractère identifiant.
  • Une enveloppe de points apparaît autour de l'association et des entités de l'agrégat dans les cas où :
    • il y a au maximum deux entités à agréger ;
    • l'angle formé par l'association et les entités est plat ou rectangle.
In [37]:
%%mocodo
EROS: congue, nibh, tincidunt
LIGULA, 0N LACUS, /1N EROS, 0N TELLUS: metus
TELLUS: integer, odio

LACUS: blandit, elit
0,N 1,N 0,N LIGULA metus EROS congue nibh tincidunt TELLUS integer odio LACUS blandit elit

Si ces conditions ne sont pas réunies, pour des raisons de simplicité du code et de clarté du diagramme, l'enveloppe n'est pas affichée. Cependant, les pointillés de la ou des pattes concernées subsistent et le reste des traitements est inchangé.

In [38]:
%%mocodo
TELLUS: integer, odio

CONSEQUAT: fermentum, dederit
LIGULA, 0N LACUS, /1N EROS, 0N TELLUS, 0N CONSEQUAT: metus
LACUS: blandit, elit

EROS: congue, nibh, tincidunt
0,N 1,N 0,N 0,N LIGULA metus TELLUS integer odio CONSEQUAT fermentum dederit LACUS blandit elit EROS congue nibh tincidunt

Conversion forcée d'une association DF en table

Normalement, les associations DF disparaissent lors du passage en relationnel. Il est cependant possible de forcer la création d'une table éponyme. Cela se fait en mettant entre crochets droits le nom de l'association (avant la version 3, on préfixait d'une barre oblique l'une au moins des entités non distinguées par un (0,1)).

Au niveau visualisation, un rectangle en pointillés apparaît autour de l'association, indiquant que celle-ci va devenir une table.

In [39]:
%%mocodo
LACUS: blandit, elit
[LIGULA], 01 LACUS, 1N EROS: metus
EROS: congue, nibh, tincidunt
0,1 1,N LIGULA metus LACUS blandit elit EROS congue nibh tincidunt

La motivation et les détails sont discutés dans la section Passage au relationnel / Conversion forcée d'une association DF en table.

Héritage (ou spécialisation)

Introduction

L'héritage permet de regrouper dans une entité, dite « mère », les attributs communs à plusieurs autres entités, dites « filles », qui se distinguent les unes des autres par des attributs spécifiques.

La syntaxe Mocodo est la suivante :

/\ Mère <- Fille_1, Fille_2, ... : type

Où :

  • Mère est une entité normale ;
  • _Fille1, _Fille2, etc. sont des entités sans identifiant (inutile de les préfixer par un tiret bas, il serait ignoré) ;
  • le « triangle » définit le type d'héritage, soit /\, soit /X\, soit /T\, soit /XT\ (éventuellement suffixé par un chiffre de 0 à 9, p. ex. /1\ ou /XT2\) ;
  • la « flèche » définit le mécanisme de passage au relationnel, soit <=, soit <-, soit ->, soit =>. Reportez-vous à cette section ;
  • le type (facultatif) n'apparaît pas sur le MCD, mais éventuellement, lors du passage au relationnel, dans la liste des champs de la table-mère ou, en cas de suppression de celle-ci, des tables dans lesquelles migre son identifiant. Il permet de préciser à laquelle des entités-filles on a affaire.

Voici un exemple :

In [40]:
%%mocodo
Personne: num SS, nom, prénom

/XT\ Personne <- Homme, Femme: sexe

Homme: 
:
Femme: nom de jeune fille
XT Personne num SS nom prénom Homme Femme nom de jeune fille

Les quatre types d'héritage

Selon les symboles inscrits dans le triangle, le MCD précédent s'interprétera ainsi :

Totalité Exclusion Symboles Exemple de population Toute personne est :
oui oui /XT\ ♂♂♂♂♂♂♂
♀♀♀♀♀♀♀♀♀♀
- soit un homme
- soit une femme
non oui /X\ ♂♂♂♂♂♂♂♂
♀♀♀♀♀♀
⚬⚬⚬⚬
- soit un homme
- soit une femme
- soit aucun des deux
oui non /T\ ♂♂♂♂♂♂
♀♀♀♀♀♀♀♀
⚥⚥⚥⚥
- soit un homme
- soit une femme
- soit les deux à la fois
non non /\ ♂♂♂♂♂
♀♀♀♀♀♀
⚬⚬⚬⚬
⚥⚥⚥⚥
- soit un homme
- soit une femme
- soit aucun des deux
- soit les deux à la fois

Ces contraintes ne sont pas transposables au niveau relationnel, mais pourront être réinjectées au niveau physique (même si Mocodo ne le fait pas actuellement).

Représentation graphique

Le type de flèche spécifiant le mécanisme de passage au modèle relationnel (<=, <-, -> ou =>) fait par défaut l'objet d'une visualisation dès le modèle conceptuel : la ou les pattes vers les entités de destination des attributs migrants sont orientées vers celles-ci ; et la ou les autres pattes sont doublées (pour <= et =>) ou non (pour <- et ->).

In [41]:
%%mocodo --mld
Personne: num SS, nom, prénom

/XT\ Personne => Homme, Femme: sexe

Homme: 
:
Femme: nom de jeune fille
XT Personne num SS nom prénom Homme Femme nom de jeune fille
Femme ( num SS, nom, prénom, nom de jeune fille )
Homme ( num SS, nom, prénom )

Cette visualisation n'est pas conventionnelle : par défaut, on se borne à ajouter une flèche dirigée vers l'entité-mère. Pour désactiver l'embellissement opéré par Mocodo, sans pour autant changer le mécanisme de passage au relationnel, répétez simplement le deuxième caractère de la flèche : <==, <--, ->> ou =>>.

In [42]:
%%mocodo --mld
Personne: num SS, nom, prénom

/XT\ Personne =>> Homme, Femme: sexe

Homme: 
:
Femme: nom de jeune fille
XT Personne num SS nom prénom Homme Femme nom de jeune fille
Femme ( num SS, nom, prénom, nom de jeune fille )
Homme ( num SS, nom, prénom )

Besoins spécifiques à la pédagogie

Si vous n'êtes pas enseignant de bases de données, vous pouvez passer directement à la section suivante.

SVG interactifs

Afficher l'explication des cardinalités

Les débutants ont souvent des doutes sur la sémantique de telle ou telle cardinalité. Cette information peut désormais être incluse dans le texte-source, en annotant les pattes correspondantes, pour apparaître à la demande lors du rendu (utile pour créer des exercices à faire en TD ou en autonomie).

Survolez les cardinalités du MCD ci-dessous pour faire apparaître leur description.

In [43]:
%%mocodo
CLIENT: Réf. client, Nom, Prénom, Adresse
PASSER, 0N [Un client peut passer un nombre quelconque de commandes.] CLIENT, 11 [Toute commande est passée par un en un seul client.] COMMANDE
COMMANDE: Num commande, Date, Montant
INCLURE, 1N [Une commande peut inclure plusieurs produits distincts, et en inclut au moins un.] COMMANDE, 0N [Certains produits ne sont jamais commandés, d'autres le sont plusieurs fois.] PRODUIT: Quantité
PRODUIT: Réf. produit, Libellé, Prix unitaire
0,N 1,1 PASSER 1,N 0,N INCLURE Quantité CLIENT Réf. client Nom Prénom Adresse COMMANDE Num commande Date Montant PRODUIT Réf. produit Libellé Prix unitaire

Les notes s'insèrent entre cardinalités et nom de l'entité. Elles sont délimitées par des crochets droits.

Avec l'option --disambiguation=notes (par défaut), elles sont également exploitables lors du passage au relationnel pour préciser la sémantique d'une clé étrangère.

L'affichage est désactivé avec l'option --hide_notes.

Limitations.

  • Non pris en charge par les éditeurs de SVG comme Inkscape.
  • Ne semble pas fonctionner dans une page HTML statique (comme la version HTML de ce document sous GitHub).
  • Nécessite de faire confiance à un notebook (Trust notebook) pour s'afficher à la réouverture.

Dévoiler un MCD par étapes

Nouveauté de la version 3. Il est possible de faire apparaître progressivement les différentes « boîtes » constituant un MCD. Pour cela, il suffit d'indenter (décaler vers la droite à l'aide d'espaces ou de tabulations) au moins une ligne. Les éléments correspondants seront alors répartis sur autant de « calques » qu'il y a de niveaux d'indentations.

Voici par exemple un exercice consistant en la description du « réel perçu » d'une entreprise de VPC :

  1. Un produit est connu par une référence, un libellé et un prix unitaire.
  2. Toute commande inclut un produit ou plusieurs, chacun en une certaine quantité.
  3. Un client peut passer zéro (client potentiel) ou plusieurs commandes.
  4. Un client peut entrer dans la base par parrainage d'un autre client.

L'enseignant peut le présenter pas à pas en suivant les étapes de l'énoncé :

In [44]:
%%mocodo  --colors ocean --shapes copperplate

      Parrainer, 01 Client, 0N Client : date parrainage
Produit: Réf. produit, Libellé, Prix unitaire
  Inclure, 1N Commande, 0N Produit: Quantité
 
    Client: Réf. client, Nom, Prénom, Adresse
    DF, 0N Client, 11 Commande
  Commande: Num Commande, Date, Montant
0,1 0,N Parrainer date parrainage 1,N 0,N Inclure Quantité 0,N 1,1 DF Produit Réf. produit Libellé Prix unitaire Client Réf. client Nom Prénom Adresse Commande Num Commande Date Montant

Remarques.

  • Pas de règle sur la taille de l'indentation. Pour Mocodo, autant de niveaux d'indentation distincts, autant de calques.
  • Pour ajouter facilement de l'interactivité à un MCD existant :
    1. commencez par indenter au maximum toutes les lignes ;
    2. effacez l'indentation des lignes du premier calque ;
    3. décalez votre curseur de $n$ caractères vers la droite ;
    4. placez-vous tour à tour sur les lignes à intégrer au deuxième calque et effacez les espaces surnuméraires ;
    5. recommencez à l'étape 3 jusqu'au dernier calque.
  • Les différents calques sont codés directement dans le SVG. L'interaction ne nécessite donc aucun logiciel spécifique.
  • Sous Mocodo online, le MCD est toujours présenté entièrement dévoilé. Cela permet de voir directement le résultat d'une modification du texte-source.

Limitations actuelles.

  • Pas de granularité plus fine que la ligne (entité ou association avec toutes ses pattes et cardinalités).
  • Pas de prise en charge des touches directionnelles. Cela serait sans doute possible, mais difficilement compatible avec la présence de plusieurs MCD interactifs sur une même page (comme dans cette documentation).

Éviter qu'une interaction sur un SVG ne s'applique à un autre

Nouveauté de la version 3.1.1. Dans un cas très rare, à savoir lorsque plusieurs SVG interactifs générés à partir du même texte-source coexistent sur une même page web (ou dans le même notebook), une interaction opérée sur l'un s'applique également à tous les autres. Par exemple, cliquer sur l'un des ronds gris de l'une des figures ci-dessous agira sur les deux figures :

In [45]:
%%mocodo
FOO: foo
  BAR: bar
FOO foo BAR bar
In [46]:
%%mocodo
FOO: foo
  BAR: bar
FOO foo BAR bar

Ce problème trahit une « collision » : différents éléments du DOM se sont vus attribuer la même empreinte (obtenue par hachage du texte-source). La solution est de passer un entier discriminant qui, par concaténation, fera de ces empreintes de véritables identifiants.

In [47]:
%%mocodo --uid_suffix 1
FOO: foo
  BAR: bar
FOO foo BAR bar
In [48]:
%%mocodo --uid_suffix 2
FOO: foo
  BAR: bar
FOO foo BAR bar

Créer un MCD à compléter

Les MCD à trous sont des exercices classiques d'introduction aux bases de données.

Supprimer le marquage d'un identifiant

Pour éviter le marquage automatique du premier attribut d'une entité comme identifiant, il suffit de le préfixer par un tiret bas (_) : ce caractère est donc un commutateur, qui souligne un attribut non souligné par défaut, et désouligne un attribut souligné par défaut.

In [49]:
%%mocodo
CLIENT: _Réf. client, Nom, Prénom, Adresse
PASSER, 0N CLIENT, 11 COMMANDE
COMMANDE: _Num commande, Date, Montant
INCLURE, 1N COMMANDE, 0N PRODUIT: Quantité
PRODUIT: _Réf. produit, Libellé, Prix unitaire
0,N 1,1 PASSER 1,N 0,N INCLURE Quantité CLIENT Réf. client Nom Prénom Adresse COMMANDE Num commande Date Montant PRODUIT Réf. produit Libellé Prix unitaire

Masquer un couple de cardinalités

Vous pouvez masquer n'importe quelles cardinalités en les remplaçant pas XX (ci-dessous à gauche) ou (nouveauté de la version 3.2) en les préfixant d'un - (ci-dessous à droite).

In [50]:
%%mocodo
CLIENT: Réf. client, Nom, Prénom, Adresse
PASSER, XX CLIENT, XX COMMANDE
COMMANDE: Num commande, Date, Montant
INCLURE, -1N COMMANDE, -0N PRODUIT: Quantité
PRODUIT: Réf. produit, Libellé, Prix unitaire
PASSER INCLURE Quantité CLIENT Réf. client Nom Prénom Adresse COMMANDE Num commande Date Montant PRODUIT Réf. produit Libellé Prix unitaire

Masquer un attribut

Vous pouvez mettre deux virgules consécutives pour réserver la place d'un attribut manquant.

Les espaces insécables sont préservés, ce qui permet de réserver plus d'espace horizontal, cf. ci-dessous premier attribut vide de INCLURE.

In [51]:
%%mocodo
CLIENT: Réf. client, , , 
PASSER, XX CLIENT, XX COMMANDE
COMMANDE: , Date, Montant
INCLURE, 1N COMMANDE, 0N PRODUIT: Quantité,                    , , ,
PRODUIT: Réf. produit, Libellé, Prix unitaire
PASSER 1,N 0,N INCLURE Quantité                    CLIENT Réf. client COMMANDE Date Montant PRODUIT Réf. produit Libellé Prix unitaire

Ne faire apparaître que le squelette du schéma conceptuel

Enfin, vous pouvez transformer en exercice à trous n'importe quel MCD en rendant complètement transparentes les couleurs des attributs, associations et cardinalités. Le style blank a été prédéfini à cet effet:

In [52]:
%%mocodo --colors=blank
CLIENT: Réf. client, Nom, Prénom, Adresse
PASSER, 0N CLIENT, 11 COMMANDE
COMMANDE: Num commande, Date, Montant
INCLURE, 1N COMMANDE, 0N PRODUIT: Quantité
PRODUIT: Réf. produit, Libellé, Prix unitaire
0,N 1,1 PASSER 1,N 0,N INCLURE Quantité CLIENT Réf. client Nom Prénom Adresse COMMANDE Num commande Date Montant PRODUIT Réf. produit Libellé Prix unitaire

Attention, n'utilisez pas cette méthode si vous souhaitez diffuser l'exercice sous forme électronique: l'information textuelle est toujours présente, susceptible d'être sélectionnée et collée ailleurs pour être lue. Vous pouvez bien sûr empêcher cette possibilité en convertissant la figure dans un format bitmap (comme PNG); mais le plus simple est de combiner les deux méthodes précédentes:

In [53]:
%%mocodo
CLIENT: ,          ,,
PASSER, XX CLIENT, XX COMMANDE
COMMANDE: ,               ,
INCLURE, XX COMMANDE, XX PRODUIT: 
PRODUIT: ,            ,
PASSER INCLURE CLIENT           COMMANDE                PRODUIT            

Remplacer tous les libellés par du faux-texte (obfuscation)

L'obfuscation d'un MCD consiste à vider celui-ci de sa sémantique de surface, en substituant des chaînes aléatoires à tous les libellés. Le résultat sera par exemple utilisé pour montrer que les principales règles de passage du schéma conceptuel au schéma relationnel peuvent être appliquées « bêtement », c'est-à-dire sans comprendre le fonctionnement de l'organisme modélisé.

Ainsi, dans l'exemple ci-dessous, les libellés du MCD CLIENT-COMMANDE-PRODUIT sont remplacés par des mots tirés au hasard:

In [54]:
%%mocodo --obfuscate --seed=1
CLIENT: Réf. client, Nom, Prénom, Adresse
PASSER, 0N CLIENT, 11 COMMANDE
COMMANDE: Num commande, Date, Montant
INCLURE, 1N COMMANDE, 0N PRODUIT: Quantité
PRODUIT: Réf. produit, Libellé, Prix unitaire
%%mocodo
LACUS: Fusce, Diam, Felis, Aliquam
SCELERISQUE, 0N LACUS, 11 AMET
AMET: Nulla, Erat, Risus
DIGNISSIM, 1N AMET, 0N METUS: Ligula
METUS: Pulvinar, Placerat, Hendrerit
0,N 1,1 SCELERISQUE 1,N 0,N DIGNISSIM Ligula LACUS Fusce Diam Felis Aliquam AMET Nulla Erat Risus METUS Pulvinar Placerat Hendrerit

Nouveauté de la version 2.0.20. Pour remplacer le texte de la cellule par le résultat de son évaluation, ajoutez l'option --replace.

En argument, vous pouvez ajouter le chemin d'un fichier texte UTF-8 quelconque où puiser les mots de substitution. Par exemple, le texte du README de ce projet:

In [55]:
%%mocodo --obfuscate=../README.md --seed=42 --no_mcd
CLIENT: Réf. client, Nom, Prénom, Adresse
PASSER, 0N CLIENT, 11 COMMANDE
COMMANDE: Num commande, Date, Montant
INCLURE, 1N COMMANDE, 0N PRODUIT: Quantité
PRODUIT: Réf. produit, Libellé, Prix unitaire
%%mocodo
OCCUPE: Évoluer, Diagram, Tutoriel, Description
LIGNE, 0N OCCUPE, 11 DATA
DATA: Pièce, Augmentera, Plongement
SORTIE, 1N DATA, 0N NOUVEL: Informations
NOUVEL: Rien, Jupyter, Mocodo

Mocodo essaie d'abord de trouver ce fichier à l'endroit indiqué. En cas d'échec, il le cherche (avec extension .txt facultative) parmi les textes distribués avec le logiciel, à savoir:

  • "lorem_ipsum.txt": le faux-texte le plus courant.
  • "disparition.txt": le lexique du célèbre roman lipogrammatique de Georges Perec.
  • "four_letter_words.txt": une sélection (SFW) de mots anglais de quatre lettres.

En cas de nouvel échec, il se rabat sur "lorem_ipsum.txt".

Notez enfin que l'algorithme s'assure que la distance de Damerau-Levenshtein entre deux libellés de substitution quelconques est d'au moins 3 (valeur par défaut du paramètre obfuscation_min_distance). En clair, cela signifie que, si vous donnez en examen un exercice de conversion en relationnel basé sur un tel MCD, les erreurs de transcription d'un étudiant stressé, inattentif, illettré, dyslexique, roublard, ou tout cela à la fois, ne devraient pas vous empêcher de retrouver son intention première.

Nouveautés de la version 3.

  • L'option --obfuscation_max_length est supprimée ; inversement, la taille minimale d'un mot de substitution est fixée (en dur) à 3.
  • L'option --seed fonctionne quelle que soit la version de Python.

Créer une vue en extension

La technique de duplication vue plus haut peut servir à produire une vue en extension d'un MCD. Voici par exemple le MCD que j'utilise en cours pour introduire la notion d'entité faible (à gauche, vue en compréhension, à droite vue en extension):

In [56]:
%%mocodo
ŒUVRE1: cote, titre, date de publication
:::
ŒUVRE2: 612.NAT.34, J'apprends à lire à mes souris blanches, mai 1975
:
  
DF1, 1N ŒUVRE1, _11 EXEMPLAIRE1
::
DF2, XX ŒUVRE2, XX EXEMPLAIRE2
DF3, XX ŒUVRE2, XX EXEMPLAIRE3
DF4, XX ŒUVRE2, XX EXEMPLAIRE4

EXEMPLAIRE1: numéro d'exemplaire, état, date d'achat
::
EXEMPLAIRE2: 1, bon état, 12/6/1975
EXEMPLAIRE3: 2, bon état, 1/8/1977
EXEMPLAIRE4: 3, reliure rongée, 3/4/2005
1,N 1,1 DF DF DF DF ŒUVRE cote titre date de publication ŒUVRE 612.NAT.34 J’apprends à lire à mes souris blanches mai 1975 EXEMPLAIRE numéro d’exemplaire état date d’achat EXEMPLAIRE 1 bon état 12/6/1975 EXEMPLAIRE 2 bon état 1/8/1977 EXEMPLAIRE 3 reliure rongée 3/4/2005

Mocodo n'interdit pas la conversion en relationnel d'un tel MCD, mais celle-ci n'a aucun sens.

Nouveauté de la version 3.2. Pour préserver la sémantique des cardinalités sans les afficher, il est maintenant possible de les préfixer d'un - (« moins »). Le résultat de la conversion en relationnel peut alors être interprété comme l'ensemble des lignes des différentes tables.

In [57]:
%%mocodo --mld
ŒUVRE: 612.NAT.34, J'apprends à lire à mes souris blanches, mai 1975
  
DF1, -1N ŒUVRE, -_11 EXEMPLAIRE1
DF2, -1N ŒUVRE, -_11 EXEMPLAIRE2
DF3, -1N ŒUVRE, -_11 EXEMPLAIRE3

EXEMPLAIRE1: 1, bon état, 12/6/1975
EXEMPLAIRE2: 2, bon état, 1/8/1977
EXEMPLAIRE3: 3, reliure rongée, 3/4/2005
DF DF DF ŒUVRE 612.NAT.34 J’apprends à lire à mes souris blanches mai 1975 EXEMPLAIRE 1 bon état 12/6/1975 EXEMPLAIRE 2 bon état 1/8/1977 EXEMPLAIRE 3 reliure rongée 3/4/2005
EXEMPLAIRE1 ( #612.NAT.34, 1, bon état, 12/6/1975 )
EXEMPLAIRE2 ( #612.NAT.34, 2, bon état, 1/8/1977 )
EXEMPLAIRE3 ( #612.NAT.34, 3, reliure rongée, 3/4/2005 )
ŒUVRE ( 612.NAT.34, J'apprends à lire à mes souris blanches, mai 1975 )

Tracé d'un MCD

Interdiction des chevauchements

Les débutants ne comprennent pas toujours du premier coup que l'ordre des lignes du texte-source correspond à celui des boîtes du MCD affiché ; ou qu'il faut sauter une ligne chaque fois que l'on veut une nouvelle rangée de boîtes. Ces malheureux se retrouvent donc plus souvent qu'à leur tour avec des chevauchements pas forcément faciles à voir :

In [58]:
%%mocodo
CLIENT: Réf. client, Nom, Prénom, Adresse
COMMANDE: Num commande, Date, Montant
PRODUIT: Réf. produit, Libellé, Prix unitaire
PASSER, 0N CLIENT, 11 COMMANDE
INCLURE, 1N COMMANDE, 0N PRODUIT: Quantité
0,N 1,1 PASSER 1,N 0,N INCLURE Quantité CLIENT Réf. client Nom Prénom Adresse COMMANDE Num commande Date Montant PRODUIT Réf. produit Libellé Prix unitaire

Ci-dessus, par exemple, l'association INCLURE, qui devrait se trouver entre CLIENT et COMMANDE, est déportée de telle sorte que ses pattes chevauchent COMMANDE, PRODUIT et PASSER, — ce qui ne se voit pas vraiment puisque les entités et associations sont tracées après les pattes.

Nouveauté de la version 3.0. Mocodo peut lever une erreur dans une telle situation. L'option correspondante, --detect_overlaps est par défaut activée sous Mocodo online, et désactivée en ligne de commande.

Si cela se produit, vous pouvez :

  • Modifier manuellement l'ordre des lignes du texte-source et/ou insérer des sauts de ligne.
  • Réarranger automatiquement le MCD (en cliquant 🔀 sous Mocodo online, ou avec l'option --arrange en ligne de commande).
  • Ignorer le problème en décochant la détection des chevauchements (sous l'onglet « Options » de Mocodo online).

Remarques.

  • Les calculs sont opérés, non pas à partir des coordonnées réelles des boîtes, mais de leurs indices $(i, j)$ dans la matrice correspondant à la grille qui sert de base au plongement. Les éventuelles retouches apportées à la position de leurs centres sont ignorées.
  • Seuls les chevauchements mettant en jeu des pattes horizontales ou verticales sont détectés. Par exemple, ci-dessous, le chevauchement sera ignoré.
In [59]:
%%mocodo
CLIENT: Réf. client, Nom, Prénom, Adresse
::

:
COMMANDE: Num commande, Date, Montant
:

::
PASSER, 0N CLIENT, 11 COMMANDE
0,N 1,1 PASSER CLIENT Réf. client Nom Prénom Adresse COMMANDE Num commande Date Montant

Insertion manuelle d'espacements

Le tracé réalisé par Mocodo pour des MCD de plusieurs rangées laisse parfois à désirer :

In [60]:
%%mocodo
Quis, 01 Risus, 1N Ipsum a
Ipsum a: semper, massa
Odio, 1N Ipsum a, 0N Posuere: suscipit

Ac, 01 Risus, 0N Risus
Risus: euismod, semper, dederit, ribandum
Diam leo, 1N Risus, 0N Posuere
Posuere: semper, massa
Pretium, 0N Posuere, 0N Posuere

Curae, 0N Risus, 0N Tellus: pede
METUS, 11 Tellus, 0N Posuere

Ultrices: libero
Lorem, 0N Ultrices, 0N Tellus, 0N Risus: lacus, feugiat
Tellus: domus, tempero
0,1 1,N Quis 1,N 0,N Odio suscipit 0,1 0,N Ac 1,N 0,N Diam leo 0,N 0,N Pretium 0,N 0,N Curae pede 1,1 0,N METUS 0,N 0,N 0,N Lorem lacus feugiat Ipsum a semper massa Risus euismod semper dederit ribandum Posuere semper massa Ultrices libero Tellus domus tempero

On voit que, par défaut, Mocodo centre les rangées qui contiennent moins de boîtes que les autres. Cela donne un bon résultat pour la première rangée, mais pas pour la troisième.

L'utilisateur peut cependant spécifier les espacements qu'il désire en complétant les rangées par des boîtes invisibles dont le seul rôle est de « pousser » les autres à l'emplacement voulu. Ainsi, il va préciser que l'association Curae doit commencer sur la troisième colonne en insérant des lignes réduites au caractère deux-points, et en profiter pour insérer un espace entre Lorem et Tellus :

In [61]:
%%mocodo
Quis, 01 Risus, 1N Ipsum a
Ipsum a: semper, massa
Odio, 1N Ipsum a, 0N Posuere: suscipit

Ac, 01 Risus, 0N Risus
Risus: euismod, semper, dederit, ribandum
Diam leo, 1N Risus, 0N Posuere
Posuere: semper, massa
Pretium, 0N Posuere, 0N Posuere

:
:
Curae, 0N Risus, 0N Tellus: pede
METUS, 11 Tellus, 0N Posuere
:

Ultrices: libero
Lorem, 0N Ultrices, 0N Tellus, 0N Risus: lacus, feugiat
:
Tellus: domus, tempero
0,1 1,N Quis 1,N 0,N Odio suscipit 0,1 0,N Ac 1,N 0,N Diam leo 0,N 0,N Pretium 0,N 0,N Curae pede 1,1 0,N METUS 0,N 0,N 0,N Lorem lacus feugiat Ipsum a semper massa Risus euismod semper dederit ribandum Posuere semper massa Ultrices libero Tellus domus tempero

Il est possible de « compresser » les suites de deux-points en supprimant les retours-chariots, autrement dit, de remplacer $n$ lignes réduites à deux-points par une ligne réduite à une séquence de $n$ deux-points. Ce raccourci est illustré dans le prochain exemple.

Ajustement automatique dans une grille minimale

Nouveauté de la version 2.2. On cherche en général à faire tenir le MCD dans la plus petite grille possible, tout en maintenant un rapport « équilibré » entre hauteur et largeur. Par exemple, un MCD de 13 boîtes (entités ou associations) peut tenir dans les grilles:

  • $13\times1$;
  • $7\times2$, ce qui laisse 1 case vide;
  • $5\times3$, ce qui laisse 2 cases vides;
  • $4\times4$, ce qui laisse 3 cases vides;
  • etc.

Les deux premières grilles étant non équilibrées, on retiendra la plus petite des suivantes, de dimensions $5\times3$.

La table ci-dessous énumère les dimensions des grilles minimales d'équilibre supérieur à 0,5 pour tous les MCD comportant moins de 100 boîtes. On peut y vérifier par exemple que le MCD de taille 13 se trouve effectivement aux coordonnées (5, 3).

1 2 3 4 5 6 7 8 9 10 11 12 13
1 1 2 3
2 4 5, 6
3 7, 8, 9 10, 11, 12 13, 14, 15
4 16 17, 18, 19, 20 21, 22, 23, 24 26, 27, 28
5 25 29, 30 31, 32, 33, 34, 35 37, 38, 39, 40 43, 44, 45
6 36 41, 42 46, 47, 48 50, 51, 52, 53, 54 57, 58, 59, 60 65, 66
7 49 55, 56 61, 62, 63 67, 68, 69, 70 73, 74, 75, 76, 77 82, 83, 84 91
8 64 71, 72 78, 79, 80 85, 86, 87, 88 92, 93, 94, 95, 96
9 81 89, 90 97, 98, 99
10 100

Nouveauté de la version 3.0. La contrainte d'équilibre est relaxée pour les MCD à 2 et 3 boîtes, qui sont placées respectivement sur des grilles $2\times1$ et $3\times1$ au lieu de $2\times2$.

Avec l'option --fit, Mocodo reformate automatiquement le MCD pour le faire entrer dans la grille minimale correspondante:

In [62]:
%%mocodo --fit
Lacus, 01 Blandit, 1N Elit
Elit: ligula, tellus
Metus, 1N Elit, 0N Congue: nibh
  
Bibendum, 01 Blandit, 0N Blandit
Blandit: consequat, ligula, nibh, consequat
Ipsum, 1N Blandit, 0N Congue

Congue: ligula, tellus
Augue, 0N Congue, 0N Congue
Velit, 0N Blandit, 0N Nonummy: sollicitudin
  
DF, 11 Nonummy, 0N Congue
Posuere: pede
Vivamus, 0N Posuere, 0N Nonummy, 0N Blandit: eleifend, iaculis
  
Nonummy: consequat, ligula
%%mocodo
Lacus, 01 Blandit, 1N Elit
Elit: ligula, tellus
Metus, 1N Elit, 0N Congue: nibh
Bibendum, 01 Blandit, 0N Blandit
Blandit: consequat, ligula, nibh, consequat

Ipsum, 1N Blandit, 0N Congue
Congue: ligula, tellus
Augue, 0N Congue, 0N Congue
Velit, 0N Blandit, 0N Nonummy: sollicitudin
DF, 11 Nonummy, 0N Congue

Posuere: pede
Vivamus, 0N Posuere, 0N Nonummy, 0N Blandit: eleifend, iaculis
Nonummy: consequat, ligula
:
:

L'algorithme se contente de supprimer ou d'insérer des sauts de ligne dans le texte-source, sans modifier l'ordre des clauses. On devra donc encore en général opérer sur le résultat un réarrangement automatique (voir plus loin).

In [63]:
%%mocodo --arrange --seed=42
Lacus, 01 Blandit, 1N Elit
Elit: ligula, tellus
Metus, 1N Elit, 0N Congue: nibh
Bibendum, 01 Blandit, 0N Blandit
Blandit: consequat, ligula, nibh, consequat

Ipsum, 1N Blandit, 0N Congue
Congue: ligula, tellus
Augue, 0N Congue, 0N Congue
Velit, 0N Blandit, 0N Nonummy: sollicitudin
DF, 11 Nonummy, 0N Congue

Posuere: pede
Vivamus, 0N Posuere, 0N Nonummy, 0N Blandit: eleifend, iaculis
Nonummy: consequat, ligula
::
%%mocodo
Bibendum, 01 Blandit, 0N Blandit
Blandit: consequat, ligula, nibh, consequat
Lacus, 01 Blandit, 1N Elit
Elit: ligula, tellus
:

Vivamus, 0N Posuere, 0N Nonummy, 0N Blandit: eleifend, iaculis
Velit, 0N Blandit, 0N Nonummy: sollicitudin
Ipsum, 1N Blandit, 0N Congue
Metus, 1N Elit, 0N Congue: nibh
:

Posuere: pede
Nonummy: consequat, ligula
DF, 11 Nonummy, 0N Congue
Congue: ligula, tellus
Augue, 0N Congue, 0N Congue
0,1 0,N Bibendum 0,1 1,N Lacus 0,N 0,N 0,N Vivamus eleifend iaculis 0,N 0,N Velit sollicitudin 1,N 0,N Ipsum 1,N 0,N Metus nibh 1,1 0,N DF 0,N 0,N Augue Blandit consequat ligula nibh consequat Elit ligula tellus Posuere pede Nonummy consequat ligula Congue ligula tellus

Si ce réarrangement échoue ou laisse à désirer, il est possible de spécifier chacune des ièmes grilles suivantes avec l'option --fit=i:

In [64]:
%%mocodo --fit=1
Lacus, 01 Blandit, 1N Elit
Elit: ligula, tellus
Metus, 1N Elit, 0N Congue: nibh
  
Bibendum, 01 Blandit, 0N Blandit
Blandit: consequat, ligula, nibh, consequat
Ipsum, 1N Blandit, 0N Congue

Congue: ligula, tellus
Augue, 0N Congue, 0N Congue
Velit, 0N Blandit, 0N Nonummy: sollicitudin
  
DF, 11 Nonummy, 0N Congue
Posuere: pede
Vivamus, 0N Posuere, 0N Nonummy, 0N Blandit: eleifend, iaculis
  
Nonummy: consequat, ligula
%%mocodo
Lacus, 01 Blandit, 1N Elit
Elit: ligula, tellus
Metus, 1N Elit, 0N Congue: nibh
Bibendum, 01 Blandit, 0N Blandit

Blandit: consequat, ligula, nibh, consequat
Ipsum, 1N Blandit, 0N Congue
Congue: ligula, tellus
Augue, 0N Congue, 0N Congue

Velit, 0N Blandit, 0N Nonummy: sollicitudin
DF, 11 Nonummy, 0N Congue
Posuere: pede
Vivamus, 0N Posuere, 0N Nonummy, 0N Blandit: eleifend, iaculis

Nonummy: consequat, ligula
:
:
:
In [65]:
%%mocodo --arrange --seed=4
Lacus, 01 Blandit, 1N Elit
Elit: ligula, tellus
Metus, 1N Elit, 0N Congue: nibh
Bibendum, 01 Blandit, 0N Blandit

Blandit: consequat, ligula, nibh, consequat
Ipsum, 1N Blandit, 0N Congue
Congue: ligula, tellus
Augue, 0N Congue, 0N Congue

Velit, 0N Blandit, 0N Nonummy: sollicitudin
DF, 11 Nonummy, 0N Congue
Posuere: pede
Vivamus, 0N Posuere, 0N Nonummy, 0N Blandit: eleifend, iaculis

Nonummy: consequat, ligula
:::
%%mocodo
Metus, 1N Elit, 0N Congue: nibh
Elit: ligula, tellus
Lacus, 01 Blandit, 1N Elit
:

Congue: ligula, tellus
Ipsum, 1N Blandit, 0N Congue
Blandit: consequat, ligula, nibh, consequat
Bibendum, 01 Blandit, 0N Blandit

Augue, 0N Congue, 0N Congue
DF, 11 Nonummy, 0N Congue
Velit, 0N Blandit, 0N Nonummy: sollicitudin
Vivamus, 0N Posuere, 0N Nonummy, 0N Blandit: eleifend, iaculis

:
:
Nonummy: consequat, ligula
Posuere: pede
1,N 0,N Metus nibh 0,1 1,N Lacus 1,N 0,N Ipsum 0,1 0,N Bibendum 0,N 0,N Augue 1,1 0,N DF 0,N 0,N Velit sollicitudin 0,N 0,N 0,N Vivamus eleifend iaculis Elit ligula tellus Congue ligula tellus Blandit consequat ligula nibh consequat Nonummy consequat ligula Posuere pede

Remarques.

  • Quand le paramètre de --fit définit une grille trop grande, le réarrangement automatique retombe fréquemment sur une sous-grille de celle-ci.
  • Dans Mocodo online, cliquer sur le bouton de réarrangement automatique avec alt (ou option sur Mac) enchaîne directement les opérations --fit=0 et --arrange=bb. Dans la plupart des cas, cela permet d'obtenir le meilleur résultat. Mais il peut également arriver que la grille minimale soit trop étroite pour autoriser un plongement planaire. Dans ce cas, cliquez sans alt pour débrayer la première opération.

Basculement des cardinalités et inflexion des pattes rectilignes

Nouveauté de la version 2.1. Mocodo est capable de détecter certaines configurations de pattes dont les cardinalités présentent un risque élevé de collision. Il procède alors à deux types d'ajustements:

  1. Issue 25. Les cardinalités d'une patte verticale ou horizontale sont envoyées de l'autre côté de la patte. Par exemple, dans le plongement du MCD précédent, la présence de la patte oblique BLANDIT-VIVAMUS envoie les cardinalités de VELIT-BLANDIT à l'opposé de leur position par défaut (à droite d'une patte verticale ou en bas d'une patte horizontale).
  2. Issue 27. Les pattes obliques sont infléchies de façon à ménager plus d'espace pour afficher deux couples de cardinalités. Ici, l'inflexion de la patte DF-CONGUE permet à ses cardinalités de coexister sans problème avec celles de l'association réflexive.

Ces ajustements automatiques résolvent les problèmes les plus courants. Toutefois, étant antérieurs au tracé proprement dit, ils peuvent seulement réduire les risques de collision, et non les prévenir totalement. Ils peuvent même en produire d'autres. Ainsi, autour des entités particulièrement pattues, des collisions qui ne se seraient pas produites par défaut seront parfois observées. L'utilisateur a alors deux possibilités:

  • modifier à la main les coordonnées des cardinalités en conflit, comme expliqué dans la section suivante;
  • diminuer la valeur du paramètre --flex (par défaut, 0.75) pour réduire la courbure de l'inflexion automatique, en allant jusqu'à 0 pour la désactiver totalement (exemple)).

Retouches fines

Par modification du fichier de géométrie

Lors du plongement, Mocodo génère systématiquement un fichier (intitulé par défaut sandbox_geo.json) répertoriant les positions les plus importantes du dessin. La plupart des autres coordonnées sont calculées relativement à celles-ci.

In [66]:
%%mocodo --shapes trebuchet --colors=brewer+1
Velit, 0N Blandit, 0N Nonummy: sollicitudin

Blandit: consequat, ligula, nibh, consequat
:::
Nonummy: consequat, ligula
  
Vivamus, 0N Nonummy, 0N Blandit: eleifend, iaculis
0,N 0,N Velit sollicitudin 0,N 0,N Vivamus eleifend iaculis Blandit consequat ligula nibh consequat Nonummy consequat ligula

Si on ouvre le fichier de géométrie généré, on y retrouvera les principaux paramètres de position:

In [67]:
display.Code("mocodo_notebook/sandbox_geo.json")
Out[67]:
{
  "width": 384,
  "height": 235,
  "cx": [
    [ "Velit", 192 ],
    [ "Blandit", 47 ],
    [ "Nonummy", 337 ],
    [ "Vivamus", 192 ]
  ],
  "cy": [
    [ "Velit", 35 ],
    [ "Blandit", 113 ],
    [ "Nonummy", 113 ],
    [ "Vivamus", 191 ]
  ],
  "shift": [
    [ "Velit,Blandit,0", 0 ],
    [ "Velit,Nonummy,0", 0 ],
    [ "Vivamus,Nonummy,0", 0 ],
    [ "Vivamus,Blandit,0", 0 ]
  ],
  "ratio": []
}
  • Un couple de dimensions width et height définit la taille du MCD ;
  • deux listes de couples cx et cy, les abscisses et ordonnées des centres des boîtes ;
  • un dictionnaire shift, les positions relatives des cardinalités par rapport à leur position par défaut ;
  • une liste ratio, les positions des flèches éventuelles.

Pour rendre le plongement plus compact, nous apportons à ce fichier quelques modifications :

In [68]:
%%file mocodo_notebook/sandbox_geo.json
{
  "width": 384,
  "height": 155,
  "cx": [
    [ "Velit", 192 ],
    [ "Blandit", 47 ],
    [ "Nonummy", 337 ],
    [ "Vivamus", 192 ]
  ],
  "cy": [
    [ "Velit", 35 ],
    [ "Blandit", 73 ],
    [ "Nonummy", 73 ],
    [ "Vivamus", 111 ]
  ],
  "shift": [
    [ "Velit,Blandit,0", -30 ],
    [ "Velit,Nonummy,0", -30 ],
    [ "Vivamus,Nonummy,0", -30 ],
    [ "Vivamus,Blandit,0", -30 ]
  ],
  "ratio": []
}
Overwriting mocodo_notebook/sandbox_geo.json

Il suffit maintenant d'ajouter l'option --reuse_geo pour appliquer ces modifications :

In [69]:
%%mocodo --shapes trebuchet --colors=brewer+1 --reuse_geo
Velit, 0N Blandit, 0N Nonummy: sollicitudin

Blandit: consequat, ligula, nibh, consequat
:::
Nonummy: consequat, ligula
  
Vivamus, 0N Nonummy, 0N Blandit: eleifend, iaculis
0,N 0,N Velit sollicitudin 0,N 0,N Vivamus eleifend iaculis Blandit consequat ligula nibh consequat Nonummy consequat ligula

Par édition de la sortie au format SVG

Tous les navigateurs modernes prennent en charge la visualisation des SVG. Pour aller au-delà, il faudra faire appel à un logiciel de dessin vectoriel dédié, comme Inkscape (libre) ou Adobe Illustrator, Freehand, CorelDRAW, etc. Les éléments du fichier SVG produit pourront alors être repositionnés à la souris. Certains sont groupés pour permettre leur déplacement en bloc. Dans la version actuelle, les liens ne suivent pas ces déplacements, ce qui peut obliger à des manipulations supplémentaires.

Réarrangement par symétrie

Mocodo permet de calculer facilement le symétrique d'un MCD, par exemple celui donné ci-dessous:

In [70]:
%%mocodo
Assistas, 01 Hci poilu, 0N Hci poilu
Hci poilu: graffiti, champignon, troussa, graffiti
Rayonnait, 0N Hci poilu, 0N Lappa: monobloc

Brisa: souffrait
Pillards, 0N Brisa, 0N Lappa, 0N Hci poilu: disions, lascar
Lappa: graffiti, champignon
Puni, 11 Lappa, 0N Lappa
0,1 0,N Assistas 0,N 0,N Rayonnait monobloc 0,N 0,N 0,N Pillards disions lascar 1,1 0,N Puni Hci poilu graffiti champignon troussa graffiti Brisa souffrait Lappa graffiti champignon

Nouveauté de la version 2.0.20. Pour remplacer le texte de la cellule par le résultat de son évaluation, ajoutez l'option --replace.

Symétrie selon l'axe vertical

In [71]:
%%mocodo --flip=v
Assistas, 01 Hci poilu, 0N Hci poilu
Hci poilu: graffiti, champignon, troussa, graffiti
Rayonnait, 0N Hci poilu, 0N Lappa: monobloc

Brisa: souffrait
Pillards, 0N Brisa, 0N Lappa, 0N Hci poilu: disions, lascar
Lappa: graffiti, champignon
Puni, 11 Lappa, 0N Lappa
%%mocodo
:
Rayonnait, 0N Hci poilu, 0N Lappa: monobloc
Hci poilu: graffiti, champignon, troussa, graffiti
Assistas, 01 Hci poilu, 0N Hci poilu

Puni, 11 Lappa, 0N Lappa
Lappa: graffiti, champignon
Pillards, 0N Brisa, 0N Lappa, 0N Hci poilu: disions, lascar
Brisa: souffrait
0,N 0,N Rayonnait monobloc 0,1 0,N Assistas 1,1 0,N Puni 0,N 0,N 0,N Pillards disions lascar Hci poilu graffiti champignon troussa graffiti Lappa graffiti champignon Brisa souffrait

Symétrie selon l'axe horizontal

In [72]:
%%mocodo --flip=h
Assistas, 01 Hci poilu, 0N Hci poilu
Hci poilu: graffiti, champignon, troussa, graffiti
Rayonnait, 0N Hci poilu, 0N Lappa: monobloc

Brisa: souffrait
Pillards, 0N Brisa, 0N Lappa, 0N Hci poilu: disions, lascar
Lappa: graffiti, champignon
Puni, 11 Lappa, 0N Lappa
%%mocodo
Brisa: souffrait
Pillards, 0N Brisa, 0N Lappa, 0N Hci poilu: disions, lascar
Lappa: graffiti, champignon
Puni, 11 Lappa, 0N Lappa

Assistas, 01 Hci poilu, 0N Hci poilu
Hci poilu: graffiti, champignon, troussa, graffiti
Rayonnait, 0N Hci poilu, 0N Lappa: monobloc
:
0,N 0,N 0,N Pillards disions lascar 1,1 0,N Puni 0,1 0,N Assistas 0,N 0,N Rayonnait monobloc Brisa souffrait Lappa graffiti champignon Hci poilu graffiti champignon troussa graffiti

Symétries selon les diagonales (transposition)

In [73]:
%%mocodo --flip=d
Assistas, 01 Hci poilu, 0N Hci poilu
Hci poilu: graffiti, champignon, troussa, graffiti
Rayonnait, 0N Hci poilu, 0N Lappa: monobloc

Brisa: souffrait
Pillards, 0N Brisa, 0N Lappa, 0N Hci poilu: disions, lascar
Lappa: graffiti, champignon
Puni, 11 Lappa, 0N Lappa
%%mocodo
Assistas, 01 Hci poilu, 0N Hci poilu
Brisa: souffrait

Hci poilu: graffiti, champignon, troussa, graffiti
Pillards, 0N Brisa, 0N Lappa, 0N Hci poilu: disions, lascar

Rayonnait, 0N Hci poilu, 0N Lappa: monobloc
Lappa: graffiti, champignon

:
Puni, 11 Lappa, 0N Lappa
0,1 0,N Assistas 0,N 0,N 0,N Pillards disions lascar 0,N 0,N Rayonnait monobloc 1,1 0,N Puni Brisa souffrait Hci poilu graffiti champignon troussa graffiti Lappa graffiti champignon

Pour une symétrie selon l'anti-diagonale, appliquer successivement les trois symétries précédentes dans n'importe quel ordre.

Astuce: édition rapide d'une ou plusieurs colonnes

La transposition peut être utilisée pour réaliser plus facilement certaines opérations d'édition en colonne, en particulier sous Mocodo online. Par exemple, supposons que l'on souhaite décaler vers le haut la dernière colonne du MCD ci-dessous:

In [74]:
%%mocodo --flex=0
AMET, 11> LOREM, 01 CONSECTETUER: adipiscing
CONSECTETUER: elit, sed
TORTOR, 0N RISUS, 11 DIGNISSIM, 1N CONSECTETUER: nec
DF, 11 RISUS, 0N RISUS

LOREM: ipsum, dolor, sit
SOLLICITUDIN, 0N SUSPENDISSE, 0N CONSECTETUER, 0N LOREM: lectus
DIGNISSIM: ligula, massa, varius
RISUS: ultricies, _cras, elementum

DF1, 11 LOREM, 1N SUSPENDISSE
SUSPENDISSE: diam
MAECENAS, 1N DIGNISSIM, 1N DIGNISSIM
SEMPER, 0N RISUS, 1N DIGNISSIM
1,1 0,1 AMET adipiscing 0,N 1,1 1,N TORTOR nec 1,1 0,N DF 0,N 0,N 0,N SOLLICITUDIN lectus 1,1 1,N DF 1,N 1,N MAECENAS 0,N 1,N SEMPER CONSECTETUER elit sed LOREM ipsum dolor sit DIGNISSIM ligula massa varius RISUS ultricies cras elementum SUSPENDISSE diam

On commence par transposer:

In [75]:
%%mocodo --no_mcd --flip=d
AMET, 11> LOREM, 01 CONSECTETUER: adipiscing
CONSECTETUER: elit, sed
TORTOR, 0N RISUS, 11 DIGNISSIM, 1N CONSECTETUER: nec
DF, 11 RISUS, 0N RISUS

LOREM: ipsum, dolor, sit
SOLLICITUDIN, 0N SUSPENDISSE, 0N CONSECTETUER, 0N LOREM: lectus
DIGNISSIM: ligula, massa, varius
RISUS: ultricies, _cras, elementum

DF1, 11 LOREM, 1N SUSPENDISSE
SUSPENDISSE: diam
MAECENAS, 1N DIGNISSIM, 1N DIGNISSIM
SEMPER, 0N RISUS, 1N DIGNISSIM
%%mocodo
AMET, 11> LOREM, 01 CONSECTETUER: adipiscing
LOREM: ipsum, dolor, sit
DF1, 11 LOREM, 1N SUSPENDISSE

CONSECTETUER: elit, sed
SOLLICITUDIN, 0N SUSPENDISSE, 0N CONSECTETUER, 0N LOREM: lectus
SUSPENDISSE: diam

TORTOR, 0N RISUS, 11 DIGNISSIM, 1N CONSECTETUER: nec
DIGNISSIM: ligula, massa, varius
MAECENAS, 1N DIGNISSIM, 1N DIGNISSIM

DF, 11 RISUS, 0N RISUS
RISUS: ultricies, _cras, elementum
SEMPER, 0N RISUS, 1N DIGNISSIM

Il suffit alors d'insérer un deux-points au début de chacune des trois premières rangées, puis de retransposer dans l'autre sens:

In [76]:
%%mocodo --flip=d
:
AMET, 11> LOREM, 01 CONSECTETUER: adipiscing
LOREM: ipsum, dolor, sit
DF1, 11 LOREM, 1N SUSPENDISSE

:
CONSECTETUER: elit, sed
SOLLICITUDIN, 0N SUSPENDISSE, 0N CONSECTETUER, 0N LOREM: lectus
SUSPENDISSE: diam

:
TORTOR, 0N RISUS, 11 DIGNISSIM, 1N CONSECTETUER: nec
DIGNISSIM: ligula, massa, varius
MAECENAS, 1N DIGNISSIM, 1N DIGNISSIM

DF, 11 RISUS, 0N RISUS
RISUS: ultricies, _cras, elementum
SEMPER, 0N RISUS, 1N DIGNISSIM
%%mocodo
:
:
:
DF, 11 RISUS, 0N RISUS

AMET, 11> LOREM, 01 CONSECTETUER: adipiscing
CONSECTETUER: elit, sed
TORTOR, 0N RISUS, 11 DIGNISSIM, 1N CONSECTETUER: nec
RISUS: ultricies, _cras, elementum

LOREM: ipsum, dolor, sit
SOLLICITUDIN, 0N SUSPENDISSE, 0N CONSECTETUER, 0N LOREM: lectus
DIGNISSIM: ligula, massa, varius
SEMPER, 0N RISUS, 1N DIGNISSIM

DF1, 11 LOREM, 1N SUSPENDISSE
SUSPENDISSE: diam
MAECENAS, 1N DIGNISSIM, 1N DIGNISSIM
:
1,1 0,N DF 1,1 0,1 AMET adipiscing 0,N 1,1 1,N TORTOR nec 0,N 0,N 0,N SOLLICITUDIN lectus 0,N 1,N SEMPER 1,1 1,N DF 1,N 1,N MAECENAS CONSECTETUER elit sed RISUS ultricies cras elementum LOREM ipsum dolor sit DIGNISSIM ligula massa varius SUSPENDISSE diam

On peut se convaincre en examinant le nouveau texte d'entrée que le résultat aurait été beaucoup plus pénible à obtenir en procédant directement.

Réarrangement automatique

Il est possible de demander à Mocodo de chercher tout seul une « bonne » permutation des boîtes, ce qui à la main deviendrait vite difficile.

Le critère que nous avons retenu pour évaluer la qualité d'une permutation est double:

  1. les liens ne doivent pas se couper ;
  2. leur longueur cumulée doit être minimale.

Deux algorithmes sont fournis :

  • un algorithme exact (bb, pour Branch & Bound), qui ne trouve que des solutions satisfaisant au premier critère;
  • un algorithme approché (ga, pour Genetic Algorithm), réservé aux cas où il est impossible d'y satisfaire. L'algorithme va alors chercher des solutions où les liens se coupent seulement le moins possible.

Nouveauté de la version 2.0.20. Pour remplacer le texte de la cellule par le résultat de son évaluation, ajoutez l'option --replace.

Méthode exacte spécialisée

À l'intérieur d'une grille prédéfinie

Voici à titre d'exemple un résultat trouvé par l'algorithme exact, suivi du MCD correspondant:

In [77]:
%%mocodo --arrange --seed=1
Lacus, 01 Blandit, 1N Elit
Elit: ligula, tellus
Metus, 1N Elit, 0N Congue: nibh

Bibendum, 01 Blandit, 0N Blandit
Blandit: consequat, ligula, nibh, consequat
Ipsum, 1N Blandit, 0N Congue
Congue: ligula, tellus
Augue, 0N Congue, 0N Congue

Velit, 0N Blandit, 0N Nonummy: sollicitudin
DF, 11 Nonummy, 0N Congue

Posuere: pede
Vivamus, 0N Posuere, 0N Nonummy, 0N Blandit: eleifend, iaculis
Nonummy: consequat, ligula
%%mocodo
Nonummy: consequat, ligula
Vivamus, 0N Posuere, 0N Nonummy, 0N Blandit: eleifend, iaculis
Posuere: pede
:

DF, 11 Nonummy, 0N Congue
Velit, 0N Blandit, 0N Nonummy: sollicitudin
Blandit: consequat, ligula, nibh, consequat
Bibendum, 01 Blandit, 0N Blandit

Congue: ligula, tellus
Ipsum, 1N Blandit, 0N Congue
Lacus, 01 Blandit, 1N Elit
:

Augue, 0N Congue, 0N Congue
Metus, 1N Elit, 0N Congue: nibh
Elit: ligula, tellus
:
0,N 0,N 0,N Vivamus eleifend iaculis 1,1 0,N DF 0,N 0,N Velit sollicitudin 0,1 0,N Bibendum 1,N 0,N Ipsum 0,1 1,N Lacus 0,N 0,N Augue 1,N 0,N Metus nibh Nonummy consequat ligula Posuere pede Blandit consequat ligula nibh consequat Congue ligula tellus Elit ligula tellus

Le réarrangement automatique se fera toujours à l'intérieur d'une grille ayant autant de colonnes et de rangées que le texte de départ (ici, $4\times5$). On peut quelquefois essayer de réduire cette grille. Par exemple, le MCD ci-dessus comporte 13 boîtes. Celles-ci pourraient donc théoriquement tenir dans une grille $5\times3=15$. Modifions le texte à la main pour avoir 3 blocs d'au plus 5 lignes, et vérifier qu'un tel réarrangement est possible:

In [78]:
%%mocodo --arrange --seed=4
Lacus, 01 Blandit, 1N Elit
Elit: ligula, tellus
Metus, 1N Elit, 0N Congue: nibh
Bibendum, 01 Blandit, 0N Blandit
Blandit: consequat, ligula, nibh, consequat

Ipsum, 1N Blandit, 0N Congue
Congue: ligula, tellus
Augue, 0N Congue, 0N Congue
Velit, 0N Blandit, 0N Nonummy: sollicitudin
DF, 11 Nonummy, 0N Congue

Posuere: pede
Vivamus, 0N Posuere, 0N Nonummy, 0N Blandit: eleifend, iaculis
Nonummy: consequat, ligula
%%mocodo
Augue, 0N Congue, 0N Congue
Congue: ligula, tellus
DF, 11 Nonummy, 0N Congue
Nonummy: consequat, ligula
Posuere: pede

:
Metus, 1N Elit, 0N Congue: nibh
Ipsum, 1N Blandit, 0N Congue
Velit, 0N Blandit, 0N Nonummy: sollicitudin
Vivamus, 0N Posuere, 0N Nonummy, 0N Blandit: eleifend, iaculis

:
Elit: ligula, tellus
Lacus, 01 Blandit, 1N Elit
Blandit: consequat, ligula, nibh, consequat
Bibendum, 01 Blandit, 0N Blandit
0,N 0,N Augue 1,1 0,N DF 1,N 0,N Metus nibh 1,N 0,N Ipsum 0,N 0,N Velit sollicitudin 0,N 0,N 0,N Vivamus eleifend iaculis 0,1 1,N Lacus 0,1 0,N Bibendum Congue ligula tellus Nonummy consequat ligula Posuere pede Elit ligula tellus Blandit consequat ligula nibh consequat

Par croissance organique

Le réarrangement dit organique consiste à choisir une première boîte au hasard, puis à essayer d'agréger les autres sans se préoccuper de contenir le tout dans une grille prédéterminée.

In [79]:
%%mocodo --arrange --organic --seed=7
Lacus, 01 Blandit, 1N Elit
Elit: ligula, tellus
Metus, 1N Elit, 0N Congue: nibh
Bibendum, 01 Blandit, 0N Blandit
Blandit: consequat, ligula, nibh, consequat

Ipsum, 1N Blandit, 0N Congue
Congue: ligula, tellus
Augue, 0N Congue, 0N Congue
Velit, 0N Blandit, 0N Nonummy: sollicitudin
DF, 11 Nonummy, 0N Congue

Posuere: pede
Vivamus, 0N Posuere, 0N Nonummy, 0N Blandit: eleifend, iaculis
Nonummy: consequat, ligula
%%mocodo
:
Bibendum, 01 Blandit, 0N Blandit
:
:

Lacus, 01 Blandit, 1N Elit
Blandit: consequat, ligula, nibh, consequat
Vivamus, 0N Posuere, 0N Nonummy, 0N Blandit: eleifend, iaculis
Posuere: pede

Elit: ligula, tellus
Ipsum, 1N Blandit, 0N Congue
Velit, 0N Blandit, 0N Nonummy: sollicitudin
Nonummy: consequat, ligula

Metus, 1N Elit, 0N Congue: nibh
Congue: ligula, tellus
DF, 11 Nonummy, 0N Congue
:

:
Augue, 0N Congue, 0N Congue
:
:
0,1 0,N Bibendum 0,1 1,N Lacus 0,N 0,N 0,N Vivamus eleifend iaculis 1,N 0,N Ipsum 0,N 0,N Velit sollicitudin 1,N 0,N Metus nibh 1,1 0,N DF 0,N 0,N Augue Blandit consequat ligula nibh consequat Posuere pede Elit ligula tellus Nonummy consequat ligula Congue ligula tellus

Cela donne un autre plongement du MCD sur une grille $4\times5$, ce qui comme on l'a vu n'est pas optimal. Mais on voit aussi qu'il peut être trivialement amélioré. De fait, le réarrangement organique fournit souvent un bon point de départ pour chercher soi-même une permutation plus esthétique ou mettant en évidence certaines propriétés du MCD.

Limitations

Pour permettre au programme de rendre plus rapidement de bonnes solutions, on a borné arbitrairement le nombre d'appels à la fonction chargée de construire une permutation à partir du placement de la première boîte. De ce fait, l'algorithme n'est plus exact, en ce sens que la meilleure solution peut occasionnellement lui échapper. Si vous soupçonnez que c'est le cas, faites un autre essai, éventuellement en augmentant la borne (par défaut 10000):

mocodo --arrange --call_limit=100000

D'autre part, le réarrangement exact ne fonctionnera jamais sur les MCD:

  • non planaires;
  • planaires n'admettant aucun plongement planaire dans les limites de la grille spécifiée.

Rappelons qu'un graphe est dit planaire lorsqu'il en existe au moins un arrangement sans croisement. Le graphe non planaire comportant le plus petit nombre de liens est connu sous le nom de $K_{3,3}$:

In [80]:
%%mocodo
DIGNISSIM: nec sem, nunc, vulputate
IMPERDIET: a praesent, nibh, semper
TINCIDUNT: faucibus, orci, cursus

RHONCUS, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT
SODALES, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT
QUIS ENIM, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT
1,N 1,N 1,N RHONCUS 1,N 1,N 1,N SODALES 1,N 1,N 1,N QUIS ENIM DIGNISSIM nec sem nunc vulputate IMPERDIET a praesent nibh semper TINCIDUNT faucibus orci cursus

Son réarrangement par Branch & bound échouera donc nécessairement. Mocodo ne cherche pas à savoir si la non-planarité est intrinsèque au graphe, ou résulte des dimensions de la grille imposée pour le plongement :

In [81]:
%%mocodo --arrange
DIGNISSIM: nec sem, nunc, vulputate
IMPERDIET: a praesent, nibh, semper
TINCIDUNT: faucibus, orci, cursus

RHONCUS, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT
SODALES, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT
QUIS ENIM, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT
Mocodo Err.9 - Impossible de calculer une mise en page planaire sur la grille impartie.

Méthode heuristique

Dans tous ces cas, on pourra se rabattre sur l'heuristique. Celle-ci, au lieu d'interdire les croisements, cherche simplement à en minimiser le nombre.

In [82]:
%%mocodo --arrange=ga --seed=42
DIGNISSIM: nec sem, nunc, vulputate
IMPERDIET: a praesent, nibh, semper
TINCIDUNT: faucibus, orci, cursus

RHONCUS, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT
SODALES, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT
QUIS ENIM, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT
%%mocodo
DIGNISSIM: nec sem, nunc, vulputate
RHONCUS, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT
IMPERDIET: a praesent, nibh, semper

SODALES, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT
TINCIDUNT: faucibus, orci, cursus
QUIS ENIM, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT
1,N 1,N 1,N RHONCUS 1,N 1,N 1,N SODALES 1,N 1,N 1,N QUIS ENIM DIGNISSIM nec sem nunc vulputate IMPERDIET a praesent nibh semper TINCIDUNT faucibus orci cursus

L'amélioration ne saute pas forcément aux yeux, mais il n'y a plus que 3 croisements au lieu de 9. Ce plongement constitue en tout cas un bon point de départ pour un réarrangement manuel. Pour arriver à une représentation lisible, il ne reste plus qu'à insérer quelques boîtes invisibles:

In [83]:
%%mocodo
RHONCUS, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT

DIGNISSIM: nec sem, nunc, vulputate
:::
IMPERDIET: a praesent, nibh, semper

SODALES, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT
:::
QUIS ENIM, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT

TINCIDUNT: faucibus, orci, cursus
1,N 1,N 1,N RHONCUS 1,N 1,N 1,N SODALES 1,N 1,N 1,N QUIS ENIM DIGNISSIM nec sem nunc vulputate IMPERDIET a praesent nibh semper TINCIDUNT faucibus orci cursus

Conversion dans d'autres formats graphiques

Mocodo génère systématiquement une sortie au format SVG :

In [84]:
%%mocodo --no_mcd --png --pdf
CLIENT: Réf. client, Nom, Prénom, Adresse
PASSER, 0N CLIENT, 11 COMMANDE
COMMANDE: Num commande, Date, Montant
INCLURE, 1N COMMANDE, 0N PRODUIT: Quantité
PRODUIT: Réf. produit, Libellé, Prix unitaire
In [85]:
display.SVG("mocodo_notebook/sandbox.svg")
Out[85]:
0,N 1,1 PASSER 1,N 0,N INCLURE Quantité CLIENT Réf. client Nom Prénom Adresse COMMANDE Num commande Date Montant PRODUIT Réf. produit Libellé Prix unitaire

Nouveauté de la version 3.0. Avec les options --pdf et --png (ou en cochant les cases correspondantes dans l'onglet Options de la version web), Mocodo convertit désormais ce SVG en PDF et PNG. Le premier format est idéal pour l'inclusion dans des documents destinés à être projetés, diffusés ou imprimés :

In [86]:
display.IFrame("mocodo_notebook/sandbox.pdf", width="100%", height="100%")
Out[86]:

Le second est un format bitmap, donc avec une certaine perte de qualité :

In [87]:
display.Image("mocodo_notebook/sandbox.png")
Out[87]:

Attention, dans un cas comme dans l'autre, seules les polices de caractères les plus courantes seront composées correctement.

Passage au relationnel

Le passage au relationnel se fait en deux étapes:

  • la création d'une représentation interne complète du MLD;
  • la traduction de celle-ci en une représentation externe dans le ou les formats de sortie souhaités.

Construction de la représentation interne

L'algorithme de base réalise la séquence d'opérations suivante :

  1. Pour chaque entité, une relation (table) de même nom et de mêmes attributs est créée. Le ou les identifiants de l'entité constituent la clé primaire de la relation.
  2. Toute relation issue d'une entité faible est renforcée, c'est-à-dire que la clé primaire de l'entité qu'elle détermine fonctionnellement vient s'adjoindre à sa clé primaire, au besoin de façon récursive.
  3. Les associations sont traitées ainsi:
    1. si toutes les pattes de l'association portent la cardinalité maximale N, une relation de même nom et de mêmes attributs est créée. Sa clé primaire est constituée de l'ensemble des clés primaires des relations issues des entités mises en jeu;
    2. dans le cas contraire, c'est-à-dire si l'une des pattes de l'association porte la cardinalité (1,1), ou à défaut (0,1), l'entité distinguée se voit adjoindre:
      1. en tant que clés étrangères, l'ensemble des clés primaires des autres entités mises en jeu;
      2. en tant que simples attributs, l'ensemble des attributs de l'association.

Remarque. Un couple de cardinalités non standard, c'est-à-dire distinct de (0,1), (1,1), (0,N) et (1,N), est traité comme (0,1) si son deuxième symbole est un 1, et comme (0,N) sinon. Cela couvre en particulier les cas (*, 1), (*,N), (?,?) et (X,X).

Traitement des associations non DF

Illustrons le premier cas du troisième point sur un MCD comportant des associations triple, double et réflexive dont toutes les cardinalités maximales sont à N.

In [88]:
%%mocodo --mld
LACUS: blandit, elit
LIGULA, 0N LACUS, 1N EROS, 0N TELLUS: metus
EROS: congue, nibh, tincidunt  

BIDENDUM, 0N TELLUS, 1N TELLUS: consequat
TELLUS: integer, odio
FAUCIBUS, 1N TELLUS, 0N EROS: ipsum
0,N 1,N 0,N LIGULA metus 0,N 1,N BIDENDUM consequat 1,N 0,N FAUCIBUS ipsum LACUS blandit elit EROS congue nibh tincidunt TELLUS integer odio
BIDENDUM ( #integer, #integer.1, consequat )
EROS ( congue, nibh, tincidunt )
FAUCIBUS ( #integer, #congue, ipsum )
LACUS ( blandit, elit )
LIGULA ( #blandit, #congue, #integer, metus )
TELLUS ( integer, odio )

Notez la désambiguïsation automatique par numérotation du deuxième attribut de BIBENDUM.

Traitement des associations DF

Illustrons l'autre cas sur un MCD quasiment identique, à ceci près que certaines cardinalités maximales ont été ramenées à 1. En tant que dépendances fonctionnelles, toutes les associations vont alors disparaître.

In [89]:
%%mocodo --mld
LACUS: blandit, elit
LIGULA, 11 LACUS, 1N EROS, 0N TELLUS: metus
EROS: congue, nibh, tincidunt  

BIDENDUM, 0N TELLUS, 11 TELLUS: consequat
TELLUS: integer, odio
FAUCIBUS, 11 TELLUS, 01 EROS: ipsum
1,1 1,N 0,N LIGULA metus 0,N 1,1 BIDENDUM consequat 1,1 0,1 FAUCIBUS ipsum LACUS blandit elit EROS congue nibh tincidunt TELLUS integer odio
EROS ( congue, nibh, tincidunt )
LACUS ( blandit, elit, #congue, #integer, metus )
TELLUS ( integer, odio, #integer.1, consequat, #congue, ipsum )

Notez les points suivants:

  • la cardinalité (1,1) est par défaut prioritaire sur (0,1) lors du traitement de l'association FAUCIBUS;
  • Mocodo n'impose pas de borne supérieure à l'arité d'une association de dépendance fonctionnelle, ici par exemple LIGULA est ternaire (alternative: modélisation par plusieurs dépendances fonctionnelles);
  • Mocodo n'interdit pas à une association de dépendance fonctionnelle de porter des attributs (alternative: les mettre dans l'entité distinguée par (1,1)).

Les deux alternatives mentionnées, plus orthodoxes mais plus lourdes, produisent de toute façon le même schéma relationnel.

Autre point litigieux: dans les dépendances fonctionnelles à double sens ((1,1) des deux côtés), la priorité est donnée à la première des entités énumérées dans l'association. Même chose quand deux (0,1) sont en concurrence.

In [90]:
%%mocodo --mld
TELLUS: integer, odio
FAUCIBUS, 11 TELLUS, 11 EROS: ipsum
EROS: congue, nibh, tincidunt  

ORCI: suspendisse, iaculis
MOLLIS, 11 POSUERE, 11 ORCI: lacus
POSUERE: pretium, euismod, porttitor
1,1 1,1 FAUCIBUS ipsum 1,1 1,1 MOLLIS lacus TELLUS integer odio EROS congue nibh tincidunt ORCI suspendisse iaculis POSUERE pretium euismod porttitor
EROS ( congue, nibh, tincidunt )
ORCI ( suspendisse, iaculis )
POSUERE ( pretium, euismod, porttitor, #suspendisse, lacus )
TELLUS ( integer, odio, #congue, ipsum )

Les traitements alternatifs (migration dans les deux sens, fusion en une seule table, etc.) ne sont pas pris en charge par Mocodo.

Traitement des entités faibles (identification relative)

In [91]:
%%mocodo --mld --relations diagram
Appartement: num appart., nb pièces
Composer, 0N Étage, _11 Appartement
Étage: num étage, nb appartements
Appartenir, 1N Immeuble, _11 Étage
Immeuble: num immeuble, nb étages
Se situer, 0N Rue, _11 Immeuble
Rue: code rue, nom rue
0,N 1,1 Composer 1,N 1,1 Appartenir 0,N 1,1 Se situer Appartement num appart. nb pièces Étage num étage nb appartements Immeuble num immeuble nb étages Rue code rue nom rue
Appartement ( #code rue, #num immeuble, #num étage, num appart., nb pièces )
Immeuble ( #code rue, num immeuble, nb étages )
Rue ( code rue, nom rue )
Étage ( #code rue, #num immeuble, num étage, nb appartements )

Dans ce joli exemple dû à Idris NEUMANN, Initiation à la conception de bases de données relationnelles avec MERISE, les renforcements successifs aboutissent à faire entrer l'identifiant de RUE dans celui de APPARTEMENT, alors même que ces entités sont séparées par non moins de trois associations.

Ce processus apparaît clairement sur le diagramme relationnel généré par la commande précédente:

In [92]:
%mocodo --input mocodo_notebook/sandbox.mld
Appartement #code rue #num immeuble #num étage num appart. nb pièces Étage #code rue #num immeuble num étage nb appartements Immeuble #code rue num immeuble nb étages Rue code rue nom rue

Les renforcements en cascade sont correctement gérés dans tous les cas, et les renforcements cycliques produisent un message d'erreur.

Rétablissement explicite de la sémantique des DF disparues

Mocodo permet de modifier légèrement le nom d'une clé étrangère, de façon à réintroduire la sémantique perdue lors de la disparition de l'association de dépendance fonctionnelle par laquelle elle a migré.

In [93]:
%%mocodo --mld
Soutenir, 01 Étudiant, 0N Date: note stage
Étudiant: num. étudiant, nom, coordonnées

Date: date
Répondre de, 0N Date, 11 Étudiant, 0N Enseignant
Enseignant: num. enseignant, nom, coordonnées
0,1 0,N Soutenir note stage 0,N 1,1 0,N Répondre de Étudiant num. étudiant nom coordonnées Date date Enseignant num. enseignant nom coordonnées
Enseignant ( num. enseignant, nom, coordonnées )
Étudiant ( num. étudiant, nom, coordonnées, date, note stage, date.1, #num. enseignant )

Par exemple, ci-dessus, la conversion en relationnel produit dans la relation ÉTUDIANT des clés étrangères date et date.1 qui ne peuvent être laissées en l'état. Par ailleurs, on peut souhaiter expliciter la raison pour laquelle un numéro d'enseignant apparaît dans la table ÉTUDIANT.

Dans les deux cas, il suffit d'employer le système d'annotation de pattes introduit plus haut:

In [94]:
%%mocodo --mld --no_mcd
Soutenir, 01 Étudiant, 0N [soutenance] Date: note stage
Étudiant: num. étudiant, nom, coordonnées

Date: date
Répondre de, 0N [visite] Date, 11 Étudiant, 0N [responsable] Enseignant
Enseignant: num. enseignant, nom, coordonnées
Enseignant ( num. enseignant, nom, coordonnées )
Étudiant ( num. étudiant, nom, coordonnées, date soutenance, note stage, date visite, #num. enseignant responsable )

De façon moins cruciale, la technique s'applique aussi aux autres types d'association:

In [95]:
%%mocodo --mld
CLIENT: Réf. client, Nom, Prénom, Adresse
PASSER, 0N [ayant commandé] CLIENT, 11 [note ignorée] COMMANDE
COMMANDE: Num. commande, Date, Montant
INCLURE, 1N [passée] COMMANDE, 0N [commandé] PRODUIT: Quantité
PRODUIT: Réf. produit, Libellé, Prix unitaire
0,N 1,1 PASSER 1,N 0,N INCLURE Quantité CLIENT Réf. client Nom Prénom Adresse COMMANDE Num. commande Date Montant PRODUIT Réf. produit Libellé Prix unitaire
CLIENT ( Réf. client, Nom, Prénom, Adresse )
COMMANDE ( Num. commande, Date, Montant, #Réf. client ayant commandé )
INCLURE ( #Num. commande passée, #Réf. produit commandé, Quantité )
PRODUIT ( Réf. produit, Libellé, Prix unitaire )

Pour désactiver cette fonctionnalité (notamment dans le cas où vous annotez chaque cardinalité d'une explication destinée aux novices), passez l'option --disambiguation=numbers_only.

Conversion forcée d'une association DF en table

Le traitement régulier d'une association DF (présence d'une cardinalité (1,1) ou, à défaut, (0,1)) ne la convertit pas en table. On a cependant la possibilité de forcer cette conversion en mettant entre crochets droits le nom de l'association.

Par exemple, supposons une cardinalité (0,1) dans laquelle le 0 est grand devant le 1 en termes de fréquence d'apparition : par défaut, la plupart des occurrences de la clé étrangère ainsi constituée restent vides. Forcer la création d'une table dédiée permettra d'économiser de l'espace de stockage.

In [96]:
%%mocodo --relations html_verbose
LACUS: blandit, elit
[LIGULA], 01 LACUS, 1N EROS: metus
EROS: congue, nibh, tincidunt
0,1 1,N LIGULA metus LACUS blandit elit EROS congue nibh tincidunt
In [97]:
display.HTML("mocodo_notebook/sandbox_verbose.html")
Out[97]:
EROS ( congue, nibh, tincidunt )
  • Le champ congue constitue la clé primaire de la table. C'était déjà un identifiant de l'entité EROS.
  • Les champs nibh et tincidunt étaient déjà de simples attributs de l'entité EROS.
LACUS ( blandit, elit )
  • Le champ blandit constitue la clé primaire de la table. C'était déjà un identifiant de l'entité LACUS.
  • Le champ elit était déjà un simple attribut de l'entité LACUS.
LIGULA ( #blandit, #congue, metus )
  • Avertissement. Table résultant de la conversion forcée d'une association DF.
  • Le champ blandit constitue la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité LACUS.
  • Le champ congue est une clé étrangère. Il a migré directement de l'entité EROS en perdant son caractère identifiant.
  • Le champ metus était déjà un simple attribut de l'association LIGULA.

Cliquez sur LIGULA ci-dessus pour voir mentionner le fait que la création de la table a été forcée manuellement.

In [98]:
%%mocodo --relations html_verbose
LACUS: blandit, elit
[LIGULA], 11 LACUS, 1N EROS: metus
EROS: congue, nibh, tincidunt
1,1 1,N LIGULA metus LACUS blandit elit EROS congue nibh tincidunt
In [99]:
display.HTML("mocodo_notebook/sandbox_verbose.html")
Out[99]:
EROS ( congue, nibh, tincidunt )
  • Le champ congue constitue la clé primaire de la table. C'était déjà un identifiant de l'entité EROS.
  • Les champs nibh et tincidunt étaient déjà de simples attributs de l'entité EROS.
LACUS ( blandit, elit )
  • Le champ blandit constitue la clé primaire de la table. C'était déjà un identifiant de l'entité LACUS.
  • Le champ elit était déjà un simple attribut de l'entité LACUS.
LIGULA ( #blandit, #congue, metus )
  • Avertissement. Table résultant de la conversion forcée d'une association DF.
  • Le champ blandit constitue la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité LACUS.
  • Le champ congue est une clé étrangère. Il a migré directement de l'entité EROS en perdant son caractère identifiant.
  • Le champ metus était déjà un simple attribut de l'association LIGULA.

La nouvelle notation fonctionne quelles que soient les cardinalités de l'association. Si cette dernière devait déjà donner lieu à la création d'une table, l'indication est visualisée, mais ignorée lors du passage au relationnel.

In [100]:
%%mocodo --relations html_verbose
LACUS: blandit, elit
[LIGULA], 1N LACUS, 1N EROS: metus
EROS: congue, nibh, tincidunt
1,N 1,N LIGULA metus LACUS blandit elit EROS congue nibh tincidunt
In [101]:
display.HTML("mocodo_notebook/sandbox_verbose.html")
Out[101]:
EROS ( congue, nibh, tincidunt )
  • Le champ congue constitue la clé primaire de la table. C'était déjà un identifiant de l'entité EROS.
  • Les champs nibh et tincidunt étaient déjà de simples attributs de l'entité EROS.
LACUS ( blandit, elit )
  • Le champ blandit constitue la clé primaire de la table. C'était déjà un identifiant de l'entité LACUS.
  • Le champ elit était déjà un simple attribut de l'entité LACUS.
LIGULA ( #blandit, #congue, metus )
  • Le champ blandit fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité LACUS.
  • Le champ congue fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité EROS.
  • Le champ metus était déjà un simple attribut de l'association LIGULA.

Limitation. Cette conversion forcée ne fonctionne pas sur les associations nommées « DF ».

Réduction de clé primaire (ou agrégation, ou pseudo-entité)

Il arrive qu'un sous-ensemble strict de l'ensemble des identifiants des entités mises en jeu dans une association dont toutes les pattes portent la cardinalité N, suffise à constituer la clé primaire de la table issue de cette association : cela se fait facilement au niveau relationnel en privant de leur caractère identifiant les clés qui n'appartiennent pas à ce sous-ensemble.

In [102]:
%%mocodo --mld
Date: Date
Réserver, /1N Client, 1N Chambre, 0N Date: Durée
Chambre: Numéro, Prix

Client: Id. client
1,N 1,N 0,N Réserver Durée Date Date Chambre Numéro Prix Client Id. client
Chambre ( Numéro, Prix )
Réserver ( #Numéro, Date, Id. client, Durée )

C'est plus ou moins équivalent à la notion traditionnelle d'agrégation ou pseudo-entité. Le traitement se généralise naturellement aux agrégats réduits à une seule entité :

In [103]:
%%mocodo --mld
LACUS: blandit, elit
LIGULA, 0N LACUS, /1N EROS: metus
EROS: congue, nibh, tincidunt
0,N 1,N LIGULA metus LACUS blandit elit EROS congue nibh tincidunt
EROS ( congue, nibh, tincidunt )
LACUS ( blandit, elit )
LIGULA ( #blandit, #congue, metus )

Traitement de l'héritage

Sémantique de la flèche

  • Le sens de la flèche détermine si la migration d'attributs se fait de la mère vers les filles (>) ou l'inverse (<).
  • Son épaisseur détermine si la migration est « minimale » (-) ou « maximale » (=).
In [104]:
%%mocodo --mld
Personne: num SS, nom, prénom

/XT\ Personne <- Homme, Femme: sexe

Homme: 
:
Femme: nom de jeune fille
XT Personne num SS nom prénom Homme Femme nom de jeune fille
Personne ( num SS, nom, prénom, sexe, nom de jeune fille )

Ci-dessus, le passage au relationnel produit une seule table :

  • num SS est l'identifiant ;
  • nom et prénom sont des champs communs à toutes les occurrences ;
  • sexe permet de préciser si une ligne donnée correspond à un homme et/ou une femme. Si le type d'héritage est total et exclusif, un booléen « non nullable » (NOT NULL en SQL) fera l'affaire ; s'il n'y a pas totalité, certaines personnes ne sont ni homme, ni femme, et ce booléen est « nullable » ; s'il n'y a pas exclusion, certaines personnes peuvent être à la fois homme et femme, et dans ce cas on peut choisir de coder le type par un entier que l'on interprétera en binaire.
  • nom de jeune fille est un attribut spécifique aux femmes. Notez qu'il peut être nul, non seulement pour les occurrences « non femmes », mais aussi pour les occurrences « femmes » célibataires. Cela montrer l'intérêt de disposer d'un champ sexe séparé.
In [105]:
%%mocodo --mld
Personne: num SS, nom, prénom

/XT\ Personne <= Homme, Femme: sexe

Homme: 
:
Femme: nom de jeune fille
XT Personne num SS nom prénom Homme Femme nom de jeune fille
Personne ( num SS, nom, prénom, sexe, Homme, Femme, nom de jeune fille )

Ci-dessus, on a doublé la flèche pour réaliser une migration « maximale » des entités-filles vers l'entité-mère. Notez le doublement des pattes qui distinguent les entités-filles. Deux nouveaux champs sont apparus : Homme et Femme, censés être de type booléen. Selon le type d'héritage, ils sont ici plus ou moins redondants avec sexe (si c'est /XT\, sexe est préférable, mais si c'est /\, sexe peut être supprimé).

In [106]:
%%mocodo --mld
Personne: num SS, nom, prénom

/XT\ Personne -> Homme, Femme: sexe

Homme: 
:
Femme: nom de jeune fille
XT Personne num SS nom prénom Homme Femme nom de jeune fille
Femme ( #num SS, nom de jeune fille )
Homme ( #num SS )
Personne ( num SS, nom, prénom, sexe )

Ci-dessus, on a réalisé une migration « minimale » de la mère vers les filles. Notez l'inversion du sens des flèches sur le schéma conceptuel.

  • Une table Personne accueille les attributs communs. Notez la présence du champ sexe.
  • Une table Femme complète ces informations par l'attribut spécifique nom de jeune fille.
  • La table Homme, réduite à sa clé primaire, a été supprimée.
In [107]:
%%mocodo --mld
Personne: num SS, nom, prénom

/XT\ Personne => Homme, Femme: sexe

Homme: 
:
Femme: nom de jeune fille
XT Personne num SS nom prénom Homme Femme nom de jeune fille
Femme ( num SS, nom, prénom, nom de jeune fille )
Homme ( num SS, nom, prénom )

Avec une migration « maximale » vers les entités-filles, les attributs communs sont « déplacés » dans chacune des tables-filles. Aucune table-mère n'est créée.

Cela n'est possible que si l'héritage est total (/T\ ou /XT\) ; dans le cas contraire, certaines occurrences (celles qui ne sont ni homme, ni femme) seraient perdues. Mocodo lève alors une erreur :

In [108]:
%%mocodo --mld
Personne: num SS, nom, prénom

/X\ Personne => Homme, Femme: sexe

Homme: 
:
Femme: nom de jeune fille
Mocodo Err.25 - La totalité (/T\ or /XT\) est requise pour définir l'héritage « => » sur
l'entité-mère « Personne ».

Héritage et associations externes

Trois des quatre mécanismes de passage au relationnel décrits ci-dessus conduisent à la disparition d'entités. Pour assurer que les jointures restent possibles, il faut alors veiller à « recoller » les références qui transitaient par ces entités. On se donne ci-dessous un MCD où les entités d'un héritage sont associées de façon diverses à des entités externes, et on étudie les tables et le diagramme relationnel produits selon le mécanisme de passage au relationnel demandé.

Aide. Cliquez sur le nom des tables pour lire les explications détaillées. Survolez le libellé des attributs pour afficher leur catégorie attribuée en interne par Mocodo (à des fins de débogage).

Voici un éventail de cas possibles pour le mécanisme de migration <- vers une entité-mère, avec disparition des entités-filles (le cas <=, essentiellement identique, n'est pas donné).

In [109]:
%%mocodo --relations diagram html_verbose
SUSCIPIT: orci, lorem
RHONCUS, 1N TRISTIS, 11 SUSCIPIT
:
:
SODALES: convallis, ipsum
VITAE, 11 QUAM, 1N SODALES
QUAM: cras, sed

CONSEQUAT: fermentum, dederit
ELIT, 11 TRISTIS, 1N CONSEQUAT
TRISTIS: magna, vestibulum
/XT\ TRISTIS <- SODALES, NEC, LACUS: type
NEC: pulvinar, audis
MOLLIS, 1N CURABITUR, 11 NEC
CURABITUR: gravida, amor

DIGNISSIM: tellus, terra
ALIQUET, 1N TRISTIS, 1N DIGNISSIM
:
:
LACUS: tempor, fugit
ULTRICES, 1N LIBERO, 1N LACUS
LIBERO: posuere, lacrima
1,N 1,1 RHONCUS 1,1 1,N VITAE 1,1 1,N ELIT XT 1,N 1,1 MOLLIS 1,N 1,N ALIQUET 1,N 1,N ULTRICES SUSCIPIT orci lorem SODALES convallis ipsum