Mocodo

  • 1  Introduction
    • 1.1  Tracé du modèle conceptuel
    • 1.2  Opérations de conversion
    • 1.3  Opérations de réécriture
  • 2  Installation et lancement du programme
    • 2.1  Installation minimale
    • 2.2  Installation complète (recommandé)
    • 2.3  Utilisation par importation
  • 3  Syntaxe de description d'un MCD
    • 3.1  Notions élémentaires
      • 3.1.1  Entités, associations, attributs, identifiants, cardinalités
      • 3.1.2  Dépendances fonctionnelles entre entités
      • 3.1.3  Associations réflexives
      • 3.1.4  Identifiants composites
      • 3.1.5  Flèches sur les pattes
      • 3.1.6  Types de données
      • 3.1.7  Tracé d'un MCD : principes
    • 3.2  Extensions du modèle
      • 3.2.1  Entité faible (ou identification relative)
      • 3.2.2  Héritage (généralisation / spécialisation)
      • 3.2.3  Contrainte inter-associations
      • 3.2.4  Agrégat (ou pseudo-entité)
      • 3.2.5  CIF à unicité complète
      • 3.2.6  Identifiants explicites dans les associations
  • 4  Conversion d'un MCD
    • 4.1  Passage au relationnel
      • 4.1.1  Niveau logique
      • 4.1.2  Niveau physique : DDL
      • 4.1.3  Notes sur les règles de passage
      • 4.1.4  Ajustement des règles de passage
      • 4.1.5  Autres sorties relationnelles
    • 4.2  Autres conversions
      • 4.2.1  Diagramme de classes UML
      • 4.2.2  ERD avec la convention Look across
      • 4.2.3  Dictionnaire des données
      • 4.2.4  URL de partage
  • 5  Mocodo pour la pédagogie
    • 5.1  Vue en extension
    • 5.2  MCD interactif
      • 5.2.1  Afficher des explications au survol
      • 5.2.2  Dévoiler un MCD par étapes
    • 5.3  Explications du passage au relationnel
    • 5.4  MCD à compléter
      • 5.4.1  Supprimer le marquage d'un identifiant
      • 5.4.2  Masquer un couple de cardinalités
      • 5.4.3  Masquer un attribut
      • 5.4.4  Ne faire apparaître que le squelette du schéma conceptuel
    • 5.5  Obfuscation d'un MCD donné
    • 5.6  Croissance stochastique
    • 5.7  Génération d'un QR code
    • 5.8  Bibliothèque de MCD en ligne
      • 5.8.1  Accès sous Mocodo online
      • 5.8.2  Accès sous terminal ou Jupyter Notebook
  • 6  Compléments sur l'aspect visuel
    • 6.1  Styles
    • 6.2  Paramétrage du réarrangement automatique
      • 6.2.1  Méthode exacte (branch & bound)
      • 6.2.2  Méthode heuristique (algorithme génétique)
    • 6.3  Amélioration du plongement
      • 6.3.1  Par duplication d'entités réduites à leur identifiant
      • 6.3.2  Par suppression de ces mêmes entités
    • 6.4  Ajustement de l'aspect de certains éléments
      • 6.4.1  Format des cardinalités
      • 6.4.2  Format des clés étrangères
      • 6.4.3  Symbole de dépendance fonctionnelle
      • 6.4.4  Basculement des cardinalités et inflexion des pattes rectilignes
      • 6.4.5  Positionnement des contraintes
      • 6.4.6  Gouttière d'identifiants
      • 6.4.7  Style et direction des pattes de l'héritage
    • 6.5  Retouches fines
    • 6.6  Conversion dans d'autres formats graphiques
  • 7  Annexe A : Miscellanées académiques
    • 7.1  Décompositions d'un MCD
      • 7.1.1  Vider les DF de leurs attributs
      • 7.1.2  Décomposer les DF n-aires
      • 7.1.3  Décomposer les associations n-aires non DF
      • 7.1.4  Décomposer les associations binaires non DF
      • 7.1.5  Décomposer en créant des entités faibles
      • 7.1.6  Conclusion sur ces décompositions
    • 7.2  Équivalences avec la convention Look Across
      • 7.2.1  Associations binaires en Look Across
      • 7.2.2  Associations n-aires en Look Across
  • 8  Annexe B : La commande mocodo
    • 8.1  Paramétrage
      • 8.1.1  mocodo --help
      • 8.1.2  Paramétrage à long terme
      • 8.1.3  Dissection de la commande
    • 8.2  L'option --transform et ses arguments
      • 8.2.1  Triage et exécution des transformations
      • 8.2.2  Aide-mémoire des transformations
      • 8.2.3  Réécriture d'éléments donnés
    • 8.3  Fonctionnement de la commande magique
    • 8.4  Gabarits de passage au relationnel
      • 8.4.1  Format des gabarits
      • 8.4.2  Dérivation de gabarits
      • 8.4.3  Exemples de création de gabarit dérivé
      • 8.4.4  Mécanisme de mise à jour
  • 9  Annexe C : Crédits
In [1]:
%reload_ext mocodo
Mocodo 4.3.2 loaded.
In [2]:
from IPython import display
from pathlib import Path
import os
if Path.cwd().name != "mocodo_notebook":
    Path("mocodo_notebook").mkdir(parents=True, exist_ok=True)
    os.chdir("mocodo_notebook")

Introduction¶

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

  • En entrée, il prend un MCD (modèle conceptuel de données) décrit dans un langage dédié minimaliste.
  • En sortie, il produit un diagramme entité-association et, à la demande, un MLD (schéma relationnel, sous forme graphique ou textuelle), un DDL (script SQL de création de la base), un diagramme de classes UML, etc.
  • En bonus, il est capable de réarranger automatiquement votre MCD de façon esthétique, et de lui appliquer des opérations de réécriture qui vont du mondain (typographie) à l'académique (décomposition d'associations), en passant par le merveilleux (inférence de types, génération d'exercices et d'exemples).

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).

Tracé du modèle conceptuel¶

Ci-dessous, un exemple d'utilisation sous Jupyter Notebook. L'appel du programme est en première ligne ; le texte-source proprement dit, lignes suivantes. En sortie, le diagramme conceptuel, égayé au passage par l'option --colors :

In [3]:
%%mocodo --colors ocean
Client: Réf. client [VARCHAR(8)], Nom [VARCHAR(255)], Prénom [VARCHAR(255)], Adresse [VARCHAR(255)]
Passer, 0N Client, 11 Commande
Commande: Num. commande [VARCHAR(8)], Date [DATE], Montant [DECIMAL(10,2)]
Inclure, 1N Commande, 0N Produit: Quantité [INTEGER]
Produit: Réf. produit [VARCHAR(8)], Libellé [VARCHAR(50)], Prix unitaire [DECIMAL(10,2)]
No description has been provided for this image

Opérations de conversion¶

L'appel précédent a automatiquement enregistré le texte-source sous le nom de sandbox.mcd. Renommons-le ccp.mcd pour y avoir accès tout au long de ce document.

In [4]:
Path("sandbox.mcd").rename("ccp.mcd");

On peut le récupérer avec --input pour lui appliquer diverses opérations. Ainsi, l'appel suivant génère et affiche son MLD, son diagramme relationnel et son DDL :

In [5]:
%mocodo --input ccp --transform mld diagram ddl --colors mondrian

ccp_mld.md
  • Client (Réf. client, Nom, Prénom, Adresse)
  • Commande (Num. commande, Date, Montant, #Réf. client)
  • Inclure (#Num. commande, #Réf. produit, Quantité)
  • Produit (Réf. produit, Libellé, Prix unitaire)

ccp_mld.svg
No description has been provided for this image

ccp_ddl.sql
CREATE TABLE Client (
  PRIMARY KEY (Ref_client),
  Ref_client VARCHAR(8) NOT NULL,
  Nom        VARCHAR(255),
  Prenom     VARCHAR(255),
  Adresse    VARCHAR(255)
);

CREATE TABLE Commande (
  PRIMARY KEY (Num_commande),
  Num_commande VARCHAR(8) NOT NULL,
  Date         DATE,
  Montant      DECIMAL(10,2),
  Ref_client   VARCHAR(8) NOT NULL
);

CREATE TABLE Inclure (
  PRIMARY KEY (Num_commande, Ref_produit),
  Num_commande VARCHAR(8) NOT NULL,
  Ref_produit  VARCHAR(8) NOT NULL,
  Quantite     INTEGER
);

CREATE TABLE Produit (
  PRIMARY KEY (Ref_produit),
  Ref_produit   VARCHAR(8) NOT NULL,
  Libelle       VARCHAR(50),
  Prix_unitaire DECIMAL(10,2)
);

ALTER TABLE Commande ADD FOREIGN KEY (Ref_client) REFERENCES Client (Ref_client);

ALTER TABLE Inclure ADD FOREIGN KEY (Ref_produit) REFERENCES Produit (Ref_produit);
ALTER TABLE Inclure ADD FOREIGN KEY (Num_commande) REFERENCES Commande (Num_commande);

Dans la suite, pour épargner la frappe, les options --input et --transform seront respectivement abrégées en -i et -t.

Les opérations de conversion ne se limitent pas forcément au schéma relationnel. En voici une qui extrait un dictionnaire des données, par défaut sous la forme d'un tableau Markdown à trois colonnes :

In [6]:
%mocodo -i ccp -t data_dict

ccp_data_dict_3.md
Entité ou association Libellé de l'attribut Type
Client Adresse VARCHAR(255)
" Nom VARCHAR(255)
" Prénom VARCHAR(255)
" Réf. client VARCHAR(8)
Commande Date DATE
" Montant DECIMAL(10,2)
" Num. commande VARCHAR(8)
Inclure Quantité INTEGER
Produit Libellé VARCHAR(50)
" Prix unitaire DECIMAL(10,2)
" Réf. produit VARCHAR(8)

Une autre qui transcrit le MCD dans la notation crow's foot (crow) pour Mermaid (mmd) :

In [7]:
%mocodo -i ccp -t crow:mmd

ccp_erd_crow.mmd
mmd
erDiagram
  Client {
    VARCHAR(8) Ref_client PK
    VARCHAR(255) Nom
    VARCHAR(255) Prenom
    VARCHAR(255) Adresse
  }
  Commande {
    VARCHAR(8) Num_commande PK
    DATE Date
    DECIMAL(10-2) Montant
  }
  Inclure {
    INTEGER Quantite PK
  }
  Produit {
    VARCHAR(8) Ref_produit PK
    VARCHAR(50) Libelle
    DECIMAL(10-2) Prix_unitaire
  }
  Client ||--o{ Commande: Passer
  Inclure }|..|| Commande: DF
  Inclure }o..|| Produit: DF

Le rendu des diagrammes décrits dans des langages-tiers (comme Mermaid, PlantUML, etc.) n'est pas directement pris en charge, mais peut être délégué (--defer) de façon transparente au service web approprié. Dans ce cas, c'est la sortie graphique qui est affichée :

In [8]:
%mocodo -i ccp -t crow:plantuml --defer

ccp_erd_crow.svg
No description has been provided for this image

Opérations de réécriture¶

Une réécriture transforme un MCD Mocodo en un autre MCD Mocodo (au contraire d'une conversion, qui produit un animal d'une espèce différente).

Heureusement, l'utilisateur n'a pas à réfléchir si la transformation qu'il souhaite appliquer est une réécriture ou une conversion : dans les deux cas, il invoque -t (c'est-à-dire --transform), et Mocodo se débrouille.

En guise de premier exemple de réécriture, mettons les noms des entités et associations (boxes) en majuscules, et les libellés (labels) en ASCII et snake case :

In [9]:
%mocodo -i ccp -t upper:boxes ascii:labels snake:labels --colors brewer+3
No description has been provided for this image

ccp.mcd
%%mocodo --colors brewer+3
CLIENT: Ref_client [VARCHAR(8)], Nom [VARCHAR(255)], Prenom [VARCHAR(255)], Adresse [VARCHAR(255)]
PASSER, 0N CLIENT, 11 COMMANDE
COMMANDE: Num_commande [VARCHAR(8)], Date [DATE], Montant [DECIMAL(10,2)]
INCLURE, 1N COMMANDE, 0N PRODUIT: Quantite [INTEGER]
PRODUIT: Ref_produit [VARCHAR(8)], Libelle [VARCHAR(50)], Prix_unitaire [DECIMAL(10,2)]

Remarquez que l'exécution d'une réécriture affiche, au-dessous du diagramme, le code-source résultant. Celui-ci est précédé de la commande magique originale, privée de l'option -i et de toute opération de réécriture. Ces dispositions permettent de continuer à travailler directement dessus si on le copie-colle dans une autre cellule.

Plusieurs opérations de réécriture de nature sémantique sont également offertes. Par exemple, on peut décomposer un MCD quelconque en un MCD équivalent, mais n'employant que des dépendances fonctionnelles et des entités faibles :

In [10]:
%mocodo -i ccp -t explode:weak,arity=2 arrange:wide --seed=3 --colors brewer+3
No description has been provided for this image

ccp.mcd
%%mocodo --seed=3 --colors brewer+3
Client: Réf. client [VARCHAR(8)], Nom [VARCHAR(255)], Prénom [VARCHAR(255)], Adresse [VARCHAR(255)]
Passer, 0N Client, 11 Commande
Commande: Num. commande [VARCHAR(8)], Date [DATE], Montant [DECIMAL(10,2)]
DF, _11 Inclure, 1N Commande
Inclure: _Quantité [INTEGER]
DF, _11 Inclure, 0N Produit
Produit: Réf. produit [VARCHAR(8)], Libellé [VARCHAR(50)], Prix unitaire [DECIMAL(10,2)]

Notez l'argument arrange:wide. Il a procédé à une réorganisation aléatoire des boîtes, ce que l'insertion de deux nouvelles associations de dépendance fonctionnelles avait rendu nécessaire. Quant à l'option --seed=3, elle garantit que le résultat sera le même à chaque exécution.

Après cet aperçu de quelques-unes des fonctionnalités de Mocodo, entrons dans les détails.

Installation et lancement du programme¶

Comme nous l'avons dit, vous pouvez utiliser Mocodo sans rien installer. Il vous suffit d'aller sur mocodo.net et de commencer à taper votre MCD. Appuyez à tout moment sur le ventilateur pour rafraîchir les diagrammes conceptuel et relationnel. Quand 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, nous vous conseillons d'installer Mocodo sur votre machine.

Installation minimale¶

Mocodo est un programme écrit en Python 3. Si vous êtes sous macOS ou Linux, il est déjà installé. Dans le cas contraire, vous devrez peut-être le faire.

Une fois Python présent sur votre machine, tapez sous un terminal:

    python -m pip install mocodo

Puis testez-le :

    mocodo

Invoqué sous cette forme, Mocodo 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 à votre fantaisie avant de relancer la commande.

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:

  • sous Linux ou macOS ;
  • sous Windows.

Installation complète (recommandé)¶

  • Installez la distribution Anaconda, qui contient Python 3, Jupyter Notebook et bien plus encore.

  • La ligne donnée précédemment installe en fait, en plus de Mocodo, sa « commande magique » pour Jupyter Notebook. Nous l'avons déjà invoquée plusieurs fois dans ce document :

      python -m pip install mocodo
  • Mocodo fonctionne parfaitement sans aucune dépendance. Cependant, si vous souhaitez :

    • utiliser l'option --svg_to pour générer des figures en PDF ou en PNG ;
    • copier directement dans le presse-papier le résultat d'une réécriture ;

    ... vous pouvez installer les dépendances optionnelles aux bibliothèques CairoSVG et Pyperclip ainsi :

      python -m pip install 'mocodo[svg,clipboard]'

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 la commande :

In [11]:
%%mocodo
MISSION: accomplie
No description has been provided for this image

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

  • exécutez sous un terminal :
ipython profile create
  • éditez le fichier créé (p. ex.: ~/.ipython/profile_default/ipython_config.py) en remplaçant la ligne suivante :
# c.TerminalIPythonApp.extensions = []

par celle-ci :

c.InteractiveShellApp.extensions = ["mocodo"]

Utilisation par importation¶

Nouveauté de la version 4.1.3. Un wrapper minimaliste permet de simuler programmatiquement l'appel à la commande mocodo.

In [12]:
from mocodo.api import mocodo

Ainsi, l'équivalent de :

mocodo -i ccp --colors mondrian

... s'écrira :

In [13]:
messages = mocodo("-i ccp --colors mondrian")

Par défaut (second argument quiet=True), la fonction n'affiche pas les messages de succès, mais renvoie leur concaténation :

In [14]:
print(messages)
Fichier de sortie « ~/Dropbox/Sites/mocodo/doc/mocodo_notebook/ccp.svg » généré avec succès.

Plus important, les fichiers de sortie sont bel bien créés :

In [15]:
display.SVG("ccp.svg")
Out[15]:
No description has been provided for this image

Si vous travaillez sous une implantation de Jupyter Notebook qui ne prend pas en charge les commandes magiques, l'importation conseillée est :

In [16]:
from mocodo.magic import mocodo

Elle permet de simuler les commandes magiques, aussi bien celles qui sont réduites à une ligne :

In [17]:
mocodo("%mocodo -i ccp --colors ocean")
No description has been provided for this image

... que celles qui portent sur toute une cellule :

In [18]:
mocodo("""
%%mocodo --colors pond
Mission: accomplie
""")
No description has been provided for this image

Le préfixe "%mocodo" ou "%%mocodo" est ignoré, mais l'autoriser permet de copier toute une ligne ou toute une cellule (vraiment) magique, et de la coller directement comme argument de la fonction.

Nouveauté de la version 4.2. Avec cette technique, Mocodo peut être utilisé sous Basthon v. 0.62.12 ou ultérieure. Basthon est une plateforme permettant de travailler sous Jupyter Notebook sans avoir à rien installer. Son auteur, Romain Casati, a ajouté un exemple d'utilisation de Mocodo dans la galerie du logiciel, à tester ici. Sous Mocodo online, cliquez sur le symbole de lecture de Basthon (dans le pied de page) pour ouvrir un notebook avec le MCD en cours d'édition.

Syntaxe de description d'un MCD¶

Notions élémentaires¶

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

In [19]:
%%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
No description has been provided for this image

Passons en revue les principes de la syntaxe. Ils ne devraient pas poser trop de problèmes.

La première ligne ne fait pas partie de la définition du MCD. Sous Jupyter Notebook, elle dénote l'appel à une « commande magique », qui lance Mocodo sur le reste de la cellule. En dehors d'un notebook, vous n'en avez pas besoin, et toute ligne commençant par un pourcentage (%) sera considérée comme un commentaire.

Une entité est définie par :

son nom⏞COMMANDEdeux-points⏞:ses attributs séparés par des virgules⏞Num. commande, Date, Montant

Notez que le premier attribut d'une entité est considéré par défaut comme son identifiant, et donc souligné.

Une association est définie par :

son nom⏞INCLUREune virgule⏞,ses pattes séparées par des virgules⏞1N⏟cardinalitésCOMMANDE⏟entité,0N⏟cardinalitésPRODUIT⏟entitédeux-points⏞:ses attributs séparés par des virgules⏞Quantité

Notez que pour les associations sans attributs (comme PASSER), le deux-points est facultatif.

Astuce. Si vous recopiez un MCD ou que vous l'avez bien en tête, commencez par les associations et, à tout moment, faites apparaître les entités manquantes (double clic sur le lapin magique sous Mocodo online). Elles auront comme identifiant le nom de l'entité en minuscules, par défaut précédé de « id. » (sauf pour les entités DATE et PÉRIODE). Vous n'aurez plus qu'à remplir les autres attributs :

In [20]:
%%mocodo -t guess:entities
Réserver, 1N Client, 1N Chambre, 0N Date: Durée
No description has been provided for this image

sandbox.mcd
%%mocodo 
Réserver, 1N Client, 1N Chambre, 0N Date: Durée

Client: id. client, 
Chambre: id. chambre, 
Date: date

Dépendances fonctionnelles entre entités¶

Lorsque l'une des cardinalités maximales d'une association binaire est 1 (ou quelquefois 0), on désigne cette association sous le nom de dépendance fonctionnelle. On la figure souvent par un cercle portant le symbole DF : cela évite de se creuser la tête pour trouver un nom à une association qui (spoiler) disparaîtra corps et biens au moment du passage au relationnel.

In [21]:
%%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
No description has been provided for this image

Associations réflexives¶

Quelquefois appelées circulaires, unaires ou récursives, elles associent une entité à elle-même. Voici par exemple une représentation des filiations patrilinéaires (le 01 permet d'« arrêter » la remontée des ancêtres) :

In [22]:
%%mocodo
HOMME: Num. SS, Nom, Prénom
ENGENDRER, 0N HOMME, 01 HOMME
No description has been provided for this image

Identifiants composites¶

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

In [23]:
%%mocodo
GRATTE-CIEL: latitude, _longitude, nom, hauteur, année de construction
No description has been provided for this image

Flèches sur les pattes¶

Suffixez 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 [24]:
%%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
No description has been provided for this image

Types de données¶

Comme on l'a vu dans l'introduction, chaque attribut peut être assorti d'un type entre crochets, qui servira lors de la conversion en SQL. À partir de la version 4.0, Mocodo est capable de deviner le type des attributs usuels à partir de leur nom :

In [25]:
%%mocodo -t guess:types data_dict --select cv
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

sandbox_data_dict_3.md
Entité ou association Libellé de l'attribut Type
CLIENT Adresse VARCHAR(30)
" Nom VARCHAR(255)
" Prénom VARCHAR(255)
" Réf. client VARCHAR(8)
COMMANDE Date DATE
" Montant DECIMAL(10,2)
" Num. commande VARCHAR(8)
INCLURE Quantité INTEGER
PRODUIT Libellé VARCHAR(50)
" Prix unitaire DECIMAL(10,2)
" Réf. produit VARCHAR(8)

Nouveauté de la version 4.3. Avec l'option -t prompt:types, Mocodo compose un prompt à copier-coller sous ChatGPT (ou autre) pour compléter le MCD avec les types manquants. Ce prompt est trop long pour être reproduit ici : il consiste en une présentation de la syntaxe de Mocodo, des instructions sur le travail demandé, plusieurs exemples corrigés, et enfin le MCD à compléter. Voici par exemple les types générés par Claude 3.5 Haiku pour le MCD de la page d'accueil de Mocodo online :

In [26]:
%%mocodo -t data_dict
AYANT-DROIT: nom ayant-droit [VARCHAR(100)], lien [VARCHAR(50)]
DIRIGER, 0N [responsable] EMPLOYÉ, 01 PROJET
REQUÉRIR, 1N PROJET, 0N PIÈCE: qté requise [INTEGER]
PIÈCE: réf. pièce [VARCHAR(20)], libellé pièce [VARCHAR(255)]
COMPOSER, 0N [composée] PIÈCE, 0N [composante] PIÈCE: quantité [INTEGER]

DF, _11 AYANT-DROIT, 0N EMPLOYÉ
EMPLOYÉ: matricule [VARCHAR(20)], nom employé [VARCHAR(100)]
PROJET: num. projet [VARCHAR(20)], nom projet [VARCHAR(255)]
FOURNIR, 1N PROJET, 1N PIÈCE, 1N SOCIÉTÉ: qté fournie [INTEGER]

DÉPARTEMENT: num. département [VARCHAR(20)], nom département [VARCHAR(100)]
EMPLOYER, 11 EMPLOYÉ, 1N DÉPARTEMENT
TRAVAILLER, 0N EMPLOYÉ, 1N PROJET
SOCIÉTÉ: num. société [VARCHAR(20)], raison sociale [VARCHAR(255)]
CONTRÔLER, 0N< [mère] SOCIÉTÉ, 01 [filiale] SOCIÉTÉ

sandbox_data_dict_3.md
Entité ou association Libellé de l'attribut Type
AYANT-DROIT lien VARCHAR(50)
" nom ayant-droit VARCHAR(100)
COMPOSER quantité INTEGER
DÉPARTEMENT nom département VARCHAR(100)
" num. département VARCHAR(20)
EMPLOYÉ matricule VARCHAR(20)
" nom employé VARCHAR(100)
FOURNIR qté fournie INTEGER
PIÈCE libellé pièce VARCHAR(255)
" réf. pièce VARCHAR(20)
PROJET nom projet VARCHAR(255)
" num. projet VARCHAR(20)
REQUÉRIR qté requise INTEGER
SOCIÉTÉ num. société VARCHAR(20)
" raison sociale VARCHAR(255)

Ce problème d'inférence n'est pas très difficile pour une IA. Les résultats devraient être très bons, surtout en comparaison de ceux de la version purement algorithmique, qui sont généralement incomplets :

In [27]:
%%mocodo -t guess:types data_dict --select cv
AYANT-DROIT: nom ayant-droit, lien
DIRIGER, 0N [responsable] 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é

DF, _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< [mère] SOCIÉTÉ, 01 [filiale] SOCIÉTÉ

sandbox_data_dict_3.md
Entité ou association Libellé de l'attribut Type
AYANT-DROIT lien
" nom ayant-droit VARCHAR(255)
COMPOSER quantité INTEGER
DÉPARTEMENT nom département VARCHAR(255)
" num. département VARCHAR(8)
EMPLOYÉ matricule
" nom employé VARCHAR(255)
FOURNIR qté fournie INTEGER
PIÈCE libellé pièce
" réf. pièce VARCHAR(8)
PROJET nom projet VARCHAR(255)
" num. projet VARCHAR(8)
REQUÉRIR qté requise INTEGER
SOCIÉTÉ num. société VARCHAR(8)
" raison sociale

Tracé d'un MCD : principes¶

Mocodo combine les avantages de l'approche diagram as code (comme PlantUML, Mermaid ou Graphviz), avec la liberté de positionnement offerte par les logiciels WYSIWYG (what you see is what you get).

Sa grande originalité est de se baser sur l'ordre et la séparation des lignes de la description pour définir une mise en page qui se révèle suffisante dans la majorité des cas.

Le pont aux ânes du langage Mocodo¶

Premier principe : les boîtes (entités et associations) définies sur des lignes consécutives sont tracées sur une seule rangée.

Si l'on écrit les définitions sur des lignes consécutives, on se retrouve donc vite avec des chevauchements qui ne sautent pas forcément aux yeux :

In [28]:
%%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é
No description has been provided for this image

L'option --detect_overlaps (active par défaut sous Mocodo online) signale le problème et donne la solution :

In [29]:
%mocodo -i sandbox --detect_overlaps
Mocodo Err.29 - Mauvaise disposition des boîtes :
  - La patte « INCLURE — COMMANDE » chevauche « PRODUIT ».
  - La patte « INCLURE — PRODUIT » chevauche « PASSER ».
  - La patte « PASSER — CLIENT » chevauche « COMMANDE ».
  - Les pattes  « PASSER — COMMANDE » et « INCLURE — COMMANDE » se chevauchent.
Pour corriger cela, réordonnez et/ou sautez des lignes dans le texte-source, soit à la
main, soit à l'aide de l'option -t arrange (tablette de chocolat sous Mocodo online).

Limitation. Seuls les chevauchements mettant en jeu des pattes horizontales ou verticales sont détectés.

MCD sur plusieurs lignes¶

Deuxième principe : pour commencer une nouvelle rangée, il faut sauter une ligne :

In [30]:
%%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
No description has been provided for this image

Les centres des boîtes sont placés aux intersections d'une grille invisible. Ils sont donc alignés aussi bien horizontalement que verticalement. De plus, dans un but esthétique, le dessin fait l'objet d'une compression dans les deux dimensions. Par exemple, ci-dessus, un espace horizontal négatif a été créé entre le bord droit de l'entité de gauche et le bord gauche de l'entité de droite.

Mise en miroir¶

Mocodo permet de calculer facilement les symétriques d'un MCD :

  • verticalement : -t flip:v ;
  • horizontalement : -t flip:h ;
  • selon la seconde diagonale (transposition) : -t flip:d.
  • selon la première diagonale (transposition) : -t flip:vhd.
In [31]:
%mocodo -i sandbox --select mcd -t flip:h
No description has been provided for this image

Corrections de la version 4.0.

  • Les sens de « horizontal » et « vertical » sont permutés pour être plus conformes à l'intuition.
  • La documentation parlait de première diagonale, c'était la seconde, et vice-versa.

Astuce. Transposez le MCD temporairement pour réaliser plus facilement certaines opérations d'édition en colonne, en particulier sous Mocodo online.

Insertion d'espacements¶

Mocodo centre les rangées qui contiennent moins de boîtes que les autres. Ce comportement n'est pas toujours idéal :

In [32]:
%%mocodo 
Ultrices, 01 Aliquet, 0N Aliquet
Aliquet: hendrerit, metus, lacus, quis
Risus, 1N Aliquet, 0N Massa
Massa: metus, posuere
Euismod, 0N Massa, 0N Massa

Convallis, 0N Aliquet, 0N Ante: vestibulum
Tincidunt, 11 Ante, 0N Massa

Gravida: ornare
Rutrum, 0N Gravida, 0N Ante, 0N Aliquet: faucibus, curae
Ante: vitae, tempor
No description has been provided for this image

L'utilisateur peut alors 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. Cela se fait en insérant manuellement des lignes réduites au caractère deux-points :

In [33]:
%%mocodo
Ultrices, 01 Aliquet, 0N Aliquet
Aliquet: hendrerit, metus, lacus, quis
Risus, 1N Aliquet, 0N Massa
Massa: metus, posuere
Euismod, 0N Massa, 0N Massa

:
:
Convallis, 0N Aliquet, 0N Ante: vestibulum
Tincidunt, 11 Ante, 0N Massa

Gravida: ornare
Rutrum, 0N Gravida, 0N Ante, 0N Aliquet: faucibus, curae
:
Ante: vitae, tempor
No description has been provided for this image

Réarrangement automatique¶

Cependant, en général, ces manipulations sont inutiles : Mocodo est capable de calculer tout seul des plongements à la fois compacts et esthétiques. Voici une compilation des réarrangements automatiques du MCD précédent produits par :

%mocodo -i sandbox -t arrange --seed 1
%mocodo -i sandbox -t arrange --seed 2
%mocodo -i sandbox -t arrange --seed 3
%mocodo -i sandbox -t arrange --seed 4
In [34]:
%mocodo -i ../examples/four_random_layouts --scale 0.8
No description has been provided for this image

Extensions du modèle¶

Entité faible (ou identification relative)¶

Préfixez d'un tiret bas (_) une cardinalité 11 pour indiquer que l'entité distinguée est faible.

In [35]:
%%mocodo
ŒUVRE: Cote œuvre, Titre, Date parution
DF, 1N ŒUVRE, _11 EXEMPLAIRE
EXEMPLAIRE: Num. exemplaire, État du livre, Date d'achat
No description has been provided for this image

Dans le diagramme, les identifiants (ou plutôt, discriminateurs) d'une telle entité seront soulignés en pointillés, tandis que le 11 sera par défaut souligné d'un trait plein.

Notez qu'un discriminateur n'est pas toujours obligatoire :

In [36]:
%%mocodo 
Employé: Num. employé, Nom employé, Prénom employé
Df, _11 Conjoint, 01 Employé
Conjoint: _Nom conjoint, Prénom conjoint
No description has been provided for this image

Son absence implique cependant que l'occurrence de l'entité forte qui « renforce » une occurrence de l'entité faible ne peut en renforcer une autre : d'où la cardinalité maximale 1 sur la patte distinguant EMPLOYÉ.

Mocodo rejettera donc la version « polygame » du MCD précédent (avec 0N à la place de 01) :

In [37]:
%%mocodo
Employé: Num. employé, Nom employé, Prénom employé
Df, _11 Conjoint, 0N Employé
Conjoint: _Nom conjoint, Prénom conjoint
Mocodo Err.50 - L'entité faible « CONJOINT » devrait avoir un discriminateur.

Héritage (généralisation / spécialisation)¶

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.

Pour définir une spécialisation, insérez une ligne spécifiant :

sa nature entre barres obliques⏞/XT\son type de flèche⏞<-une entité⏞mèreune virgule⏞,des entités séparées par des virgules⏞fille 1, fille 2, fille 3optionnellement, un attribut⏞: discriminateur

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

/XT\ Personne <- Homme, Femme: sexe

Homme: 
:
Femme: nom de jeune fille
No description has been provided for this image

Inscrivez dans le triangle les symboles de votre choix pour prendre une part active aux guerres culturelles de notre temps :

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

Contrainte inter-associations¶

Pour définir une telle contrainte, ajoutez n'importe où une ligne spécifiant :

son nom entre parenthèses⏞(FOO)les types de liens et les boîtes qu'elle met en jeu, séparés par des virgules⏞->boîte 1,..boîte 2,--boîte 3,boîte 4optionnellement, ses coordonnées⏞:horizontale, verticale

Précisions.

  • Comme leur nom ne l'indique pas, ces contraintes peuvent aussi bien porter sur des entités que des associations.
  • Le nom d'une contrainte peut être formé de zéro à trois symboles quelconques.
  • Un lien est soit vide (trait invisible), soit formé d'un ou plusieurs symboles - (trait plein) ou . (trait pointillé), optionnellement précédés d'un symbole < (flèche vers la contrainte) et/ou suivis d'un symbole > (flèche vers la boîte).
  • 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 l'exemple ci-dessous a donc dû être « aéré » avec des : pour leur faire de la place.
  • Les clauses de définition des contraintes peuvent apparaître n'importe où. Notez cependant que tout réarrangement automatique les enverra systématiquement à la fin du texte-source.
  • Chaque coordonnée du centre de la contrainte peut être exprimée sous la forme :
    • d'une référence à une boîte sur laquelle l'aligner horizontalement ou verticalement (respectivement) ;
    • d'un pourcentage de la largeur ou de la hauteur (respectivement) du MCD.
  • En l'absence de coordonnées, la contrainte est placée au barycentre des boîtes qu'elle relie.

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

In [39]:
%%mocodo -t
:::
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
No description has been provided for this image
  • Article (réf. article, prix)
  • Commande (num. commande, date, #num dépôt)
  • Composer (#num. commande, #réf. article)
  • Dépôt (num dépôt, surface)
  • Stocker (#num dépôt, #réf. article, quantité)

Notez que pour Mocodo, ces contraintes sont purement décoratives : le passage au niveau relationnel ou physique n'en tient pas compte.

Agrégat (ou pseudo-entité)¶

Dans le MCD ci-dessous, le petit rond et l'enveloppe pointillée indiquent qu'une réservation d'une chambre donnée à une date donnée ne peut être faite que par un seul client :

In [40]:
%%mocodo --colors ocean # changement de palette pour faire apparaître un fond semi-transparent 
Date: Date
Réserver, /1N Client, 1N Chambre, 0N Date: Durée
Chambre: Num. chambre, Prix

Client: Id. client
No description has been provided for this image

La syntaxe est minimale : une simple barre oblique / avant la cardinalité de l'entité-cible.

S'il y a au maximum deux entités à agréger, et que l'angle formé par l'association et les entités est plat ou rectangle, une enveloppe de points matérialise la pseudo-entité.

Sinon, pour des raisons de simplicité du code et de clarté du diagramme, l'enveloppe n'est pas affichée. Cependant, le petit rond subsiste et le reste des traitements est bien sûr inchangé.

Remarques.

  • La représentation traditionnelle demanderait à insérer une association DF entre CLIENT et RÉSERVER. 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.
  • Les agrégats sur association binaire sont soit inutiles (sur une DF), soit impossibles (sur une non-DF, ils reviennent à permettre à une même occurrence d'entité de renforcer plusieurs occurrences d'une entité faible sans discriminateur). Mocodo les interdit dans les deux cas.

CIF à unicité complète¶

La notion d'agrégation n'a pas très bonne presse dans les milieux autorisés. Ceux-ci lui préfèrent généralement celle (équivalente) de contrainte d'intégrité fonctionnelle à unicité complète. Pour rentrer dans leurs bonnes grâces (et désactiver du même coup la visualisation de l'enveloppe et du petit rond), il suffit d'expliciter la contrainte correspondante dans le MCD précédent. Mocodo peut le faire pour vous :

In [41]:
%mocodo -i sandbox -t create:cifs arrange --seed=12 --colors ocean
No description has been provided for this image

sandbox.mcd
%%mocodo --seed=12 --colors ocean
Date: Date
Réserver, /1N Client, 1N Chambre, 0N Date: Durée
Chambre: Num. chambre, Prix

-INVISIBLE_1, XX Client, XX Client
Client: Id. client
:

(CIF) ..Réserver, ->Client, --Chambre, --Date: INVISIBLE_1, INVISIBLE_1

Remarquez que la visibilité de la CIF est assurée par le positionnement de celle-ci sur une boîte invisible introduite à cet effet : si vous rectifiez ce positionnement, vous pouvez bien sûr supprimer cette boîte.

Vous avez également le droit d'alléger la visualisation des CIFs complètes en transformant les traits pleins "--" des entités émettrices en traits invisibles "". Là encore, Mocodo peut le faire pour vous :

In [42]:
%mocodo -i sandbox -t create:cifs=light arrange --seed=12 --colors ocean
No description has been provided for this image

sandbox.mcd
%%mocodo --seed=12 --colors ocean
Date: Date
Réserver, /1N Client, 1N Chambre, 0N Date: Durée
Chambre: Num. chambre, Prix

-INVISIBLE_1, XX Client, XX Client
Client: Id. client
:

(CIF) ..Réserver, ->Client, Chambre, Date: INVISIBLE_1, INVISIBLE_1

Limitation. Au niveau fonctionnel, c'est toujours la barre oblique qui conditionne le traitement des CIF. Par conséquent, les CIF à unicité incomplète ne sont prises en charge qu'au niveau visuel.

Identifiants explicites dans les associations¶

Mocodo 4.1.1 relaxe par défaut (sauf dans la version en ligne) la contrainte de Merise restreignant aux entités la présence d'identifiants. Si vous l'osez, vous pouvez donc obtenir le même schéma relationnel avec le MCD « allégé » suivant :

In [43]:
%%mocodo -t
Client: Id. client
Réserver, 1N Client, 0N Chambre: _Date, Durée
Chambre: Num. chambre, Prix
No description has been provided for this image
  • Chambre (Num. chambre, Prix)
  • Réserver (Id. client, #Num. chambre, Date, Durée)

L'introduction de cette possibilité, surtout destinée à simplifier le plongement des MCD touffus, est discutée ici.

Conversion d'un MCD¶

Passage au relationnel¶

Il 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.

Pour construire 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 :
  4. 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 ;
  5. 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).

Pour construire la représentation externe, Mocodo formate la représentation interne à l'aide d'un gabarit. Près d'une centaine de gabarits sont fournis, qui permettent de produire quatre grandes catégories de résultats :

  1. le schéma relationnel dans toutes les combinaisons de formats (HTML, Markdown, texte brut, LATEX) et d'options (avec ou sans explications, avec ou sans boilerplate, avec ou sans visualisation des contraintes d'unicité et d'optionalité) ;
  2. le diagramme relationnel au format Mocodo, avec ou sans visualisation des contraintes d'unicité et d'optionalité, ou dans des formats externes, comme DBML ou D2.
  3. le DDL en SQL ANSI et dans les principaux dialectes (Microsoft SQL Server, MySQL, Oracle DB, PostgreSQL, SQLite), avec ou sans boilerplate de création de la base ;
  4. le graphe des dépendances.

Niveau logique¶

Schéma relationnel¶

La transformation -t mld opère la conversion d'un MCD (modèle conceptuel de données) en un MLD (modèle logique de données), autrement appelé schéma relationnel :

In [44]:
%mocodo -i ccp -t mld

ccp_mld.md
  • Client (Réf. client, Nom, Prénom, Adresse)
  • Commande (Num. commande, Date, Montant, #Réf. client)
  • Inclure (#Num. commande, #Réf. produit, Quantité)
  • Produit (Réf. produit, Libellé, Prix unitaire)

Sous Jupyter Notebook, comme pour toutes les opérations de conversion, le tracé du MCD est omis par défaut. Dans le cas très fréquent où l'on a besoin de visualiser simultanément le MCD et le MLD, on peut invoquer l'option -t sans arguments (ou encore --mld) :

In [45]:
%mocodo -i ccp -t
No description has been provided for this image
  • Client (Réf. client, Nom, Prénom, Adresse)
  • Commande (Num. commande, Date, Montant, #Réf. client)
  • Inclure (#Num. commande, #Réf. produit, Quantité)
  • Produit (Réf. produit, Libellé, Prix unitaire)

Diagramme relationnel¶

La plupart des SGBD offrent une représentation hybride (graphique / texte) de la base sous la forme de tables liées par des flèches. Nous l'appelons diagramme relationnel. Sous Mocodo :

In [46]:
%mocodo -i ccp --colors mondrian -t diagram

ccp_mld.svg
No description has been provided for this image

Le nom du fichier généré avant rendu graphique se termine par _mld.mcd. L'extension .mcd signifie que Mocodo peut le prendre comme texte-source (bien que ce ne soit pas un schéma conceptuel). Examinons son contenu :

In [47]:
display.Code("ccp_mld.mcd", language="text")
Out[47]:
%%mocodo
:
Client: Réf. client, Nom, Prénom, Adresse
:
Commande: Num. commande, Date, Montant, #Réf. client > Client > Réf. client
:
Inclure: #Num. commande > Commande > Num. commande, _#Réf. produit > Produit > Réf. produit, Quantité
:
Produit: Réf. produit, Libellé, Prix unitaire
:

La syntaxe d'un MLD est effectivement la même que celle d'un MCD, à ceci près que les associations sont remplacées par des liens allant de l'attribut a1 de l'entité E1 à l'attribut a2 de l'entité E2, et notés : E1: ... a1 > E2 > a2.

Les relations sont placées dans le même ordre que les boîtes du MCD d'origine. Vous devrez quelquefois les réarranger (automatiquement ou manuellement) pour obtenir un résultat plus esthétique. Notez que des boîtes invisibles ont été automatiquement insérées une colonne sur deux afin de laisser de la place aux flèches.

Limitation. Les clés étrangères composites sont actuellement représentées comme si elles étaient séparées (autant de flèches que de parties).

Nouveautés de la version 4.0.

  • Ce qui se notait E1: ... a1->E2->a2 se note maintenant E1: ... a1 > E2 > a2.
  • Sous Jupyter Notebook, un seule étape suffit pour visualiser le diagramme relationnel.
  • Le nom du fichier intermédiaire se termine par _mld.mcd au lieu de .mld. L'ancienne extension est abandonnée.

Niveau physique : DDL¶

SQL¶

La principale raison de vivre d'un MCD est de se métamorphoser in fine en une chatoyante base de données relationnelles. Cela se fait au moyen d'un sous-ensemble du langage SQL appelé DDL (Data Definition Language). Sous Mocodo :

In [48]:
%mocodo -i ccp -t sql

ccp_ddl.sql
CREATE TABLE Client (
  PRIMARY KEY (Ref_client),
  Ref_client VARCHAR(8) NOT NULL,
  Nom        VARCHAR(255),
  Prenom     VARCHAR(255),
  Adresse    VARCHAR(255)
);

CREATE TABLE Commande (
  PRIMARY KEY (Num_commande),
  Num_commande VARCHAR(8) NOT NULL,
  Date         DATE,
  Montant      DECIMAL(10,2),
  Ref_client   VARCHAR(8) NOT NULL
);

CREATE TABLE Inclure (
  PRIMARY KEY (Num_commande, Ref_produit),
  Num_commande VARCHAR(8) NOT NULL,
  Ref_produit  VARCHAR(8) NOT NULL,
  Quantite     INTEGER
);

CREATE TABLE Produit (
  PRIMARY KEY (Ref_produit),
  Ref_produit   VARCHAR(8) NOT NULL,
  Libelle       VARCHAR(50),
  Prix_unitaire DECIMAL(10,2)
);

ALTER TABLE Commande ADD FOREIGN KEY (Ref_client) REFERENCES Client (Ref_client);

ALTER TABLE Inclure ADD FOREIGN KEY (Ref_produit) REFERENCES Produit (Ref_produit);
ALTER TABLE Inclure ADD FOREIGN KEY (Num_commande) REFERENCES Commande (Num_commande);

Notez le NOT NULL des clés primaires. Il s'agit d'une redondance, mais aussi d'une bonne pratique. Non seulement parce qu'explicit is better than implicit : elle peut se révéler utile, par exemple pour désactiver les contraintes de clé primaire pendant une maintenance tout en continuant à interdire le remplissage avec des NULL. Si cela vous gêne, nous montrons en annexe comment l'éliminer.

Principales nouveautés de la version 4.0.

  • Génération automatique des contraintes UNIQUE, NOT NULL et NULL appropriées.
  • Les libellés sont convertis en ASCII, et toute suite de caractères qui ne sont ni des lettres, ni des chiffres, ni des tirets bas sont remplacés par un unique tiret bas. Cela simplifie la référence aux tables et aux champs, et évite de noyer le DDL sous un essaim de délimiteurs (qui plus est spécifiques à chaque dialecte). Ainsi, « Réf. client » se trouvera transformé en Ref_client.
  • Vos choix de casse (minuscules, MAJUSCULES, snake_case, camelCase, PascalCase, etc.) sont respectés.

Inférence de type¶

Avec l'option de réécriture -t create:types Mocodo essaiera d'inférer des libellés des attributs tout type manquant. La langue définie avec l'option --language est prioritaire, mais l'anglais prend la relève en cas d'échec.

In [49]:
%%mocodo -t create:types --select rw
Customer: Customer ID, Last Name, First Name, Address
Make Order, 0N Customer, 11 Order
Order: Order Number, Date, Amount
INCLUDE, 1N Order, 0N Product: Quantity
Product: Product ID, Description, Unit Price

sandbox.mcd
%%mocodo --select rw
Customer: Customer ID [VARCHAR(8)], Last Name [VARCHAR(255)], First Name [VARCHAR(255)], Address [VARCHAR(30)]
Make Order, 0N Customer, 11 Order
Order: Order Number [VARCHAR(8)], Date [DATE], Amount [DECIMAL(10,2)]
INCLUDE, 1N Order, 0N Product: Quantity [INTEGER]
Product: Product ID [VARCHAR(8)], Description [TEXT], Unit Price [DECIMAL(10,2)]

Il va de soi que les types inférés devront être systématiquement contrôlés, et parfois corrigés ou complétés. Une discussion sur StackOverflow, Common MySQL fields and their appropriate data types, a servi de point de départ. La liste des types utilisée est celle de Wikipedia. Consultez les correspondances spécifiées dans mocodo/resources/default_datatypes_fr.tsv, etc. pour plus de détails, et n'hésitez pas à ouvrir le débat si vous avez des corrections ou des suggestions.

Si vous préférez tout typer à la main, vous pouvez au moins créer les « cases » à remplir :

In [50]:
%%mocodo -t create:types=[] --select rw
Customer: Customer ID, Last Name, First Name, Address
Make Order, 0N Customer, 11 Order
Order: Order Number, Date, Amount
INCLUDE, 1N Order, 0N Product: Quantity
Product: Product ID, Description, Unit Price

sandbox.mcd
%%mocodo --select rw
Customer: Customer ID [], Last Name [], First Name [], Address []
Make Order, 0N Customer, 11 Order
Order: Order Number [], Date [], Amount []
INCLUDE, 1N Order, 0N Product: Quantity []
Product: Product ID [], Description [], Unit Price []

Dialectes de SQL¶

L'argument sql peut être remplacé par un nom de dialecte parmi mysql, oracle, postgresql, sqlite et (nouveauté de la version 4) mssql. Quelques transformations seront alors appliquées au code-source généré. Du fait de l'uniformisation de la syntaxe apportée par la version 4, elles sont assez minimes.

Notez les points suivants :

  • Mocodo ne touche pas aux types spécifiés par l'utilisateur. Une traduction inter-dialectes automatique est envisageable dans le futur, mais c'est un problème qui n'a en réalité aucune solution satisfaisante.
  • Mocodo protège les noms de tables ou de colonnes qui se trouveraient faire partie des mots réservés par le dialecte-cible. Par exemple, ci-dessous, les noms USER et MEMBER sont réservés en MySQL. Les listes viennent du site modern-sql.com de Markus Winand, et plus précisément de la page https://modern-sql.com/reserved-words-empirical-list.
  • Avec la sous-sous-option b, un boilerplate de création de la base est ajouté en préambule.
In [51]:
%%mocodo -t mysql:b
USER: username, mail, member

sandbox_ddl_mysql.sql
CREATE DATABASE IF NOT EXISTS `MCD`
  CHARACTER SET utf8mb4
  COLLATE utf8mb4_general_ci
;
USE `MCD`;

CREATE TABLE `USER` (
  PRIMARY KEY (username),
  username VARCHAR(42) NOT NULL,
  mail     VARCHAR(42),
  `member` VARCHAR(42)
);

Notes sur les règles de passage¶

Génération de contraintes d'optionalité et d'unicité¶

Avec la sous-sous-option c, Mocodo peut faire apparaître dès le niveau logique certaines contraintes du niveau physique. Les notations sont les suivantes :

Contrainte niveau logique niveau physique
non-optionalité attribut! NOT NULL
optionalité attribut? NULL
unicité attribut u1 u2... UNIQUE

Par exemple, ci-dessous, la clé étrangère #Réf_client est maintenant marquée comme non optionnelle :

In [52]:
%mocodo -i ccp -t mld:c

ccp_mld.md
  • Client (Réf. client, Nom, Prénom, Adresse)
  • Commande (Num. commande, Date, Montant, #Réf. client!)
  • Inclure (#Num. commande, #Réf. produit, Quantité)
  • Produit (Réf. produit, Libellé, Prix unitaire)

La clé étrangère #id entreprise est marquée comme optionnelle :

In [53]:
%%mocodo --select all -t mld:c
Entreprise: id. entreprise, raison, activité, adresse
Envoyer, 0N Entreprise, 01 Participant
Participant: id. inscrit, nom, adresse
No description has been provided for this image

sandbox_mld.md
  • Entreprise (id. entreprise, raison, activité, adresse)
  • Participant (id. inscrit, nom, adresse, #id. entreprise?)

La clé étrangère #id employé est marquée comme unique :

In [54]:
%%mocodo --select all -t mld:c
EMPLOYÉ: id. employé, nom employé
DIRIGER, 11 DÉPARTEMENT, 01 EMPLOYÉ
DÉPARTEMENT: id. département, nom département
No description has been provided for this image

sandbox_mld.md
  • DÉPARTEMENT (id. département, nom département, #id. employé! u1)
  • EMPLOYÉ (id. employé, nom employé)

Ajout manuel de contraintes d'optionalité et d'unicité¶

Les contraintes NOT NULL ou NULL spécifiées dans les types peuvent également faire l'objet d'une visualisation au niveau relationnel :

In [55]:
%%mocodo -t mld:c
Personne: id. personne [VARCHAR(8)], nom [VARCHAR(255) NOT NULL], prénom [VARCHAR(255)], nom de jeune fille [VARCHAR(255) NULL]

sandbox_mld.md
  • Personne (id. personne, nom!, prénom, nom de jeune fille?)

Pour les contraintes d'unicité, qui peuvent s'appliquer à plusieurs groupes d'attributs potentiellement non disjoints, la notation est un peu plus complexe. Voici un exemple proposé par Fabien Duchateau :

In [56]:
%%mocodo --select all -t mld:c --shapes trebuchet # changement de police de caractères pour mieux distinguer les 1 des I
CLIENT: Réf. client, 1_Nom, 1_Prénom, Adresse, 2_Mail
No description has been provided for this image

sandbox_mld.md
  • CLIENT (Réf. client, Nom u1, Prénom u1, Adresse, Mail u2)

C'est l'occasion d'introduire quelques définitions :

  • On appelle identifiant candidat d'une entité tout sous-ensemble minimal d'attributs dont chaque occurrence est unique.
  • Parmi ces sous-ensembles, l'un est élu identifiant (tout court), souligné, et appelé à devenir clé primaire lors du passage au relationnel.
  • Les candidats malheureux sont appelés identifiants alternatifs.

Ainsi, dans l'exemple précédent, l'ensemble des identifiants candidats de CLIENT est constitué de :

  • l'identifiant proprement dit Réf. client ;
  • l'identifiant alternatif (Nom, Prénom) (dont on supposera pour les besoins de la cause qu'il assure l'unicité) ;
  • l'identifiant alternatif Mail.

Par défaut, dès la première déclaration d'un identifiant alternatif, Mocodo fait apparaître une gouttière à gauche des attributs de toutes les entités. Y sont portés :

  • un symbole « ID » (resp. « id ») pour l'identifiant fort (resp. faible).
  • des chiffres de 1 à 9 correspondant aux numéros des identifiants alternatifs.

La notation de Mocodo permet de faire de n'importe quels sous-ensembles d'attributs des identifiants alternatifs. Ci-dessous, le premier identifiant alternatif est le triplet (bar, biz, quux), le second (biz, buz, quux) et le troisième (qux, quux) :

In [57]:
%%mocodo --select all -t markdown:c sql --shapes trebuchet
FOO: foo, 1_bar, 12_biz, 2_buz, 3_qux, 123_quux
No description has been provided for this image

sandbox_mld.md
  • FOO (foo, bar u1, biz u1 u2, buz u2, qux u3, quux u1 u2 u3)

sandbox_ddl.sql
CREATE TABLE FOO (
  PRIMARY KEY (foo),
  foo  VARCHAR(42) NOT NULL,
  bar  VARCHAR(42),
  biz  VARCHAR(42),
  buz  VARCHAR(42),
  qux  VARCHAR(42),
  quux VARCHAR(42),
  UNIQUE (bar, biz, quux),
  UNIQUE (biz, buz, quux),
  UNIQUE (qux, quux)
);

Examinons le cas exceptionnel où l'identifiant à souligner a un attribut commun avec un identifiant alternatif. Ce dernier devant être distinct et minimal, cela implique que l'identifiant est composite.

In [58]:
%%mocodo --shapes trebuchet
Entité 1_: 1_foo, _bar, 1_biz
Entité 2_: foo, 1_bar, 1_biz
Entité 3_: foo, 01_bar, 1_biz
No description has been provided for this image
  • Si l'attribut commun est en tête de liste (ici, foo, entité 1), rien ne change, on écrit 1_foo.
  • S'il n'est pas en tête de liste (ici, bar, entité 2), l'écriture 1_bar dénote déjà l'appartenance à un identifiant alternatif. Elle ne peut dénoter simultanément l'appartenance à l'identifiant à souligner.
  • C'est pourquoi on doit donc expliciter l'appartenance à l'identifiant à souligner qui, comme on l'a vu, est numéroté 0 (entité 3).

Un sous-cas demande encore réflexion : celui où le premier attribut ne fait pas partie de l'identifiant à souligner (entité 4). Si l'on veut alors que ce premier attribut appartienne à une clé alternative, il faut expliciter le 0 (entité 5).

In [59]:
%%mocodo --shapes trebuchet
Entité 40: _foo, _bar, biz
Entité 50: 01_foo, _bar, 1_biz
No description has been provided for this image

En résumé, on explicite le 0, soit pour empêcher le soulignement du premier attribut, soit pour forcer le soulignement d'un attribut suivant.

Cela devrait vous rappeler quelque chose… Remplacez 0 par _ dans la phrase précédente et vous retrouverez la règle que vous avez appris à connaître et à aimer : on explicite le _, soit pour empêcher le soulignement du premier attribut, soit pour forcer le soulignement d'un attribut suivant.

Gestion des entités faibles (identification relative)¶

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 :

In [60]:
%%mocodo -t
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
No description has been provided for this image
  • 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)

Le résultat apparaît plus clairement sur le diagramme relationnel :

In [61]:
%mocodo -i sandbox -t diagram --colors mondrian

sandbox_mld.svg
No description has been provided for this image

Une phase préliminaire de l'algorithme de passage au relationnel consiste à « renforcer » les entités faibles de façon à traiter uniquement des identifiants forts dans la suite. Cela permet la gestion des renforcements en cascade comme ci-dessus, ainsi que la détection des problèmes de renforcement cyclique :

In [62]:
%%mocodo
Pick, 0N Land, _11 Peer
Land: true, hold

Peer: foot, city
Zone, 1N Peer, _11 Land
No description has been provided for this image
In [63]:
%mocodo -i sandbox -t
Mocodo Err.17 - Cycle d'entités faibles dans "Land", "Peer".

Gestion de l'héritage¶

La bonne gestion d'un héritage est primordiale, tant du point de vue de la préservation du patrimoine, que de l'optimisation des ressources financières, de la minimisation des conflits familiaux et du respect des dernières volontés du défunt. Je blague.

Adaptons ici un exemple d'un cours de Stéphane Crozat. Nous reprenons sa terminologie et donnons en parallèle celle introduite par Martin Fowler dans Patterns of Enterprise Application Architecture, Addison-Wesley (2003).

Ci-dessous, l'héritage est considéré comme total (tout document est soit un ouvrage, soit une thèse, soit les deux). Crozat passe en revue trois mécanismes possibles pour le passage au relationnel.


L'héritage par référence (en anglais, Class Table Inheritance ou Table Per Type Inheritance) se note en Mocodo par une flèche simple allant vers les filles. Une référence à la table-mère sera ajoutée dans chaque table-fille comme clé étrangère. L'intérêt de cette solution est en raison directe du nombre d'attributs non identifiants de l'entité-mère.

In [64]:
%%mocodo --select all -t mld:c
DOCUMENT: cote, titre, auteur
    
OUVRAGE: éditeur
/T\ DOCUMENT -> OUVRAGE, THÈSE
THÈSE: discipline, université
No description has been provided for this image

sandbox_mld.md
  • DOCUMENT (cote, titre, auteur)
  • OUVRAGE (#cote, éditeur)
  • THÈSE (#cote, discipline, université)

L'héritage par absorption dans les tables-filles (en anglais, Concrete Table Inheritance ou Table Per Concrete Inheritance) se note en doublant la flèche :

  1. les attributs de la table-mère sont reproduits dans chacune des filles. Pour chaque document qui est à la fois un ouvrage et une thèse, il y aura donc duplication des triplets (cote, titre, auteur).
  2. la table-mère disparaît. Pour éviter de perdre les informations sur les documents qui ne seraient ni des ouvrages, ni des thèses, Mocodo lève une erreur si l'héritage n'est pas total (T ou XT).
In [65]:
%%mocodo --select all -t mld:c
DOCUMENT: cote, titre, auteur
    
OUVRAGE: éditeur
/T\ DOCUMENT => OUVRAGE, THÈSE
THÈSE: discipline, université
No description has been provided for this image

sandbox_mld.md
  • OUVRAGE (cote, titre, auteur, éditeur)
  • THÈSE (cote, titre, auteur, discipline, université)

L'héritage par absorption dans la table-mère (en anglais, Single Table Inheritance ou Table Per Hierarchy Inheritance) se note par une flèche simple allant vers la mère. Les tables-filles disparaissent, et leurs attributs migrent dans la mère avec une contrainte d'optionalité (point d'interrogation en relationnel, NULL en SQL).

In [66]:
%%mocodo --select all -t mld:c sql
DOCUMENT: cote, titre, auteur

OUVRAGE: éditeur
/X\ DOCUMENT <- OUVRAGE, THÈSE: discriminateur [ENUM ('OUVRAGE', 'THÈSE')]
THÈSE: discipline, université
No description has been provided for this image

sandbox_mld.md
  • DOCUMENT (cote, titre, auteur, discriminateur?, éditeur?, discipline?, université?)

sandbox_ddl.sql
CREATE TABLE DOCUMENT (
  PRIMARY KEY (cote),
  cote           VARCHAR(42) NOT NULL,
  titre          VARCHAR(42),
  auteur         VARCHAR(42),
  discriminateur ENUM ('OUVRAGE', 'THÈSE') NULL,
  editeur        VARCHAR(42) NULL,
  discipline     VARCHAR(42) NULL,
  universite     VARCHAR(42) NULL
);

Ci-dessus, nous avons donné comme « attribut » au triangle d'héritage un « discriminateur » de type ENUM. Cela ajoute à la table un champ optionnel ou non (selon que l'héritage est partiel ou total) permettant de déterminer à quel type concret d'une occurrence on a affaire.

C'est par défaut un UNSIGNED INT, qui pourra prendre les valeurs :

  • 1 = OUVRAGE, 2 = THÈSE, pour l'héritage exclusif ;
  • 1 (20) = OUVRAGE, 2 (21) = THÈSE, 3 (20|21) = OUVRAGE + THÈSE, pour l'héritage non exclusif.

Alternativement à l'emploi d'un discriminateur, Mocodo peut ajouter un drapeau booléen par table-fille. Cela se note en doublant la flèche :

In [67]:
%%mocodo --select all -t mld:c sql
DOCUMENT: cote, titre, auteur

OUVRAGE: éditeur
/T\ DOCUMENT <= OUVRAGE, THÈSE
THÈSE: discipline, université
No description has been provided for this image

sandbox_mld.md
  • DOCUMENT (cote, titre, auteur, est ouvrage!, éditeur?, est these!, discipline?, université?)

sandbox_ddl.sql
CREATE TABLE DOCUMENT (
  PRIMARY KEY (cote),
  cote        VARCHAR(42) NOT NULL,
  titre       VARCHAR(42),
  auteur      VARCHAR(42),
  est_ouvrage BOOLEAN NOT NULL,
  editeur     VARCHAR(42) NULL,
  est_these   BOOLEAN NOT NULL,
  discipline  VARCHAR(42) NULL,
  universite  VARCHAR(42) NULL
);

Gestion de l'agrégation¶

Un agrégat simple autour d'une association dont toutes les cardinalités maximales sont N se traduit en relationnel comme la même association non agrégée, mais avec une clé primaire réduite :

In [68]:
%%mocodo --select all -t mld:c
DATE: date
RÉSERVER, /1N CLIENT, 1N CHAMBRE, 0N DATE: durée
CHAMBRE: num. chambre, prix

CLIENT: id. client, nom client
No description has been provided for this image

sandbox_mld.md
  • CHAMBRE (num. chambre, prix)
  • CLIENT (id. client, nom client)
  • RÉSERVER (#num. chambre, date, #id. client!, durée)

Un agrégat simple autour d'une association dont la cardinalité maximale « de sortie » est 1 se traduit en relationnel comme la même association non agrégée, mais avec une contrainte d'unicité sur la clé étrangère. Ci-dessous, au lieu d'avoir simplement num résa ⟹ (num voilier, num semaine), on a donc en plus (num voilier, num semaine) ⟹ num résa :

In [69]:
%%mocodo --select all -t mld:c
Voilier: num voilier, longueur
Offrir, /11 Réservation, 0N Voilier, 0N Semaine: tarif
Semaine: num semaine, date début

Réservation: num résa, arrhes, date résa
No description has been provided for this image

sandbox_mld.md
  • Réservation (num résa, arrhes, date résa, #num voilier! u1, #num semaine! u1, tarif)
  • Semaine (num semaine, date début)
  • Voilier (num voilier, longueur)

Le cas des agrégats multiples, plus rare, est étudié en annexe.

Ajustement des règles de passage¶

Supprimer ou maintenir une table facultative¶

Le passage au relationnel supprime automatiquement les tables réduites à une clé primaire, pourvu qu'aucun composant de celle-ci ne soit clé étrangère. Si l'on souhaite maintenir certaines de ces tables, on préfixe d'un + l'entité concernée. Ainsi, ci-dessous, Date est supprimée, mais pas Thème.

In [70]:
%%mocodo --select mld mcd -t mld:e
Animateur: num. animateur, nom animateur
Intervenir, 1N Animateur, 1N Formation, 1N Date: nb heures
Formation: id. formation, durée
Aborder, 1N Thème, 1N Formation
+Thème: thème

Date: date
:

sandbox_mld.md
  • Aborder (#thème, #id. formation)

    • Le champ thème fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité Thème.
    • Le champ id. formation fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité Formation.
  • Animateur (num. animateur, nom animateur)

    • Le champ num. animateur constitue la clé primaire de la table. C'était déjà un identifiant de l'entité Animateur.
    • Le champ nom animateur était déjà un simple attribut de l'entité Animateur.
  • Formation (id. formation, durée)

    • Le champ id. formation constitue la clé primaire de la table. C'était déjà un identifiant de l'entité Formation.
    • Le champ durée était déjà un simple attribut de l'entité Formation.
  • Intervenir (#num. animateur, #id. formation, date, nb heures)

    • Le champ num. animateur fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité Animateur.
    • Le champ id. formation fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité Formation.
    • Le champ date fait partie de la clé primaire de la table. Sa table d'origine (Date) ayant été supprimée, il n'est pas considéré comme clé étrangère.
    • Le champ nb heures était déjà un simple attribut de l'association Intervenir.
  • Thème (thème)

    • Le champ thème constitue la clé primaire de la table. C'était déjà un identifiant de l'entité Thème.

NB. La table Date a été supprimée car elle était réduite à la clé primaire de son entité d'origine. Pour conserver de telles tables, préfixez d'un « + » la définition des entités d'origine.

No description has been provided for this image

Notez l'explication de la suppression (en NB) et celle de la perte du caractère étranger de l'attribut date (dans la table Intervenir). Pour une discussion sur cette problématique, cf. issue #66.

Forcer une table pour éviter un champ optionnel¶

Une association de dépendance fonctionnelle ne donne normalement pas lieu à une création de table. Pour reprendre un exemple vu plus haut :

In [71]:
%%mocodo --select all -t mld:c
Entreprise: id. entreprise, raison, activité, adresse
Envoyer, 0N Entreprise, 01 Participant
Participant: id. inscrit, nom, adresse
No description has been provided for this image

sandbox_mld.md
  • Entreprise (id. entreprise, raison, activité, adresse)
  • Participant (id. inscrit, nom, adresse, #id. entreprise?)

Dans le cas où les particuliers sont beaucoup plus nombreux que les employés d'entreprise, la clé étrangère #id. entreprise est presque toujours à NULL. C'est une perte d'espace de stockage. On peut entourer l'association de crochets droits préfixer d'un + (à partir de la version 4) l'association pour forcer sa conversion en table. Mocodo produit alors une visualisation intermédiaire entre entité et association :

In [72]:
%%mocodo --select all -t mld:c --colors mondrian
Entreprise: id. entreprise, raison, activité, adresse
+Envoyer, 0N Entreprise, 01 Participant
Participant: id. inscrit, nom, adresse
No description has been provided for this image

sandbox_mld.md
  • Entreprise (id. entreprise, raison, activité, adresse)
  • Envoyer (#id. inscrit, #id. entreprise!)
  • Participant (id. inscrit, nom, adresse)

Cela permet du même coup d'éviter un champ optionnel, dont la gestion peut être délicate (notamment sous Microsoft SQL Server qui, au mépris du standard SQL, ne semble pas convaincu qu'une colonne UNIQUE peut contenir plus d'un NULL !).

Préciser le rôle d'une clé étrangère¶

Ce MCD modélise la soutenance de stage des étudiants, ainsi que la visite d'amitié et de contrôle dont les honore leur enseignant responsable :

In [73]:
%%mocodo -t
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
No description has been provided for this image
  • Enseignant (num. enseignant, nom, coordonnées)
  • Étudiant (num. étudiant, nom, coordonnées, date 1, note stage, date 2, #num. enseignant)

Force est de constater que la table Étudiant laisse quelque peu à désirer du point de vue sémantique :

  • on ne sait pas à quoi correspondent les attributs date 1 et date 2 : ils ne peuvent en tout cas certainement pas être laissés en l'état ;
  • ensuite, on pourrait avoir envie d'expliciter la raison pour laquelle un enseignant apparaît parmi les attributs d'un étudiant.

Ces précisions peuvent être apportées en insérant, entre la cardinalité et l'entité des pattes appropriées, une note entre crochets, appelée rôle. Ces rôles seront utilisés pour compléter le nom des clés étrangères correspondantes. Cela permet de réintroduire la sémantique perdue lors de la disparition des associations de dépendance fonctionnelle par lesquelles elle ont migré :

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

Date: date
Répondre de, 0N [+ visite resp] Date, 11 Étudiant, 0N [-num. ens. resp.] Enseignant
Enseignant: num. enseignant, nom, coordonnées

sandbox_mld.md
  • Enseignant (num. enseignant, nom, coordonnées)
  • Étudiant (num. étudiant, nom, coordonnées, date soutenance, note stage, date visite resp, #num. ens. resp.)

La composition du rôle est entièrement paramétrable :

  • date soutenance : par défaut, le rôle est concaténé à la clé, avec un séparateur dépendant du gabarit (espace par défaut, tiret bas pour SQL).
  • date visite resp. : + en préfixe supprime le séparateur.
  • num. ens. resp. : - en préfixe supprime le nom de la clé et le remplace par le rôle.

Pour ne pas surcharger le dessin, le rôle n'est pas affiché à côté du lien, mais il apparaît au survol de la cardinalité.

Correction de la version 4.0. Dans une association réflexive hiérarchique, c'est désormais le rôle porté par la patte *N qui sert à rétablir la sémantique. Auparavant c'était l'inverse, en contradiction avec le traitement des associations binaires et n-aires : si vous avez utilisé des rôles dans une association réflexive avant la version 4.0.0, vous devez donc les permutez pour que Mocodo les traite correctement. Reprenons la filiation patrilinéaire :

In [75]:
%%mocodo -t
HOMME: num. SS, nom, prénom
ENGENDRER, 0N [père] HOMME, 01 [fils] HOMME
No description has been provided for this image
  • HOMME (num. SS, nom, prénom, #num. SS père)

Orienter la migration dans les DF à double sens¶

Lorsque toutes les cardinalités d'une dépendance fonctionnelle sont 11 (ou toutes 01), le sens de migration est spécifié à coût zéro en référençant l'entité réceptrice en tête de la liste des entités énumérées dans la clause de définition de l'association :

In [76]:
%%mocodo -t mld diagram sql --colors mondrian
USER: user id [VARCHAR(8)], name [VARCHAR(100)], pseudo [VARCHAR(100)]
DF, 11 USER, 11 AUTHENTICATION
AUTHENTICATION: email [VARCHAR(255)], password hash [BINARY(64)], salt [BINARY(16)]

sandbox_mld.md
  • AUTHENTICATION (email, password hash, salt)
  • USER (user id, name, pseudo, #email)

sandbox_mld.svg
No description has been provided for this image

sandbox_ddl.sql
CREATE TABLE AUTHENTICATION (
  PRIMARY KEY (email),
  email         VARCHAR(255) NOT NULL,
  password_hash BINARY(64),
  salt          BINARY(16)
);

CREATE TABLE USER (
  PRIMARY KEY (user_id),
  user_id VARCHAR(8) NOT NULL,
  name    VARCHAR(100),
  pseudo  VARCHAR(100),
  email   VARCHAR(255) NOT NULL,
  UNIQUE (email)
);

ALTER TABLE USER ADD FOREIGN KEY (email) REFERENCES AUTHENTICATION (email);

Dans la version avec identification relative, c'est l'entité faible qui doit être placée en tête :

In [77]:
%%mocodo -t mld diagram sql --colors mondrian
USER: user id [VARCHAR(8)], name [VARCHAR(100)], pseudo [VARCHAR(100)]
DF, _11 AUTHENTICATION, 11 USER
AUTHENTICATION: email [VARCHAR(255)], password hash [BINARY(64)], salt [BINARY(16)]

sandbox_mld.md
  • AUTHENTICATION (#user id, email, password hash, salt)
  • USER (user id, name, pseudo)

sandbox_mld.svg
No description has been provided for this image

sandbox_ddl.sql
CREATE TABLE AUTHENTICATION (
  PRIMARY KEY (user_id, email),
  user_id       VARCHAR(8) NOT NULL,
  email         VARCHAR(255) NOT NULL,
  password_hash BINARY(64),
  salt          BINARY(16)
);

CREATE TABLE USER (
  PRIMARY KEY (user_id),
  user_id VARCHAR(8) NOT NULL,
  name    VARCHAR(100),
  pseudo  VARCHAR(100)
);

ALTER TABLE AUTHENTICATION ADD FOREIGN KEY (user_id) REFERENCES USER (user_id);

Les traitements alternatifs (fusion en une seule table ou migration dans les deux sens) ne sont pas pris en charge par Mocodo. La dernière pratique ressortit à la phase d'optimisation et de dénormalisation de la base, qui est en dehors de sa juridiction. La seule chose que vous pouvez faire, à des fins d'illustration, est de reprendre le MLD généré pour y ajouter à la main la migration inverse. Notez cependant que les schémas logique et physique générés seront alors dépourvus de toute clé étrangère (et nécessiteront donc également d'être retouchés à la main).

In [78]:
%%mocodo -t mld sql --colors mondrian --select all
:
USER: user id [VARCHAR(8)], name [VARCHAR(100)], pseudo [VARCHAR(100)], #email > AUTHENTICATION > email
:
AUTHENTICATION: email [VARCHAR(255)], password hash [BINARY(64)], salt [BINARY(16)], #user id > USER > user id
:
No description has been provided for this image

sandbox_mld.md
  • AUTHENTICATION (email, password hash, salt, user id)
  • USER (user id, name, pseudo, email)

sandbox_ddl.sql
CREATE TABLE AUTHENTICATION (
  PRIMARY KEY (email),
  email         VARCHAR(255) NOT NULL,
  password_hash BINARY(64),
  salt          BINARY(16),
  user_id       VARCHAR(42)
);

CREATE TABLE USER (
  PRIMARY KEY (user_id),
  user_id VARCHAR(8) NOT NULL,
  name    VARCHAR(100),
  pseudo  VARCHAR(100),
  email   VARCHAR(42)
);

Autres sorties relationnelles¶

Graphe des dépendances¶

La table A dépend de la table B lorsque A possède une clé étrangère qui est clé primaire de B. Cette notion est utile dans le cas où l'on doit importer une base de données à partir d'un ensemble de fichiers CSV (ou autres). Si l'on veut éviter de perdre le bénéfice du contrôles de clés étrangères (en faisant, p. ex. sous MySQL, SET FOREIGN_KEY_CHECKS = 0), il conviendra de lire ces fichiers dans un ordre topologique quelconque. Mocodo peut générer un graphe des dépendances qui met cet ordre en évidence :

In [79]:
%mocodo -i ccp -t dependencies --defer

ccp_dependencies.svg
No description has been provided for this image

Même si un tel graphe n'est pas forcément sans circuits, remplir les tables dans le sens de lecture des langues latines minimisera le recours à la désactivation des contraintes de clés étrangères.

Diagramme relationnel / DDL BDML¶

D'après son site officiel :

DBML (Database Markup Language) est un DSL (langage dédié) open-source conçu pour définir et documenter les schémas et structures de base de données. Il vise la simplicité, la cohérence et la lisibilité.

Mocodo parle maintenant DBML :

In [80]:
%mocodo -i ccp -t dbml --title CCP

ccp_ddl.dbml
dbml
Table "Client" {
  "Réf. client" VARCHAR(8) [pk, NOT NULL]
  "Nom"         VARCHAR(255)
  "Prénom"      VARCHAR(255)
  "Adresse"     VARCHAR(255)
}

Table "Commande" {
  "Num. commande" VARCHAR(8) [pk, NOT NULL]
  "Date"          DATE
  "Montant"       DECIMAL(10,2)
  "Réf. client"   VARCHAR(8) [NOT NULL]
}

Table "Inclure" {
  "Num. commande" VARCHAR(8) [NOT NULL]
  "Réf. produit"  VARCHAR(8) [NOT NULL]
  "Quantité"      INTEGER
  Indexes {
    ("Num. commande", "Réf. produit") [pk]
  }
}

Table "Produit" {
  "Réf. produit"  VARCHAR(8) [pk, NOT NULL]
  "Libellé"       VARCHAR(50)
  "Prix unitaire" DECIMAL(10,2)
}

Ref:"Commande"."Réf. client" > "Client"."Réf. client"
Ref:"Inclure"."Num. commande" > "Commande"."Num. commande"
Ref:"Inclure"."Réf. produit" > "Produit"."Réf. produit"

À notre connaissance, il n'existe pas actuellement d'API publique de rendu des diagrammes DBML. Pour les visualiser, copiez-collez la sortie sur Dbdiagram.io, ou installez un plugin VS-Code :

In [81]:
display.SVG("../examples/dbml.svg")
Out[81]:
No description has been provided for this image

Diagramme relationnel D2¶

D2 est un langage de description de diagrammes de différents types. La prise en charge des diagrammes relationnels est minimale, mais le projet est jeune (actuellement en version 0.6.1, open source depuis novembre 2022). Son point fort est TALA, son algorithme de plongement propriétaire, que vous pouvez tester ici. Celui-ci requérant une licence payante, si vous déférez le rendu, c'est le plongement par défaut (Dagre, celui de Mermaid) qui sera utilisé.

In [82]:
%mocodo -i ccp -t d2

ccp_ddl.d2
d2
"Client": { shape: sql_table
  "Réf. client": VARCHAR(8) {constraint: PK}
  "Nom":         VARCHAR(255) 
  "Prénom":      VARCHAR(255) 
  "Adresse":     VARCHAR(255) 
}

"Commande": { shape: sql_table
  "Num. commande": VARCHAR(8) {constraint: PK}
  "Date":          DATE 
  "Montant":       DECIMAL(10,2) 
  "Réf. client":   VARCHAR(8) {constraint: [FK; NOT NULL]}
}

"Inclure": { shape: sql_table
  "Num. commande": VARCHAR(8) {constraint: [PK; FK]}
  "Réf. produit":  VARCHAR(8) {constraint: [PK; FK]}
  "Quantité":      INTEGER 
}

"Produit": { shape: sql_table
  "Réf. produit":  VARCHAR(8) {constraint: PK}
  "Libellé":       VARCHAR(50) 
  "Prix unitaire": DECIMAL(10,2) 
}

"Commande"."Réf. client" -> "Client"."Réf. client"
"Inclure"."Num. commande" -> "Commande"."Num. commande"
"Inclure"."Réf. produit" -> "Produit"."Réf. produit"

In [83]:
%mocodo -i ccp -t d2 --defer

ccp_ddl.svg
No description has been provided for this image

Autres conversions¶

Diagramme de classes UML¶

À tout seigneur tout honneur, Mocodo peut traduire votre MCD en UML. Ce formalisme graphique n'a, curieusement, pas de DSL textuel officiel. Nous nous rabattons donc sur le standard de fait, PlantUML :

In [84]:
%mocodo -i ccp --title CCP -t uml:plantuml=- # '-' supprime un préambule par défaut qui ne nous intéresse pas ici

ccp_uml.puml
puml
@startuml "CCP"

!define Table(x) class "x" << (T,#FFFFFF) >>
!define pk(x) <b>x</b>

Table("Client") {
    {field} + pk(Réf. client) VARCHAR(8)
    {field} + Nom         VARCHAR(255)
    {field} + Prénom      VARCHAR(255)
    {field} + Adresse     VARCHAR(255)
}

"Client" "1" --- "*" "Commande": "Passer"

Table("Commande") {
    {field} + pk(Num. commande) VARCHAR(8)
    {field} + Date          DATE
    {field} + Montant       DECIMAL(10,2)
}

"Commande" "*" --- "1..*" "Produit": "Inclure"
("Commande", "Produit") .. "Inclure"
Table("Inclure") {
    {field} + Quantité INTEGER
}

Table("Produit") {
    {field} + pk(Réf. produit)  VARCHAR(8)
    {field} + Libellé       VARCHAR(50)
    {field} + Prix unitaire DECIMAL(10,2)
}

@enduml

In [85]:
%mocodo -i ccp -t uml --defer --colors brewer+5

ccp_uml.svg
No description has been provided for this image

ERD avec la convention Look across¶

Nouveauté de la version 4.0. Force est de reconnaître que de nos jours, les MCD à la sauce Merise ne sont plus goûtés que par une poignée d'irréductibles Gaulois (et contractuellement leurs étudiants). Dans le cadre de son projet secret de domination planétaire, Mocodo commence à faire du pied à des notations mieux comprises du reste de l'univers.

Notation de Chen¶

Un MCD peut être converti en un ERD (Entity-Relationship Diagram) dans la notation de Chen, sans ses attributs ou avec :

In [86]:
%mocodo -i ccp -t chen --defer --colors ocean

ccp_erd_chen.svg
No description has been provided for this image
In [87]:
%mocodo -i ccp -t chen:attrs --defer --colors ocean

ccp_erd_chen.svg
No description has been provided for this image

Notation crow's foot¶

Dans le même ordre d'idées, Mocodo peut générer des ERD dans l'astucieuse notation introduite en 1976 par Gordon Everest. Par défaut, le format du fichier intermédiaire est là encore Graphviz :

In [88]:
%mocodo -i ccp -t crow --defer --colors brewer+3

ccp_erd_crow.svg
No description has been provided for this image

Il est également possible de demander une sortie au format Mermaid. Vous en avez un exemple dans l'introduction, nous ne le répétons pas ici. Le DSL de Mermaid est de plus haut niveau, non encombré d'informations de style. Cependant, le format Graphviz peut être préféré pour plusieurs raisons :

  • on peut lui appliquer une palette de couleurs de Mocodo (cf. ci-dessus) ;
  • il gère les accents ;
  • il admet la virgule dans les types (Mermaid demande actuellement à transformer DECIMAL(10,2) en DECIMAL(10-2)) ;
  • il peut produire de meilleurs plongements (notamment en jouant sur la valeur de l'option --seed) ;
  • ceux-ci peuvent-être rectifiés à la main (quoique péniblement).

Dictionnaire des données¶

Vous pouvez extraire sous forme de table diverses informations sur les attributs de votre MCD.

Un format possible est TSV. Dans ce cas, sous Jupyter Notebook, si la bibliothèque pandas est installée, elle sera rendue comme un dataframe :

In [89]:
%mocodo -i ccp -t data_dict:tsv

ccp_data_dict_3.tsv
  Entité ou association Libellé de l'attribut Type
0 Client Adresse VARCHAR(255)
1 Client Nom VARCHAR(255)
2 Client Prénom VARCHAR(255)
3 Client Réf. client VARCHAR(8)
4 Commande Date DATE
5 Commande Montant DECIMAL(10,2)
6 Commande Num. commande VARCHAR(8)
7 Inclure Quantité INTEGER
8 Produit Libellé VARCHAR(50)
9 Produit Prix unitaire DECIMAL(10,2)
10 Produit Réf. produit VARCHAR(8)

Le format par défaut est Markdown. Vous pouvez préciser en sous-sous-option tout ou partie des colonnes suivantes dans l'ordre où vous les souhaitez :

  • label: le libellé de l'attribut ;
  • type : son type ou un descriptif (auquel cas il conviendra de changer le nom de la colonne) ;
  • box : le nom de l'entité ou association où il se trouve.

Entourez ces noms de colonnes de balises Markdown pour les mettre en forme (pas d'incidence en TSV). Faites-les suivre de ="Nom de colonne personnalisé" pour éviter la valeur par défaut (dépendante de l'option language). Dans l'exemple ci-dessous, les sous-sous-options se décodent ainsi :

  • **box**="Entité ou association" : boîtes en colonne 1, en-tête personnalisé, cellules en gras ;
  • label : libellé des attributs en colonne 2 ;
  • `type`=`Type` : types en colonne 3, en-tête personnalisé et cellules dans une police non proportionnelle.
In [90]:
%mocodo -i ccp -t data_dict:**box**="Entité ou<br>association",label,`type`=`"Type de données"`

ccp_data_dict_3.md
Entité ou
association
Libellé de l'attribut Type de données
Client Adresse VARCHAR(255)
" Nom VARCHAR(255)
" Prénom VARCHAR(255)
" Réf. client VARCHAR(8)
Commande Date DATE
" Montant DECIMAL(10,2)
" Num. commande VARCHAR(8)
Inclure Quantité INTEGER
Produit Libellé VARCHAR(50)
" Prix unitaire DECIMAL(10,2)
" Réf. produit VARCHAR(8)

Aménités.

  • Au format Markdown, les répétitions de cellules de la première colonne sont remplacées par un guillemet itératif.
  • Le tableau est automatiquement trié selon sa première, puis éventuellement deuxième et troisième colonnes.
  • Si une seule colonne est demandée, la ligne d'en-tête n'est pas générée et, en Markdown, c'est une liste qui est produite.
In [91]:
%mocodo -i ccp -t data_dict:label

ccp_data_dict_1.md
  • Adresse
  • Date
  • Libellé
  • Montant
  • Nom
  • Num. commande
  • Prix unitaire
  • Prénom
  • Quantité
  • Réf. client
  • Réf. produit

Nouveautés de la version 4.0.

  • Sélection, ordre et nommage des colonnes, mise en forme Markdown, tri, guillemets itératifs.
  • Remplacement par un algorithme dédié du gabarit relationnel utilisé (abusivement) dans les versions antérieures.

URL de partage¶

Vous pouvez demander à encoder le texte-source de votre MCD dans un lien vers Mocodo online, qui le composera automatiquement dans la zone d'entrée :

In [92]:
%mocodo -i ccp -t share

ccp_url.url
https://www.mocodo.net/?mcd=eNptkMEKgkAQhu89xRwLJDQQwtuySgm5mEgX6bDlBgu6xrYLvZLP4Ys1ahZYt_m_Yeb_Z2glhTIBZF17W8N1UFCcSEb3JFtuV2cHWFN_ycb3e5bqrlV_OCm1eDzEjC9SjlA74DKgg4UDnge0qWuuSrGYigCYrTHFW85yhNwgCkkeoUgaZXgfNYxonJDD0nOdDTrF6lpZLXA_--wffFPdlFbipUeLc9J0LRQxy6NdlGG-qTm-4T7Kmf9BXkRV9XMT9t3xF_IJVknDpRY_gV4LRG5Z

Mocodo pour la pédagogie¶

Vue en extension¶

Un chiffre ou tiret bas à la fin du nom d'une boîte (entité ou association) est utilisé en interne pour distinguer cette boîte des autres, mais n'est pas affiché dans le diagramme conceptuel. Cela 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 [93]:
%%mocodo
ŒUVRE1: cote, titre, date de publication
:::
ŒUVRE2: 612.NAT.34, J'apprends à lire à mes souris blanches, mai 1975
:
  
DF, 1N ŒUVRE1, _11 EXEMPLAIRE1
::
DF, XX ŒUVRE2, XX EXEMPLAIRE2
DF, XX ŒUVRE2, XX EXEMPLAIRE3
DF, 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
No description has been provided for this image

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

Si l'on veut garder les cardinalités sans les afficher, on peut les préfixer d'un -. Le résultat de la conversion en relationnel peut alors être interprété comme l'ensemble des lignes des différentes tables.

In [94]:
%%mocodo -t
ŒUVRE: 612.NAT.34, J'apprends à lire à mes souris blanches, mai 1975
  
DF, -1N ŒUVRE, -_11 EXEMPLAIRE1
DF, -1N ŒUVRE, -_11 EXEMPLAIRE2
DF, -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
No description has been provided for this image
  • EXEMPLAIRE (#612.NAT.34, 1, bon état, 12/6/1975)
  • EXEMPLAIRE (#612.NAT.34, 2, bon état, 1/8/1977)
  • EXEMPLAIRE (#612.NAT.34, 3, reliure rongée, 3/4/2005)
  • ŒUVRE (612.NAT.34, J'apprends à lire à mes souris blanches, mai 1975)

MCD interactif¶

Afficher des explications au survol¶

Les débutants ont souvent des doutes sur la sémantique de telle ou telle cardinalité. Cette information peut être incluse dans le texte-source en annotant les pattes correspondantes. Survolez les cardinalités du MCD ci-dessous pour faire apparaître leur description.

In [95]:
%%mocodo
Produit: réf. produit, libellé, prix unitaire
Inclure, 1N [Une commande inclut au moins un produit.] Commande, 0N [Un produit peut être commandé un nombre quelconque de fois.] Produit: quantité
Commande: num. commande, date, montant
DF, 0N [Un client peut passer zéro (prospect) ou plusieurs commandes.] Client, 11 [Une commande est passée par un et un seul client.] Commande
Client: réf. client, nom, adresse
Parrainer, 01 [Un client peut avoir été parrainé ou non.] Client, 0N [Un client peut parrainer d'autres clients.] Client : date parrainage
No description has been provided for this image

Nouveauté de la version 4.3. Avec l'option -t prompt:cards, Mocodo compose un prompt à copier-coller sous ChatGPT (ou autre) pour compléter le MCD avec de telles descriptions. Ce prompt est trop long pour être reproduit ici : il consiste en une présentation de la syntaxe de Mocodo, des instructions sur le travail demandé, plusieurs exemples corrigés, et enfin le MCD à compléter. Voici par exemple les explications générées par DeepSeek pour le MCD de la page d'accueil de Mocodo online :

In [96]:
%%mocodo
AYANT-DROIT: nom ayant-droit, lien
DIRIGER, 0N [Un employé peut diriger zéro ou un projet.] EMPLOYÉ, 01 [Un projet est dirigé par au plus un employé.] PROJET
REQUÉRIR, 1N [Un projet requiert au moins une pièce.] PROJET, 0N [Une pièce peut être requise par plusieurs projets.] PIÈCE: qté requise
PIÈCE: réf. pièce, libellé pièce
COMPOSER, 0N [Une pièce peut être composée de plusieurs autres pièces.] PIÈCE, 0N [Une pièce peut entrer dans la composition de plusieurs autres pièces.] PIÈCE: quantité

DF, _11 [Un ayant-droit est associé à un et un seul employé.] AYANT-DROIT, 0N [Un employé peut avoir plusieurs ayants-droit.] EMPLOYÉ
EMPLOYÉ: matricule, nom employé
PROJET: num. projet, nom projet
FOURNIR, 1N [Un projet est fourni par au moins une société.] PROJET, 1N [Une pièce est fournie par au moins une société.] PIÈCE, 1N [Une société fournit au moins une pièce pour un projet.] SOCIÉTÉ: qté fournie

DÉPARTEMENT: num. département, nom département
EMPLOYER, 11 [Un employé appartient à un et un seul département.] EMPLOYÉ, 1N [Un département emploie au moins un employé.] DÉPARTEMENT
TRAVAILLER, 0N [Un employé peut travailler sur plusieurs projets.] EMPLOYÉ, 1N [Un projet implique au moins un employé.] PROJET
SOCIÉTÉ: num. société, raison sociale
CONTRÔLER, 0N< [Une société peut en contrôler une autre.] SOCIÉTÉ, 01 [Une société est contrôlée par au plus une autre société.] SOCIÉTÉ
No description has been provided for this image

Le résultat est en général plus qu'honorable, mais demande à être relu attentivement pour vérifier l'adhérence au MCD original, corriger d'éventuelles hallucinations ou apporter des précisions. Ci-dessus, en l'occurrence, une société peut en contrôler plusieurs autres (et non une autre).

Différence syntaxique entre rôles et explications. Remarquez que la syntaxe est la même que pour les rôles, qui sont en plus utilisés lors du passage au relationnel. Comment Mocodo fait-il la différence ? En appliquant les règles suivantes :

  • si la note de patte commence par + ou -, ou qu'elle ne contient aucun espace, c'est un rôle.
  • sinon, c'est une description de cardinalité.

Explication de contraintes. Le même principe s'applique aux contraintes (survolez le Ⓘ) :

In [97]:
%%mocodo
Projet: num. projet, nom projet
:
Fournir, 1N Projet, 1N Pièce, 1N Société: quantité
Société: num. société, raison sociale

Requérir, 1N Projet, 0N Pièce: quantité
:
Pièce: réf. pièce, libellé pièce

(I) [Toute pièce fournie doit avoir été requise.] ..Pièce, ->Requérir, --Fournir, Projet
No description has been provided for this image

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 [98]:
%%mocodo --colors ocean
      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
No description has been provided for this image

Remarques.

  • Pas de règle sur la taille de l'indentation. Pour Mocodo, autant de niveaux d'indentation distincts, autant de calques.

  • 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.

  • 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.

    Depuis la version 4.0, l'éditeur de Mocodo online vous permet de créer des curseurs multiples, ce qui simplifie encore ces opérations.

Limitations.

  • 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.

Dans le cas très rare où plusieurs SVG interactifs générés à partir du même texte-source coexistent sur une même page web, 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 [99]:
%%mocodo
FOO: foo
  BAR: bar
No description has been provided for this image
In [100]:
%%mocodo
FOO: foo
  BAR: bar
No description has been provided for this image

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 [101]:
%%mocodo --uid_suffix 1
FOO: foo
  BAR: bar
No description has been provided for this image
In [102]:
%%mocodo --uid_suffix 2
FOO: foo
  BAR: bar
No description has been provided for this image

Explications du passage au relationnel¶

Les gabarits de conversion en MLD (à savoir html, markdown, latex et text) admettent une sous-sous-option e qui accompagne le résultat par des explications détaillées du mécanisme de passage :

In [103]:
%mocodo -i ccp -t markdown:e

ccp_mld.md
  • Client (Réf. client, Nom, Prénom, Adresse)

    • Le champ Réf. client constitue la clé primaire de la table. C'était déjà un identifiant de l'entité Client.
    • Les champs Nom, Prénom et Adresse étaient déjà de simples attributs de l'entité Client.
  • Commande (Num. commande, Date, Montant, #Réf. client)

    • Le champ Num. commande constitue la clé primaire de la table. C'était déjà un identifiant de l'entité Commande.
    • Les champs Date et Montant étaient déjà de simples attributs de l'entité Commande.
    • Le champ Réf. client est une clé étrangère. Il a migré par l'association de dépendance fonctionnelle Passer à partir de l'entité Client en perdant son caractère identifiant.
  • Inclure (#Num. commande, #Réf. produit, Quantité)

    • Le champ Num. commande fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité Commande.
    • Le champ Réf. produit fait partie de la clé primaire de la table. C'est une clé étrangère qui a migré directement à partir de l'entité Produit.
    • Le champ Quantité était déjà un simple attribut de l'association Inclure.
  • Produit (Réf. produit, Libellé, Prix unitaire)

    • Le champ Réf. produit constitue la clé primaire de la table. C'était déjà un identifiant de l'entité Produit.
    • Les champs Libellé et Prix unitaire étaient déjà de simples attributs de l'entité Produit.

Nous avons essayé d'être aussi précis que possible, tout en « factorisant » avec soin les lignes consécutives suseptibles de l'être. Vous pouvez adapter ces explications à votre enseignement en modifiant une copie du gabarit html-ce.yaml, dont les autres sont dérivés.

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 [104]:
%%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
No description has been provided for this image

Masquer un couple de cardinalités¶

Vous pouvez masquer n'importe quelles cardinalités en les remplaçant par XX ou en les préfixant d'un - :

In [105]:
%%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
No description has been provided for this image

Nouveauté de la version 4.0. Si la cardinalité comporte un et un seul X, l'autre caractère sera affiché tout seul.

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 [106]:
%%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
No description has been provided for this image

Régression de la version 4.0. Les espaces insécables ne sont plus préservés. Il n'y a donc plus d'autre moyen de réserver davantage d'espace horizontal que d'employer le style blank (paragraphe suivant).

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

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 [107]:
%mocodo -i ccp --colors=blank
No description has been provided for this image

Attention, n'utilisez cette méthode que pour la projection : l'information textuelle est toujours présente, susceptible d'être sélectionnée et collée ailleurs. Vous pouvez bien sûr empêcher cette possibilité en convertissant le SVG en PNG, mais le plus simple est d'appliquer une réécriture empty :

In [108]:
%mocodo -i ccp -t empty # équivalent de "delete:types,notes,attrs,cards"
No description has been provided for this image

ccp.mcd
%%mocodo 
Client:  ,  ,  ,  
Passer, XX Client, XX Commande
Commande:  ,  ,  
Inclure, XX Commande, XX Produit:  
Produit:  ,  ,

Obfuscation d'un MCD donné¶

Obfusquer un MCD consiste à vider celui-ci de sa sémantique de surface en substituant des chaînes aléatoires à tous les libellés. Cela permet de créer des exemples d'illustration de telle ou telle notion « pure » sans risquer de voir son public se focaliser sur des détails-métier (c'est l'équivalent de la variable méta-syntaxique foobar dans le contexte de la pédagogie de la programmation).

In [109]:
%mocodo -i ccp --seed=1 --select mcd -t obfuscate  # raccourci pour "obfuscate:labels"
No description has been provided for this image

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

In [110]:
%mocodo -i ccp -t obfuscate:labels=../../README.md --seed=1 --select mcd
No description has been provided for this image

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

  • "lorem.txt" (6464 mots) : le faux-texte le plus courant, augmenté d'une sélection des 10000 mots latins les plus courants compilés par Kyle P. Johnson, le tout privé de ses doublons et des mots de moins de 3 lettres ("lorem_ipsum.txt" avant la version 4.0).
  • "fr.txt" (3396 mots) : une liste des 4000 mots français les plus courants, privée de ceux comportant une apostrophe ou moins de 4 lettres. Source : http://wortschatz.uni-leipzig.de/index.html via Wikitionary. Nouveauté de la version 4.0.
  • "fr5.txt" (464 mots): la liste de "fr.txt", restreinte aux mots de 5 lettres. Nouveauté de la version 4.0.
  • "en4.txt" (640 mots): une sélection (SFW) de mots anglais de quatre lettres ("four_letter_words.txt" avant la version 4.0).
  • "disparition.txt" (7489 mots) : le lexique du célèbre roman lipogrammatique de Georges Perec, privé des mots de moins de 4 lettres.

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

NB. L'algorithme s'assure que la distance de Damerau-Levenshtein entre deux libellés de substitution quelconques est d'au moins 3. 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 lui octroyer les points qui lui reviennent.

Croissance stochastique¶

Vous pouvez créer un MCD partiellement aléatoire à partir d'un MCD donné en lui ajoutant un nombre n d'associations (avec les entités nécessaires) :

In [111]:
%mocodo -i ccp -t grow:n=4 arrange --seed=1 --select mcd
No description has been provided for this image
  • Des sous-options pré-définies (données ci-dessous avec leur valeur par défaut après le =) permettent de spécifier finement le nombre désiré :

    • d'associations réflexives (arity_1=2) ;
    • d'associations ternaires (arity_3=2) ;
    • d'associations quaternaires (arity_4=0) ;
    • d'associations doubles, i.e., associant le même couple d'entités (doubles=1) ;
    • d'identifiants composites (composites=1) ;
    • d'attributs maximum par entité (ent_attrs=4) ;
    • d'attributs maximum par association (assoc_attrs=2).
  • On ne peut pas préciser directement le nombre d'associations binaires : si le nombre total des autres associations spécifiées n'arrivent pas à n, elles viennent en complément.

  • Des sous-options de forme plus ou moins libre décrivent les cardinalités. Par exemple, _11-*N=2 créera deux entités faibles et /*N-*N un agrégat. Les associations de complément sont *N-*N.

Avec la sous-option from_scratch, le MCD de départ est vide. À titre d'exemple, voici la transformation complexe invoquée par Mocodo online pour créer un MCD d'entraînement à la conversion au relationnel, accompagné de cette dernière. Notez la création de rôles par défaut : ils permettent de simuler le rétablissement de la sémantique des associations disparues.

In [ ]:
%mocodo --seed=2 --mld -t grow:from_scratch,arity_3=1,_11-*N=1 obfuscate create:roles lower:roles arrange

Il n'est pas impossible que le MCD résultant soit incorrect (p. ex., apparition d'une identification relative circulaire), mais les contrôles effectués a priori et a posteriori devraient dans la majorité des cas produire quelque chose de raisonnable.

Génération d'un QR code¶

Impressionnez votre public en accompagnant l'option -t share de --defer :

In [112]:
%mocodo -i ccp -t share --defer

ccp_url.svg
No description has been provided for this image

Limitation. Comme il faut un mobile pour scanner ce QR code, et que Mocodo online n'est pas vraiment adapté aux mobiles, l'intérêt réel de cette fonctionnalité est pour l'instant discutable.

Bibliothèque de MCD en ligne¶

Vous avez créé avec Mocodo toute une bibliothèque de MCD, certains pour illustrer des points de votre cours, d'autres comme solutions d'exercices. À partir de la version 4.1, vous pouvez donner accès à tel ou tel de ces MCD en communiquant simplement son nom à vos étudiants.

Accès sous Mocodo online¶

Pour comprendre le fonctionnement, accédons à un MCD de la bibliothèque par défaut : copiez-collez la chaîne def_weak-974e comme titre du MCD dans l'onglet Entrée de Mocodo online. Le texte-source est mis à jour avec le contenu d'un fichier def_weak-974e.mcd stocké en ligne :

Remarques.

  • Vous avez sans doute déjà utilisé cette fonctionnalité sans le savoir en parcourant le tutoriel, dont les MCD, appelés tuto-0000, tuto-0001, etc., sont récupérés de la même manière.
  • Tous les noms de fichiers de la bibliothèque par défaut se terminent par un code de quatre caractères alphanumériques : cette disposition évite qu'un utilisateur ne tombe dessus par hasard, et protège certains MCD (typiquement, les solutions d'exercices) de la curiosité naturelle des étudiants. Au moment de la correction, je leur donne simplement le nom complet, et ils récupèrent directement la solution, ce qui dégage du temps pour des activités plus éducatives que la recopie.

Bien sûr, la plupart des MCD de la bibliothèque par défaut n'intéressent que mon enseignement, et n'ont pas vocation à être diffusés au-delà du cercle très select des happy few qui en bénéficient.
Pour mettre votre propre bibliothèque à la disposition de vos propres étudiants :

  1. placez-la dans un répertoire dédié d'un serveur sur lequel vous avez les droits ;
  2. copiez-collez l'URL de ce répertoire dans le champ Bibliothèque de MCD (onglet Options). Désormais, c'est à cette adresse que Mocodo essaiera de trouver les MCD quand vous mettrez à jour leur titre ;
  3. vos étudiants devront eux-mêmes avoir renseigné le champ en question, ce qui peut poser des problèmes à certains. Facilitez-leur la tâche en leur donnant le lien suivant (tout ce qui suit lib= doit bien sûr être remplacé par l'adresse de votre répertoire distant) :
https://www.mocodo.net/?lib=https://your_server.com/path/to/your/mcd/directory

Ils n'auront plus qu'à cliquer pour remplir automatiquement le champ approprié, lequel persistera dans les cookies de leur navigateur.

Accès sous terminal ou Jupyter Notebook¶

L'option --input (ou -i) est surchargée pour aller chercher un MCD sur internet s'il ne se trouve pas dans le répertoire local. Pour commencer la démonstration, assurons-nous que le fichier en question n'existe pas en local :

In [113]:
path = Path("def_weak-974e.mcd")
path.unlink(missing_ok=True)
path.is_file()
Out[113]:
False

Récupérons-le de façon transparente dans la bibliothèque par défaut (avec ou sans extension .mcd) :

In [114]:
%mocodo -i def_weak-974e.mcd
No description has been provided for this image

Notez qu'au passage, pour le rendre disponible hors ligne, le fichier a été sauvegardé sur votre machine :

In [115]:
path.is_file()
Out[115]:
True

NB. Si le paramètre de -i est un chemin de la forme path/to/file.mcd (avec ou sans extension .mcd), c'est la dernière partie du chemin (à savoir file.mcd) qui sera récupérée sur le serveur. Par contre, c'est le chemin complet qui déterminera l'emplacement de la sauvegarde.

Pour utiliser votre propre répertoire distant, passez son URL à l'option --lib :

mocodo -i your_diagram.mcd --lib https://your_server.com/path/to/your/mcd/directory

Nous vous conseillons d'ajouter cette option dans votre fichier de paramètres personnalisé params.json.

Compléments sur l'aspect visuel¶

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).

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.

Réglages. 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).

Paramétrage du réarrangement automatique¶

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

Le critère que nous avons retenu pour évaluer la qualité du tracé est double :

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

Actuellement, deux algorithmes d'arrangement 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.

Remarque. Mocodo met en œuvre une technique de réarrangement originale : en contraignant la position des boîtes aux intersections d'une grille invisible, il transforme un classique problème de plongement en un problème d'affectation, ce qui permet de satisfaire de façon efficace à un certain nombre de contraintes esthétiques pertinentes (planarité, compacité, etc.).

Nous illustrerons les algorithmes et leurs paramètres sur le MCD d'accueil de Mocodo online.

Le réarrangement automatique peut se faire sans contraintes, ou dans les limites d'une grille spécifiée par l'utilisateur.

Méthode exacte (branch & bound)¶

Arrangement non contraint (par défaut)¶

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 [116]:
%mocodo -i ../examples/landing --select mcd --seed=2 -t arrange
No description has been provided for this image

Cela donne un plongement sur une grille 5×4, ce qui est loin d'être optimal. Cependant, l'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.

Arrangement dans la grille courante¶

Le réarrangement automatique des boîtes peut s'opérer dans les limites de la grille courante ; c'est-à-dire que le MCD résultant aura (au plus) le même nombre de colonnes et de rangées que le texte de départ (ici, 4×5) :

In [117]:
%mocodo -i ../examples/landing --select mcd --seed=2 -t arrange:current
No description has been provided for this image

Arrangement en privilégiant la largeur¶

Dans un document paginé, on cherche en général à utiliser en priorité l'espace horizontal. La version 4.0 introduit à cet effet une option de réarrangement « en largeur d'abord ». Le MCD d'accueil s'y prête particulièrement bien :

In [118]:
%mocodo -i ../examples/landing --select mcd --seed=2 -t arrange:wide=8 --scale 0.8
No description has been provided for this image

Ici, l'utilisateur a demandé 8 boîtes en largeur (c'est aussi la valeur par défaut). L'algorithme commence par calculer le nombre de lignes minimal correspondant, sachant qu'il a 14 boîtes à placer : c'est ⌈14/8⌉=2. Il cherche donc un plongement sur une grille 8×2.

Arrangement dans une grille équilibrée minimale¶

On peut chercher à faire tenir le MCD dans la plus petite grille possible, tout en maintenant entre hauteur et largeur un rapport « équilibré » (ou proche du nombre d'or). Par exemple, un MCD de 13 boîtes (entités ou associations) peut tenir dans les grilles:

  • 13×1;
  • 7×2, ce qui laisse 1 case vide;
  • 5×3, ce qui laisse 2 cases vides;
  • 4×4, 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×3.

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 (en gras) 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

Le MCD d'accueil ayant déjà été arrangé avec l'option -t arrange:balanced, nous ne le reproduisons pas ici. Sachez cependant qu'au cas où, pour une raison ou une autre, la plus petite grille équilibrée ne convient pas, il est possible de passer à la ie suivante en mettant i en sous-sous-argument. Ici, pour 14 boîtes, balanced=1 permet donc de passer de la grille 5×3 (prévue pour 13, 14 et 15 boîtes) à la grille 4×4 (prévue pour 16 boîtes).

In [119]:
%mocodo -i ../examples/landing --select mcd --seed=1 -t arrange:balanced=1
No description has been provided for this image

Limitations de la méthode exacte¶

Le réarrangement exact ne fonctionnera jamais sur les MCD non planaires ou n'admettant aucun plongement planaire dans les limites de la grille spécifiée (par les sous-options current, wide ou balanced).

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 doux nom de K3,3 :

In [120]:
%%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
No description has been provided for this image

Son réarrangement par Branch & bound échouera donc nécessairement :

In [121]:
%mocodo -i sandbox --seed=1 -t arrange:balanced
Mocodo Err.9 - Impossible de calculer un plongement planaire satisfaisant la contrainte
donnée.

Comme on voit, 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. Pour en avoir le cœur net, tentez un arrangement non contraint :

In [122]:
%mocodo -i sandbox --seed=1 -t arrange
Mocodo Err.41 - Impossible de calculer un plongement planaire.

NB. Plusieurs paramètres permettent de régler le fonctionnement de l'algorithme exact (Branch and Bound) :

  • call_limit : nombre maximal d'appels pour une boîte de départ donnée (défaut: 10000).
  • min_objective : meilleur objectif esthétique pour la mise en page (défaut: 0).
  • max_objective : pire objectif esthétique pour la mise en page (défaut: 15).

Réservés aux spécialistes, ils ne sont pas décrits dans cette documentation.

Méthode heuristique (algorithme génétique)¶

Dans tous les cas où la méthode exacte ne produit pas de résultat satisfaisant, on pourra se rabattre sur une heuristique qui, au lieu d'interdire les croisements, cherchera simplement à en minimiser le nombre.

In [123]:
%mocodo -i sandbox --seed=1 -t arrange:algo=ga
No description has been provided for this image

sandbox.mcd
%%mocodo --seed=1
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

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

In [124]:
%%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
No description has been provided for this image

NB. Plusieurs paramètres permettent de régler le fonctionnement de l'algorithme génétique :

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

Réservés aux spécialistes, ils ne sont pas décrits dans cette documentation.

Amélioration du plongement¶

Une entité liée à de nombreuses associations peut limiter ou même empêcher les possibilités de réarrangement sans croisements.

Par duplication d'entités réduites à leur identifiant¶

Lorsque cette entité est indépendante et réduite à son identifiant, elle est vouée à disparaître lors du passage au relationnel. Il n'y a donc 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.

Prenons comme exemple un MCD extrait d'une étude de François de Sainte Marie, et présenté comme suit :

Le graphe sous-jacent étant non planaire, des croisements sont inévitables (ici entre certaines pattes des associations SHR, CT et THR). Cependant, cette non-planarité résulte elle-même de la mise en jeu d'une même entité Période dans quatre associations triples. La monnayer en quatre entités Période numérotées augmente l'ordre du graphe, mais le rend planaire, le tout sans impact sur le schéma relationnel :

In [125]:
%%mocodo -t
Étudiant: id. étudiant, nom étudiant
:
:
SHR, 0N Période3, 0N Salle, 0N Étudiant
Période3: heure

:
CSG, 0N Niveau, 1N Cours, 1N Étudiant
Niveau: niveau
:

CHS, 0N Période2, 0N Cours, 0N Étudiant
Cours: id. cours, nom cours
CHR, 0N Période4, 0N Salle, 0N Cours
Salle: id. salle, nom salle

Période2: heure
CT, 11 Cours, 1N Professeur
Période4: heure
:
:

:
Professeur: id. professeur, nom professeur
:
THR, 0N Période1, 0N Salle, 0N Professeur
Période1: heure
No description has been provided for this image
  • CHR (heure, #id. salle, #id. cours)
  • CHS (heure, #id. cours, #id. étudiant)
  • Cours (id. cours, nom cours, #id. professeur)
  • CSG (niveau, #id. cours, #id. étudiant)
  • Étudiant (id. étudiant, nom étudiant)
  • Professeur (id. professeur, nom professeur)
  • Salle (id. salle, nom salle)
  • SHR (heure, #id. salle, #id. étudiant)
  • THR (heure, #id. salle, #id. professeur)

Ce genre de problème (et sa solution) se présente typiquement lorsqu'une entité DATE réduite à un identifiant date est associée à un grand nombre d'entités n'ayant rien à voir entre elles.

Par suppression de ces mêmes entités¶

Inversement, toujours étant donné que ce type d'entité est destiné à disparaître lors du passage au relationnel, on peut décider de les supprimer par anticipation. Pour cela, il faut accepter que les associations puissent être porteuses d'identifiants (ce qui n'est pas prévu par Merise). Cela permet d'obtenir un schéma conceptuel beaucoup plus lisible, toujours sans impact sur le schéma relationnel :

In [126]:
%%mocodo -t
CSG, 1N Cours, 1N Étudiant: _niveau
:
Cours: id. cours, nom cours
CT, 11 Cours, 1N Professeur

:
CHS, 0N Cours, 0N Étudiant: _heure
CHR, 0N Salle, 0N Cours: _heure
Professeur: id. professeur, nom professeur
    
Étudiant: id. étudiant, nom étudiant
SHR, 0N Salle, 0N Étudiant: _heure
Salle: id. salle, nom salle
THR, 0N Salle, 0N Professeur: _heure
No description has been provided for this image
  • CHR (#id. salle, #id. cours, heure)
  • CHS (#id. cours, #id. étudiant, heure)
  • Cours (id. cours, nom cours, #id. professeur)
  • CSG (#id. cours, #id. étudiant, niveau)
  • Étudiant (id. étudiant, nom étudiant)
  • Professeur (id. professeur, nom professeur)
  • Salle (id. salle, nom salle)
  • SHR (#id. salle, #id. étudiant, heure)
  • THR (#id. salle, #id. professeur, heure)

Notez qu'avec cette technique, les cardinalités minimales des pattes distinguées par les entités supprimées sont perdues dès le niveau conceptuel (sachant qu'elles l'auraient été de toute façon lors du passage au relationnel).

Comme la notion d'identifiant explicite d'association enfreint le standard Merise, et risque de semer la discorde entre professeurs et étudiants, elle est par défaut désactivée sous Mocodo online. En ligne de commande, elle est interdite à la demande :

In [127]:
%mocodo -i sandbox --no_assoc_ids
Mocodo Err.52 - L'association « CSG » ne peut pas avoir d'identifiant.

Ajustement de l'aspect de certains éléments¶

Format des cardinalités¶

Par défaut, les cardinalités sont séparées par une virgule, et celles des entités faibles soulignées, mais cela peut être changé :

In [128]:
%%mocodo  --card_format=({min_card}/{max_card}) --strengthen_card=(1/1)(R)
ŒUVRE: Cote œuvre, Titre, Date parution
DF, 1N ŒUVRE, _11 EXEMPLAIRE
EXEMPLAIRE: Num. exemplaire, État du livre, Date d'achat
No description has been provided for this image

Format des clés étrangères¶

La mise en forme des clés étrangères affichées dans le diagramme relationnel peut être paramétrée, par exemple pour enlever le préfixe par défaut (#) :

In [129]:
%mocodo -i ccp -t diagram --fk_format={label}

ccp_mld.svg
No description has been provided for this image

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 [130]:
%%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
No description has been provided for this image

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,

Basculement des cardinalités et inflexion des pattes rectilignes¶

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 monstrueusement pattues, des collisions qui ne se seraient pas produites par défaut seront parfois observées. L'utilisateur a alors deux possibilités:

  • 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 ;
  • modifier à la main les positions des cardinalités en conflit, comme expliqué dans la section suivante.

Positionnement des contraintes¶

En ajoutant des liens invisibles¶

La possibilité de rendre un trait invisible peut être exploitée pour « attirer » une contrainte vers telle ou telle boîte existante, soit en la répétant dans la définition de la contrainte, soit en l'y intégrant (fictivement) si elle n'en fait pas partie.

Par exemple, ci-dessous, répéter l'association Stocker et intégrer l'entité Commande permet de réduire la largeur du MCD sans compromettre sa lisibilité :

In [131]:
%%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
No description has been provided for this image

En ajoutant une boîte invisible¶

Ces réglages restent relativement fragiles. Une façon d'assurer qu'ils survivront à un réarrangement est de faire coïncider le centre d'une contrainte avec celui d'une boîte supplémentaire, que nous appelons ici « Z » :

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

:
Louer, 11 Commande, 0N Dépôt
Z, XX Commande, XX Article, XX 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: Z, Z
No description has been provided for this image

Il ne reste plus qu'à rendre invisibles l'association Z et ses pattes en préfixant Z d'un signe moins - :

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

:
Louer, 11 Commande, 0N Dépôt
-Z, XX Commande, XX Article, XX 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: Z, Z
No description has been provided for this image

Cette technique résiste très bien aux réarrangements automatiques.

Gouttière d'identifiants¶

Elle apparaît automatiquement (visibility=auto) dès qu'il y a au moins un identifiant alternatif. Il est possible de l'en empêcher :

In [134]:
%%mocodo --gutters ids:visibility=off
CLIENT: Réf. client, 1_Nom, 1_Prénom, Adresse, 2_Mail
No description has been provided for this image

... ou au contraire de la forcer quand elle est superfétatoire :

In [135]:
%%mocodo --gutters ids:visibility=on
CLIENT: Réf. client, Nom, Prénom, Adresse, Mail
No description has been provided for this image

Vous pouvez aussi préciser quelles chaînes dénoteront un identifiant fort (par défaut, strong=ID), un identifiant faible (par défaut, weak=id) ainsi que les numéros des groupes d'identifiants alternatifs (par défaut, alts=123456789, mais vous pouvez lister moins de 9 symboles) :

In [136]:
%%mocodo --gutters ids:strong=➤,alts=❶❷❸❹
CLIENT: Réf. client, 1_Nom, 1_Prénom, Adresse, 2_Mail
No description has been provided for this image

Style et direction des pattes de l'héritage¶

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 [137]:
%%mocodo -t
Personne: num SS, nom, prénom

/XT\ Personne => Homme, Femme: sexe

Homme: 
:
Femme: nom de jeune fille
No description has been provided for this image
  • Femme (num SS, nom, prénom, nom de jeune fille)
  • Homme (num SS, nom, prénom)

Cette visualisation n'est pas conventionnelle : on se borne normalement à 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, prolongez simplement d'un caractère la flèche : <==, <--, --> ou ==> :

In [138]:
%%mocodo -t
Personne: num SS, nom, prénom

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

Homme: 
:
Femme: nom de jeune fille
No description has been provided for this image
  • Femme (num SS, nom, prénom, nom de jeune fille)
  • Homme (num SS, nom, prénom)

Changement de la version 4.0. Précédemment, --> et ==> s'écrivaient respectivement ->> et =>>.

Retouches fines¶

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. Les autres coordonnées sont calculées relativement à celles-ci.

In [139]:
%%mocodo --colors brewer+1
VELIT, 1N> BLANDIT, 11 NONUMMY: sollicitudin

BLANDIT: consequat, ligula, nibh, consequat
:::
NONUMMY: consequat, ligula
  
VIVAMUS, 0N NONUMMY, 0N BLANDIT: eleifend, iaculis
No description has been provided for this image

Ouvrons le fichier de géométrie généré :

In [140]:
display.Code("sandbox_geo.json")
Out[140]:
{
  "width": 444,
  "height": 242,
  "cx": [
    [ "VELIT", 214 ],
    [ "BLANDIT", 58 ],
    [ "NONUMMY", 378 ],
    [ "VIVAMUS", 214 ]
  ],
  "cy": [
    [ "VELIT", 38 ],
    [ "BLANDIT", 117 ],
    [ "NONUMMY", 117 ],
    [ "VIVAMUS", 196 ]
  ],
  "shift": [
    [ "VELIT,BLANDIT,0", 0 ],
    [ "VELIT,NONUMMY,0", 0 ],
    [ "VIVAMUS,NONUMMY,0", 0 ],
    [ "VIVAMUS,BLANDIT,0", 0 ]
  ],
  "ratio": [
    [ "VELIT,BLANDIT,0", 1.0 ]
  ]
}

On y trouve :

  • 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 : leur valeur peuvent 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).

Copions-collons ce texte, apportons-lui quelques modifications et sauvegardons-le :

In [141]:
%%file sandbox_geo.json
{
  "width": 444,
  "height": 182,
  "cx": [
    [ "VELIT", 214 ],
    [ "BLANDIT", 58 ],
    [ "NONUMMY", 378 ],
    [ "VIVAMUS", 214 ]
  ],
  "cy": [
    [ "VELIT", 38 ],
    [ "BLANDIT", 87 ],
    [ "NONUMMY", 87 ],
    [ "VIVAMUS", 136 ]
  ],
  "shift": [
    [ "VELIT,BLANDIT,0", -30 ],
    [ "VELIT,NONUMMY,0", -30 ],
    [ "VIVAMUS,NONUMMY,0", 0 ],
    [ "VIVAMUS,BLANDIT,0", 0 ]
  ],
  "ratio": [
    [ "VELIT,BLANDIT,0", 0.5 ]
  ]
}
Overwriting sandbox_geo.json

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

In [142]:
%mocodo -i sandbox --colors brewer+1 --reuse_geo
No description has been provided for this image

Bien entendu, ce genre de manipulations doit rester exceptionnel. Il est en tout cas à réserver à la toute dernière étape de production d'un MCD, puisque la plupart des évolutions subséquentes de son texte-source frapperaient d'obsolescence votre fichier de géométrie.

NB. Étant donné que Mocodo produit des SVG, rien ne vous empêche de retoucher ceux-ci avec un logiciel de dessin vectoriel dédié, comme Inkscape (libre) ou Adobe Illustrator, Freehand, CorelDRAW, etc. Attention, le SVG généré n'est pas spécialement pensé pour cet usage. Certains éléments sont groupés pour permettre leur déplacement en bloc, mais les liens ne suivent pas ces déplacements, ce qui peut vite devenir fastidieux.

Conversion dans d'autres formats graphiques¶

Avec l'option --svg_to suivie de pdf et/ou png, Mocodo convertit en PDF et/ou PNG le SVG généré pour le MCD.

In [143]:
%mocodo -i ccp --svg_to png pdf --select

Le premier format est prévu pour inclusion dans des documents qui ne gèrent pas les SVG :

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

Attention, seules les polices de caractères les plus courantes apparaîtront correctement sur toutes les plateformes.

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

In [145]:
display.Image("ccp.png")
Out[145]:
No description has been provided for this image

Mentionnons une possibilité amusante, actuellement non intégrée à Mocodo : Svg2Rough.js pourra donner à votre travail une touche finale plus informelle, dans un style « tracé à main levée ».

In [146]:
display.Image("../examples/svg2roughjs.png")
Out[146]:
No description has been provided for this image

Annexe A : Miscellanées académiques¶

Décompositions d'un MCD¶

Aussi surprenant que cela puisse paraître, tout MCD peut être transformé en un MCD équivalent dont les seules associations sont des dépendances fonctionnelles binaires non porteuses d'attributs, telles que celle ci-dessous :

In [147]:
%%mocodo 
ENTITÉ 1_: at 1 1, at 1 2, at 1 3
DF, ?1 ENTITÉ 1_, XX ENTITÉ 2_
ENTITÉ 2_: at 2 1, at 2 2, at 2 3
No description has been provided for this image

La transformation peut demander jusqu'à trois opérations que Mocodo appelle drain, split et explode, et que nous allons découvrir dans la suite.

Vider les DF de leurs attributs¶

In [148]:
%%mocodo -t
Entreprise: nom entreprise, adresse, téléphone
Proposer, 0N Entreprise, 11 Stage: date proposition
Stage: num. stage, sujet
Attribuer, 11 Étudiant, 01 Stage: date signature
Étudiant: num étudiant, nom
Soutenir, 01 Étudiant, 0N Date: note stage
Date: date
No description has been provided for this image
  • Entreprise (nom entreprise, adresse, téléphone)
  • Étudiant (num étudiant, nom, #num. stage, date signature, date, note stage)
  • Stage (num. stage, sujet, #nom entreprise, date proposition)

Le MCD ci-dessus comporte trois associations de dépendance fonctionnelle porteuses d'attributs. Certains auteurs considèrent cela comme une anomalie. En tout état de cause, Mocodo peut les déplacer dans les entités distinguées par les cardinalités 11. Nous appelons cette opération un « drainage des dépendances fonctionnelles » (option -t drain). Notez bien que ces deux MCD sont strictement équivalents, et produisent le même MLD.

In [149]:
%mocodo -i sandbox --mld -t drain
No description has been provided for this image
  • Entreprise (nom entreprise, adresse, téléphone)
  • Étudiant (num étudiant, nom, date signature, #num. stage, date, note stage)
  • Stage (num. stage, sujet, date proposition, #nom entreprise)

La première version peut être préférée pour des raisons de localité sémantique (date proposition dans PROPOSER), ou honnie parce qu'elle complique la définition d'identifiant d'association. Mocodo n'a pas d'opinion sur la question. Par contre, il se refuse à procéder au drainage via les cardinalités 01. Dans le MCD ci-dessus, le placement de note stage dans SOUTENIR indique qu'un étudiant peut ne pas se voir attribuer de note de stage ; si elle était mise dans ÉTUDIANT, la connaissance du fait que ce champ autorise la valeur NULL serait perdue.

Décomposer les DF n-aires¶

De même, d'aucuns regardent de travers les dépendances fonctionnelles d'arité n supérieure à 2 :

In [150]:
%%mocodo -t
Bataille: nom bataille, lieu, date
Récolter, 0N Villageois, 0N Bataille, 11 Trophée
Villageois: nom villageois, adresse, fonction

Trophée: numéro, type, état
No description has been provided for this image
  • Bataille (nom bataille, lieu, date)
  • Trophée (numéro, type, état, #nom villageois, #nom bataille)
  • Villageois (nom villageois, adresse, fonction)

Toute DF de ce type peut en effet être « fendue » en n−1 DF. L'option -t split génère le MCD équivalent :

In [151]:
%mocodo -i sandbox --seed=3 --mld -t split arrange:wide
No description has been provided for this image
  • Bataille (nom bataille, lieu, date)
  • Trophée (numéro, type, état, #nom bataille, #nom villageois)
  • Villageois (nom villageois, adresse, fonction)

Décomposer les associations n-aires non DF¶

Toute association non DF d'arité n peut être décomposée en un ensemble de n associations DF : elle-même se voit alors remplacée par une entité liée aux n entités originales. Cette nouvelle entité est appelée « entité-intersection », « entité-associative » ou « Gerund », cf. Song, Il-Yeol & Evans, Mary & Park, Eui Kyun. A Comparative Analysis of Entity-Relationship Diagrams. Journal of Computer and Software Engineering. 3 (1995). Dans les cours de Laurent Audibert ou de Patrick Bergougnoux, l'opération est illustrée à l'aide du MCD suivant :

In [152]:
%%mocodo -t
Film: id. film, titre, durée
Projeter, 1N Salle, 1N Créneau, 1N Film: tarif
Salle: num. salle, capacité

Créneau: num. créneau, date, heure début
No description has been provided for this image
  • Créneau (num. créneau, date, heure début)
  • Film (id. film, titre, durée)
  • Projeter (#num. salle, #num. créneau, #id. film, tarif)
  • Salle (num. salle, capacité)

La décomposition est invoquée par l'option -t explode :

In [153]:
%mocodo -i sandbox --seed=8 --mld -t explode arrange:balanced
No description has been provided for this image
  • Créneau (num. créneau, date, heure début)
  • Film (id. film, titre, durée)
  • Projeter (id. projeter, tarif, #id. film, #num. salle, #num. créneau)
  • Salle (num. salle, capacité)

Le nouveau MCD a vocation à être retouché pour :

  • se rapprocher du plongement initial ;
  • nommer judicieusement les nouveaux identifiant, entité et associations créés.
In [154]:
%%mocodo -t
Film: id. film, titre, durée
Concerner, 11 Projection, 1N Film
Projection: id. projection, tarif
Avoir lieu dans, 11 Projection, 1N Salle
Salle: num. salle, capacité

Avoir lieu pendant, 11 Projection, 1N Créneau

Créneau: num. créneau, date, heure début
No description has been provided for this image
  • Créneau (num. créneau, date, heure début)
  • Film (id. film, titre, durée)
  • Projection (id. projection, tarif, #id. film, #num. salle, #num. créneau)
  • Salle (num. salle, capacité)

Décomposer les associations binaires non DF¶

Considérons le MCD suivant, qui comporte deux associations binaires non DF, l'une porteuse d'attribut, l'autre non :

In [155]:
%%mocodo -t
COMMANDE: num. commande, date, montant
LIGNE COM., 1N COMMANDE, 0N PRODUIT: quantité
PRODUIT: réf. produit, libellé, prix unitaire
DISPONIBILITÉ, 1N PRODUIT, 0N PAYS
PAYS: code pays, nom pays
No description has been provided for this image
  • COMMANDE (num. commande, date, montant)
  • DISPONIBILITÉ (#réf. produit, #code pays)
  • LIGNE COM. (#num. commande, #réf. produit, quantité)
  • PAYS (code pays, nom pays)
  • PRODUIT (réf. produit, libellé, prix unitaire)

Par souci de concision, quand on parle d'associations n-aires dans ce document, c'est par opposition aux associations binaires ; mais bien sûr, la règle de décomposition énoncée à la section précédente est également valable pour n=2, même si par défaut elle ne s'applique qu'aux associations d'arité minimale 3. En réduisant la valeur de arity à 2, toutes les associations binaires non DF seront également décomposées :

In [156]:
%mocodo -i=sandbox --seed=1 --scale=0.9 --mld -t explode:arity=2 arrange:wide=9
No description has been provided for this image
  • COMMANDE (num. commande, date, montant)
  • DISPONIBILITÉ (id. disponibilité, #réf. produit, #code pays)
  • LIGNE COM. (id. ligne com., quantité, #num. commande, #réf. produit)
  • PAYS (code pays, nom pays)
  • PRODUIT (réf. produit, libellé, prix unitaire)

Cette décomposition devient un peu extrême ! Vous pouvez conserver certaines associations binaires non DF, à savoir celles qui ne portent aucun attribut, en mettant arity à 2.5 (à lire comme « intermédiaire entre 2 et 3 ») :

In [157]:
%mocodo -i=sandbox --mld -t explode:arity=2.5 arrange:wide --seed=1
No description has been provided for this image
  • COMMANDE (num. commande, date, montant)
  • DISPONIBILITÉ (#réf. produit, #code pays)
  • LIGNE COM. (id. ligne com., quantité, #réf. produit, #num. commande)
  • PAYS (code pays, nom pays)
  • PRODUIT (réf. produit, libellé, prix unitaire)

Décomposer en créant des entités faibles¶

Ci-dessus, le processus de modification a créé un identifiant id. ligne com. qui peut sembler superfétatoire. Si l'on a introduit la notion d'entité faible, on aura ici avantage à utiliser l'option weak :

In [158]:
%mocodo -i=sandbox --mld -t explode:arity=2.5,weak arrange:wide --seed=1
No description has been provided for this image
  • COMMANDE (num. commande, date, montant)
  • DISPONIBILITÉ (#réf. produit, #code pays)
  • LIGNE COM. (#num. commande, #réf. produit, quantité)
  • PAYS (code pays, nom pays)
  • PRODUIT (réf. produit, libellé, prix unitaire)

Cas des agrégats. Comme on sait, la notion d'entité faible peut souvent permettre de se passer de celle d'agrégat. Ainsi, le MCD ci-dessous :

In [159]:
%%mocodo -t --colors ocean
Chambre: num. chambre, tarif
Réservation, /1N Client, 1N Chambre, 0N Date: durée
Client: réf. client, nom client

Date: date
No description has been provided for this image
  • Chambre (num. chambre, tarif)
  • Client (réf. client, nom client)
  • Réservation (#num. chambre, date, #réf. client, durée)

... se verra décomposé de la même façon que sans agrégat, à ceci près que la patte distinguée par le "/" produira une cardinalité 11 au lieu d'une cardinalité _11 :

In [160]:
%mocodo -i sandbox --mld -t explode:weak arrange:wide=5 --seed 21
No description has been provided for this image
  • Chambre (num. chambre, tarif)
  • Client (réf. client, nom client)
  • Réservation (date, #num. chambre, durée, #réf. client)

Cette décomposition peut quelquefois se simplifier. Ici, on remarque que l'entité DATE est indépendante et réduite à son identifiant. Si l'on anticipe sur le passage au relationnel, on peut donc la supprimer, après avoir pris soin, bien sûr, de déplacer dans RÉSERVATION son unique attribut. Celui-ci renforçant une entité faible, il doit garder son caractère identifiant.

In [161]:
%%mocodo -t
Chambre: num. chambre, tarif
DF, _11 Réservation, 1N Chambre
Réservation: date, durée
DF, 11 Réservation, 1N Client
Client: réf. client, nom client
No description has been provided for this image
  • Chambre (num. chambre, tarif)
  • Client (réf. client, nom client)
  • Réservation (#num. chambre, date, durée, #réf. client)

Conclusion sur ces décompositions¶

Comme l'indique le nom que nous leur avons malicieusement attribué, certaines de ces décompositions peuvent littéralement faire exploser la taille du MCD. Cependant :

  • elles sont intéressantes d'un point de vue terroriste théorique ;
  • elles peuvent permettre la détection d'erreurs de conception ;
  • elles peuvent conduire à des améliorations fines du MCD (c'est ce qu'on a fait sur celui des réservations de chambre) ;
  • elles décrivent le MCD dans un langage volontairement appauvri, ce qui le rendra plus aisément portable dans une autre notation, comme UML ou crow's foot.

Équivalences avec la convention Look Across¶

La convention Look Across s'oppose à la convention Look Here de Merise. Elle est plus répandue internationalement. Nous allons l'étudier par le biais du formalisme graphique de Chen, auquel cette section pourra du même coup servir d'introduction pour les personnes familières avec Merise.

Associations binaires en Look Across¶

Cardinalités minimale et maximale¶

Considérons un MCD Merise avec une association de dépendance fonctionnelle :

In [162]:
%%mocodo
Employé: employé
Travailler, 11 Département, 1N Employé
Département: département
No description has been provided for this image

Dans le formalisme graphique de Chen, cela donnera :

In [163]:
%mocodo -i sandbox -t chen:layout=circo --defer

sandbox_erd_chen.svg
No description has been provided for this image

Le 1 et le N correspondent aux cardinalités maximales du MCD Merise. Comme on voit, elles sont permutées. Merise suit la convention Look Here (LH) ; la notation de Chen, Look Across (LA). Comme cette dernière est la plus répandue dans le monde anglo-saxon, nous parlerons par commodité d'« ERD » (Entity-relationship diagram) pour les modèles conceptuels selon Chen, et toujours de « MCD » pour ceux de Merise.

Considérons maintenant les deux versions d'une association avec des cardinalités minimales distinctes :

In [164]:
%%mocodo
Mer: mer
Recevoir, 01 Rivière, 1N Mer
Rivière: rivière
No description has been provided for this image
In [165]:
%mocodo -i sandbox -t chen:layout=circo --defer

sandbox_erd_chen.svg
No description has been provided for this image

Les cardinalités maximales sont toujours permutées ; par contre, les cardinalités minimales ne le sont pas. Dans l'ERD, elles sont figurées par un trait simple (0) ou double (1). On les appelle aussi des « participations » : une rivière peut ne participer (directement) à l'alimentation d'aucune mer (ce n'est pas un fleuve) ; toute mer participe à la réception d'une rivière (un fleuve) minimum. Les conventions sont donc les suivantes :

Cardinalités MCD Merise ERD Chen
minimale LH LH
maximale LH LA

La notation Merise a l'avantage de la cohérence ; celle de Chen en a d'autres, que nous verrons un peu plus loin.

Avant cela, voyons un dernier point de détail : lorsque deux cardinalités N se trouvent de part et d'autre d'une association binaire, l'une est notée M :

In [166]:
%%mocodo
PROJET: projet
REQUÉRIR, 1N PROJET, 0N PIÈCE
PIÈCE: pièce
COMPOSER, 0N PIÈCE, 0N PIÈCE
No description has been provided for this image
In [167]:
%mocodo -i sandbox -t chen:layout=circo --defer

sandbox_erd_chen.svg
No description has been provided for this image

Entités faibles et entités associatives¶

Maintenant examinons le cas des entités faibles :

In [168]:
%%mocodo
Œuvre: œuvre
DF, 0N Œuvre, _11 Exemplaire
Exemplaire: exemplaire
No description has been provided for this image
In [169]:
%mocodo -i sandbox -t chen:layout=circo --defer

sandbox_erd_chen.svg
No description has been provided for this image

L'entité faible, à l'instar de la DF « renforçante », sont entourées d'un double trait.

Le vocabulaire de Chen comporte encore un élément graphique, que Merise ne distingue pas spécialement. Nous avons vu que toute association non DF pouvait être décomposée de façon équivalente par l'insertion d'entités faibles :

In [ ]:
%%mocodo
Produit: produit
DF, _11 Ligne de commande, 0N Produit
Ligne de commande: _quantité
DF, _11 Ligne de commande, 1N Commande
Commande: commande

LIGNE DE COMMANDE est quelquefois qualifiée d'« entité associative », et Chen la figure logiquement par un losange (association) inscrit dans un rectangle (entité). Graphviz ne prend actuellement pas en charge cette représentation. Nous l'approximons donc ainsi :

In [170]:
%mocodo -i sandbox -t chen:layout=circo,mindist=2,scale=0.6 --defer

sandbox_erd_chen.svg
No description has been provided for this image

Associations n-aires en Look Across¶

Triplet NNN¶

Passons maintenant aux choses sérieuses. Jusqu'ici, la différence entre les deux notations était purement cosmétique. Qu'en est-il des associations n-aires, et que signifie Look Across quand across peut désigner plusieurs endroits ?

In [171]:
%%mocodo -t
Employé: employé
Appliquer, 0N Employé, 1N Projet, 1N Compétence
Projet: projet

Compétence: compétence
No description has been provided for this image
  • Appliquer (employé, projet, compétence)

Dans ce cas (le plus usuel), la question ne se pose pas vraiment, ou du moins n'est pas tranchée de façon évidente :

In [172]:
%mocodo -i sandbox -t chen:layout=circo,mindist=1,scale=0.4 --defer

sandbox_erd_chen.svg
No description has been provided for this image

Quels sont les autres cas ? Il ne s'agit pas de ceux où l'association n-aire est entourée d'une ou plusieurs cardinalités maximale 1, puisqu'on pourrait alors la décomposer en DF binaires (cf. argument split). En réalité, on touche ici aux limites de la notation Look Here, plus intuitive, mais moins puissante que Look Across, et que Merise n'a pu rattraper que dans sa version 2.

Pour répondre progressivement à la question, procédons désormais dans l'ordre inverse, en présentant d'abord l'ERD, et ensuite seulement le MCD équivalent.

Les exemples qui suivent (ainsi d'ailleurs que le précédent), sont adaptés des pages 28 sqq. et 96 sqq. de l'ouvrage de Toby J. Teorey, Sam S. Lightstone, Tom Nadeau, H.V. Jagadish, Database Modeling and Design - Logical Design, 5th Edition - February 10, 2011 (Elsevier).

Triplet 1NN¶

Le premier ERD apportant véritablement quelque chose de nouveau a cette structure :

In [173]:
%%mocodo -t chen:layout=circo,mindist=1,scale=0.45 --defer
Ingénieur: ingénieur
Gérer, /1N Responsable, 1N Ingénieur, 1N Projet
Projet: projet

Responsable: responsable

sandbox_erd_chen.svg
No description has been provided for this image

Les auteurs explicitent ainsi ses règles de gestion :

Chaque ingénieur travaillant sur un projet particulier a exactement un responsable, mais chaque responsable d'un projet peut gérer plusieurs ingénieurs, et chaque responsable d'un ingénieur peut gérer cet ingénieur sur plusieurs projets.

Reprenons ces trois assertions, et faisons-les correspondre au trois cardinalités dans le sens anti-horaire à partir du 1 :

  • 1 : pour un couple (ingénieur, projet) donné, un seul responsable possible ;
  • N : pour un couple (responsable, projet) donné, plusieurs ingénieurs possibles ;
  • N : pour un couple (responsable, ingénieur) donné, plusieurs projets possibles.

Avec Merise, les assertions seraient plutôt du type : « pour un x donné, tant de couples (y, z) possibles ». Il y a donc bien permutation, mais permutation des références au singleton et au n−1-uplet.

C'est la réponse à notre question initiale, et nous verrons avec plaisir qu'elle reste valable quel que soit le triplet de cardinalités de l'association ternaire.

Pour l'instant, résumons les règles de gestion par cette unique dépendance fonctionnelle :

  • (Ingénieur, Projet) ⟹ Responsable.

Pour exprimer cela en (ou en dépit de) Look Here, on doit recourir à un agrégat :

In [174]:
%mocodo -i sandbox --mld --colors pond
No description has been provided for this image
  • Gérer (ingénieur, projet, responsable)

… ou à une CIF à unicité complète (ici en notation allégée) :

In [175]:
%mocodo -i sandbox --mld -t create:cifs=light arrange:balanced --seed=3
No description has been provided for this image
  • Gérer (ingénieur, projet, responsable)

... Ou encore à une entité faible :

In [176]:
%mocodo -i sandbox --mld -t explode:weak,arity=2 arrange:balanced --seed=14
No description has been provided for this image
  • Gérer (ingénieur, projet, responsable)

Les schémas relationnels produits permettent de se convaincre que ces différentes variantes respectent bien la dépendance fonctionnelle désirée : (Ingénieur, Projet) ⟹ Responsable.

Triplet 11N¶

Passons à la deuxième combinaison intéressante :

In [177]:
%%mocodo -t chen:layout=circo,mindist=1,scale=0.45 --defer
Projet: projet
Affecter, /1N Site, /1N Projet, 0N Employé
Site: site

Employé: employé

sandbox_erd_chen.svg
No description has been provided for this image

Règles de gestion :

Chaque employé affecté à un projet travaille sur un seul site pour ce projet, mais peut se trouver sur différents sites pour différents projets. Sur un site donné, un salarié ne travaille que sur un seul projet. Sur un site donné, il peut y avoir plusieurs employés affectés à un projet donné.

Autrement dit (en partant du bas et dans le sens anti-horaire) :

1 : pour un couple (projet, employé) donné, un seul site possible ; 1 : pour un couple (employé, site) donné, un seul projet possible ; N : pour un couple (projet, site) donné, plusieurs employés possibles.

En résumé, deux dépendances fonctionnelles :

  • (Projet, Employé) ⟹ Site.
  • (Employé, Site) ⟹ Projet.

Voici le MCD correspondant, successivement avec des agrégats et des CIFS (plus de variante possible avec entité faible) :

In [178]:
%mocodo -i sandbox --select all -t mld:c --colors pond
No description has been provided for this image

sandbox_mld.md
  • Affecter (projet, employé u1, site! u1)
In [179]:
%mocodo -i sandbox --select mcd mld -t mld:c create:cifs=light arrange:balanced --seed=3
No description has been provided for this image

sandbox_mld.md
  • Affecter (projet, employé u1, site! u1)

On voit apparaître dans le schéma relationnel un « u1 » en exposant qui signifie : contrainte d'unicité n°1. Il y a en effet deux clés candidates : (projet, employé) et (employé, site). Seule l'une des deux est devenue clé primaire, mais cela ne veut pas dire qu'on a perdu la contrainte de dépendance fonctionnelle induite par l'autre. En SQL :

In [180]:
%mocodo -i sandbox -t sql

sandbox_ddl.sql
CREATE TABLE Affecter (
  PRIMARY KEY (projet, employe),
  projet  VARCHAR(42) NOT NULL,
  employe VARCHAR(42) NOT NULL,
  site    VARCHAR(42) NOT NULL,
  UNIQUE (employe, site)
);

Triplet 111¶

La dernière combinaison obéit à la même logique :

In [181]:
%%mocodo -t chen:layout=circo,mindist=1,scale=0.45 --defer
Technicien: technicien
Utiliser, /1N Technicien, /1N Carnet, /1N Projet
Projet: projet

Carnet: carnet

sandbox_erd_chen.svg
No description has been provided for this image

Règles de gestion :

Un technicien utilise exactement un carnet pour chaque projet. Chaque carnet appartient à un technicien pour chaque projet. Notez qu'un technicien peut toujours travailler sur plusieurs projets et gérer différents carnets pour différents projets.

Autrement dit (en partant du haut et dans le sens horaire) :

  • 1 : pour un couple (technicien, projet) donné, un seul carnet possible ;
  • 1 : pour un couple (carnet, projet) donné, un seul technicien possible ;
  • 1 : pour un couple (carnet, technicien) donné, un seul projet possible.

En résumé, trois dépendances fonctionnelles :

  • (Technicien, Projet) ⟹ Carnet.
  • (Carnet, Technicien) ⟹ Projet.
  • (Carnet, Projet) ⟹ Technicien.
In [182]:
%mocodo -i sandbox --select all -t mld:c --colors pond
No description has been provided for this image

sandbox_mld.md
  • Utiliser (carnet u1, projet u2, technicien! u1 u2)
In [183]:
%mocodo -i sandbox --select mcd mld -t mld:c create:cifs=light arrange:balanced flip:d,v --seed=12
No description has been provided for this image

sandbox_mld.md
  • Utiliser (carnet u1, projet u2, technicien! u1 u2)

Il y a maintenant trois clés candidates, correspondant à deux contraintes d'unicité. En SQL :

In [184]:
%mocodo -i sandbox -t sql

sandbox_ddl.sql
CREATE TABLE Utiliser (
  PRIMARY KEY (carnet, projet),
  carnet     VARCHAR(42) NOT NULL,
  projet     VARCHAR(42) NOT NULL,
  technicien VARCHAR(42) NOT NULL,
  UNIQUE (carnet, technicien),
  UNIQUE (projet, technicien)
);

Conclusion sur les agrégats multiples¶

Notre syntaxe /1N pour les agrégats permet d'exprimer simplement toutes les combinaisons possibles de cardinalités d'une association n-aire dans la notation de Chen : il suffit de mettre un /1N partout où Chen met un 1. Chaque /1N créera une nouvelle dépendance fonctionnelle, autrement dit, une nouvelle clé candidate.

Plus rigoureusement : supposons une association n-aire A exclusivement entourée de 1N (ou 0N). Soient E1, E2, ..., En les entités mises en jeu, et k1,k2, ..., kn leurs identifiants respectifs. Alors, noter /1N (ou /0N) la cardinalité de la patte de Ei dénote l'existence de la dépendance fonctionnelle suivante : (k1,...,ki−1,ki+1,...,kn)⟹ki, autrement dit : que (k1,...,ki−1,ki+1,...,kn) est une clé candidate de la table A.

Notez pour finir que Mocodo permet de spécifier à coût zéro quelle clé candidate sera élue clé primaire. Il suffit pour cela de placer en tête de la liste des entités mises en jeu par A celle dont l'identifiant ne doit pas entrer dans la clé primaire. Si c'est E1, la clé primaire sera automatiquement (k2,...,kn).

Annexe B : La commande mocodo¶

Paramétrage¶

mocodo --help¶

In [185]:
%mocodo --help
usage: mocodo [--language CODE] [--params_path PATH] [--input PATH] [--help]
              [--version] [--restore] [--lib [URL]] [--output_dir PATH]
              [--encodings [STR ...]] [--svg_to {png,pdf} [{png,pdf} ...]]
              [--print_params] [--reuse_geo] [--uid_suffix INT]
              [--select [{all,mcd,rw,source,text,code,mocodo,cv,mld,ddl,sql} ...]]
              [--defer [STR ...]] [--mld] [--transform [STR ...]]
              [--seed [FLOAT]] [--title STR] [--df STR] [--card_format [STR]]
              [--fk_format [STR]] [--strengthen_card [STR]] [--flex FLOAT]
              [--colors STEM_OR_PATH] [--shapes STEM_OR_PATH] [--scale RATE]
              [--adjust_width RATE] [--detect_overlaps] [--no_assoc_ids]
              [--gutters STR [STR ...]]

NOM :
Mocodo - Un générateur de diagrammes entité-association.

DESCRIPTION :
Mocodo est un outil libre destiné à l'enseignement des bases de données relationnelles.
Il prend en entrée une description textuelle des entités et associations d'un diagramme
entité-association (MCD). Il produit en sortie un dessin vectoriel en SVG et un schéma
relationnel dans divers formats (SQL, LaTeX, Markdown, etc.).

NOTE :
Chacune des valeurs suivantes est :
- spécifiée explicitement par l'utilisateur comme option de ligne de commande ;
- sinon, récupérée depuis un fichier de chemin --params_path ;
- sinon, récupérée depuis un fichier nommé « params.json » dans le répertoire d'entrée ;
- sinon, calculée à partir d'une valeur par défaut, éventuellement dépendante de votre système.
    

OPTIONS SUR MOCODO LUI-MÊME :
  --language CODE       force la localisation des messages avec le code de
                        langue donné (par exemple, « fr », « en », ...)
                        (default: fr)
  --help                affiche ce message d'aide, puis termine
  --version             affiche le numéro de version, puis termine
  --restore             recrée une version vierge des fichiers « sandbox.mcd »
                        et « params.json » dans le répertoire d'entrée, puis
                        termine (default: 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.
                        S'il n'existe pas, utilise les paramètres par défaut.
                        (default: params.json)
  --input PATH, -i PATH
                        le chemin du fichier d'entrée. Par défaut, les
                        fichiers de sortie seront générés dans le même
                        répertoire (default: /Users/aristide/Dropbox/Sites/moc
                        odo/doc/mocodo_notebook/sandbox.mcd)
  --lib [URL]           remote directory to use as fallback when the input
                        file is not found locally (default:
                        https://mocodo.net/web/lib)
  --output_dir PATH     le répertoire des fichiers de sortie (default: .)
  --encodings [STR ...]
                        un ou plusieurs encodages à essayer successivement
                        lors de la lecture du fichier d'entrée (default:
                        ['utf8', 'macroman'])
  --svg_to {png,pdf} [{png,pdf} ...]
                        génère une version PNG ou PDF de la sortie SVG
                        (requiert CairoSVG) (default: [])
  --print_params        affiche le contenu du fichier de paramètres, puis
                        termine (default: False)
  --reuse_geo           réutilise le fichier de géométrie de l'exécution
                        précédente (default: False)
  --uid_suffix INT      ajoute un discriminateur à un SVG interactif (default:
                        0)
  --select [{all,mcd,rw,source,text,code,mocodo,cv,mld,ddl,sql} ...]
                        sous Jupyter Notebook, spécifie explicitement les
                        catégories de résultats à afficher
  --defer [STR ...]     utilise un service web externe pour convertir les
                        résultats de la conversion dans les formats graphiques
                        donnés
  --mld                 alias de compatibilité ascendante pour « -t » (sans
                        arguments). Équivalent à « -t markdown » mais, sous
                        Jupyter Notebook, n'empêche pas le rendu du diagramme
                        conceptuel dans la sortie de la cellule (default:
                        False)
  --transform [STR ...], -t [STR ...]
                        crée une nouvelle version du MCD en appliquant
                        séquentiellement les opérations de réécriture données,
                        et/ou le convertit dans les formats ou langages
                        donnés. Sous Jupyter Notebook, « -T » remplace
                        respectivement la cellule courante par le résultat
                        textuel, ou le copie dans le presse-papier (pip3
                        install pyperclip)
  --seed [FLOAT]        valeur initiale pour le générateur de nombres
                        aléatoires (default: None)
  --title STR           nom du modèle, utilisé à divers endroits (système de
                        fichiers, base de données, etc.) (default: MCD)

ASPECT DE LA SORTIE GRAPHIQUE :
  --df STR              l'acronyme à entourer dans une dépendance
                        fonctionnelle (default: DF)
  --card_format [STR]   chaîne de formatage pour les cardinalités minimales et
                        maximales (default: {min_card},{max_card})
  --fk_format [STR]     chaîne de formatage pour les clés étrangères dans le
                        diagramme relationnel (default: #{label})
  --strengthen_card [STR]
                        chaîne pour les cardinalités relatives (default:
                        _1,1_)
  --flex FLOAT          incurve les pattes rectilignes dont les cardinalités
                        peuvent se chevaucher (default: 0.75)
  --colors STEM_OR_PATH
                        la palette de couleurs à utiliser lors de la
                        génération du dessin. Nom (sans extension) d'un
                        fichier situé dans le répertoire « colors », ou chemin
                        vers un fichier personnel (default: bw)
  --shapes STEM_OR_PATH
                        spécification des polices, dimensions, etc. Nom (sans
                        extension) d'un fichier situé dans le répertoire
                        « shapes », ou chemin vers un fichier personnel
                        (default: copperplate)
  --scale RATE          applique au diagramme le facteur de mise à l'échelle
                        donné (default: 1)
  --adjust_width RATE   applique à tous les textes calculés le facteur de mise
                        à l'échelle donné (default: 1)
  --detect_overlaps     lève une erreur quand des pattes horizontales ou
                        verticales se chevauchent (default: False)
  --no_assoc_ids        interdit l'utilisation d'identifiants dans les
                        associations (conformément au standard Merise)
                        (default: False)
  --gutters STR [STR ...]
                        définit la visibilité et le contenu des gouttières
                        latérales

VOIR AUSSI :
  Version en ligne      https://mocodo.net
  Code source           https://github.com/laowantong/mocodo
  Documentation         https://rawgit.com/laowantong/mocodo/master/doc/fr_refman.html
  Aide-mémoire pour -t  https://github.com/laowantong/mocodo/blob/master/doc/fr_cheat_sheet.md

LICENCE :               MIT

CONTACT :
  Auteur                Aristide Grange
  Adresse               Université de Lorraine
                        Laboratoire LCOMS - UFR MIM
                        3 rue Augustin Fresnel
                        57070 METZ Technopôle
                        France
  Courriel              <prénom.nom>@univ-lorraine.fr
    

Paramétrage à long terme¶

Pour éviter d'avoir à invoquer Mocodo répétitivement avec une longue kyrielle d'options, vous pouvez mettre celles-ci 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).

Pour que le style de vos MCD soit maintenu à moindre frais à travers tous vos documents, vous êtes encouragés à modifier ce fichier de paramètres selon vos goûts et vos besoins. Mocodo peut même vous aider à le faire en exécutant la cellule suivante:

%mocodo --print_params

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

In [186]:
# You may edit and run the following lines
import json, pathlib
params = """\
{
  "adjust_width": 1,
  "card_format": "{min_card},{max_card}",
  "colors": "bw",
  "detect_overlaps": false,
  "df": "DF",
  "encodings": [ "utf8", "macroman" ],
  "fk_format": "#{label}",
  "flex": 0.75,
  "language": "fr",
  "lib": "https://mocodo.net/web/lib",
  "mld": false,
  "no_assoc_ids": false,
  "output_dir": ".",
  "restore": false,
  "scale": 1,
  "seed": null,
  "shapes": "copperplate",
  "strengthen_card": "_1,1_",
  "svg_to": [],
  "title": "MCD",
  "uid_suffix": 0
}"""
try:
    json.loads(params)
except:
    raise RuntimeError("Invalid JSON. Check your syntax on https://jsonlint.com.")
pathlib.Path("./params.json").write_text(params, encoding="utf8");

Ensuite :

  1. Modifiez la variable params à votre gré en respectant la syntaxe JSON.
  2. Exécutez la cellule pour créer un fichier de nom et emplacement adéquats.

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.

Dissection de la commande¶

L'API de Mocodo a été revue de façon radicale pour la version 4.0. Le nombre d'options de premier niveau a été réduit ; en contrepartie, certaines sont devenues de véritables mini-commandes, avec leur propre liste d'arguments, et une syntaxe et un comportement uniformes. Voici leur définition en ABNF :

Introduisons, sur un exemple fictif, un vocabulaire que nous avons essayé d'employer le plus rigoureusement possible tout au long de cette documentation (et dans le code lui-même) :

mocodo    --select all    --transform  drain  arrange:wide  explode:weak,arity=2.5
  • La commande mocodo est invoquée avec les options --select et --transform.
  • On passe à la seconde trois arguments de complexité croissante, drain, arrange:wide et explode:weak,arity=2.5. Notez que le séparateur des arguments est l'espace. Par conséquent, un argument ne peut contenir d'espaces qu'entre guillemets.
  • Chacun des arguments consiste en un nom de sous-option (drain, arrange ou explode), suivi éventuellement d'un deux-points (:), suivi d'une liste de sous-arguments séparés par des virgules (,).
  • Chacun des sous-arguments consiste en un nom de sous-sous-option, suivi éventuellement d'un signe égal (=), suivi d'un sous-sous-argument (éventuellement entre guillemets).

On n'ira pas plus loin et, heureusement, la plupart des commandes réelles n'atteignent pas ce degré d'imbrication. La décomposition suivante fixera peut-être les idées, ou pourra du moins servir de référence en cas de doute :

mocodo⏟command--select⏟optionall⏟argument--transform⏟optiondrain⏟sub-option⏟argumentarrange⏟sub-option:wide⏟sub-sub-opt⏟sub-arg⏟argumentexplode⏟sub-option:weak⏟sub-sub-opt⏟sub-arg,arity⏟sub-sub-opt=2.5⏟sub-sub-arg⏟sub-argument⏟argument

L'intérêt de cette structuration en arborescence est double. Elle permet :

  • de créer des pipelines d'opérations : le résultat de l'application du premier argument est fourni en entrée au second, etc ;
  • de regrouper les opérations interdépendantes. Par exemple, avant la version 4.0, l'argument explode:weak,arity=2.5 aurait dû être mis à plat : --explode --weak_explosion --explosion_arity=2.5. Cela donne le même statut à toutes, masquant le fait que certaines n'ont de sens qu'en présence d'une autre.

L'option --transform et ses arguments¶

Triage et exécution des transformations¶

L'option à tout faire est --transform, que vous pouvez abréger -t. Avant de traiter ses arguments, Mocodo commence par les répartir en deux catégories :

  • les réécritures, qui transforment le MCD original en un nouveau MCD avec, par exemple, les libellés mis en majuscules, ou les associations n-aires décomposées en DF, ou les boîtes réarrangées ;
  • les conversions, qui produisent quelque chose qui n'est pas un MCD : ce peut être un dictionnaire des données, un diagramme de classes UML, un ERD dans la notation crow's foot, etc.

L'exécution se déroule alors en deux étapes :

  1. les réécritures sont opérées en pipeline, c'est-à-dire que le MCD produit par la première réécriture est passé en entrée de la seconde, etc. Leur ordre a donc de l'importance ;
  2. les conversions sont alors appliquées au résultat de la dernière réécriture. Leur ordre n'a pas d'importance.

Aide-mémoire des transformations¶

L'option -t (ou --transform) permet d'accéder à un grand nombre d'opérations de conversion ou de réécriture.

Toutes les opérations de conversion ont déjà été décrites dans ce document :

  • produits dérivés : data_dict, share ;
  • schémas relationnels textuels : html, latex, markdown, text ;
  • DDL : sql (et ses dialectes) ;
  • autres sorties relationnelles : diagram, dbml, d2, dependencies ;
  • conversions dans d'autres notations : uml, crow, chen.

Certaines opérations de réécriture ont été présentées, d'autres passées sous silence :

  • réorganisation du MCD : arrange, flip ;
  • obfuscation et randomisation d'éléments donnés : randomize, drown ;
  • génération de MCD aléatoires : grow ;
  • décomposition d'associations : split, drain, explode ;
  • inférence d'informations manquantes : create ;
  • suppression d'éléments donnés : delete ;
  • traitement de chaînes de caractères : truncate, slice, prefix, suffix, replace ;
  • homogénéisation de la mise en forme : ascii, camel, snake, pascal, lower, upper, etc.

L'aide-mémoire suivant devrait vous permettre de prendre en main les sous-options de --transform qui vous intéressent. Survolez une sous-option pour afficher ses alias éventuels.

In [187]:
display.Markdown("../fr_cheat_sheet.md")
Out[187]:

Opérations de conversion¶

Sous-option Description Exemples Explications
ast crée l'arbre de syntaxe abstraite du texte source (pour le débogage)
chen convertit le modèle conceptuel dans la notation de Chen chen sans attributs
chen:attrs avec attributs
chen:attrs --defer calcule le rendu graphique via un service web
chen:layout=circo,mindist=2,scale=0.6 ajoute des options arbitraires pour Graphviz
crow convertit le modèle conceptuel dans la notation crow's foot crow format Graphviz
crow --defer calcule le rendu graphique via un service web
crow:mmd format Mermaid
crow:mermaid idem
d2 convertit le modèle conceptuel en un schéma relationnel au format D2
data_dict extrait tous les attributs du MCD dans une table data_dict tableau Markdown, trois colonnes
data_dict:label liste Markdown, une colonne
data_dict:label,type='Description' deux colonnes, un libellé personnalisé
data_dict:label='Attribut',type='Description' deux colonnes, deux libellés personnalisés
data_dict:**box**='Entité ou<br>association',label,`type`=`'Type de données'` mise en forme de certains libellés
data_dict:tsv tableau TSV, trois colonnes
data_dict:tsv,label liste des attributs séparés par des retours à la ligne
dbml convertit le modèle conceptuel en un schéma relationnel au format DBML dbml version de base
dbml:b avec boilerplate
debug liste des informations internes relatives à la conversion en schéma relationnel
dependencies convertit le modèle conceptuel en un graphe de dépendances
diagram convertit le modèle conceptuel en un diagramme relationnel au format Mocodo diagram version de base
diagram:c avec contraintes d'unicité et d'optionalité
html convertit le modèle conceptuel en un schéma relationnel au format HTML html version de base
html:b avec boilerplate
html:c avec contraintes d'unicité et d'optionalité
html:e avec explications
html:bce avec boilerplate, contraintes et explications
latex convertit le modèle conceptuel en un schéma relationnel au format LaTeX latex version de base
latex:b avec boilerplate
latex:c avec contraintes d'unicité et d'optionalité
latex:e avec explications
latex:bce avec boilerplate, contraintes et explications
markdown convertit le modèle conceptuel en un schéma relationnel au format Markdown markdown version de base
markdown:c avec contraintes d'unicité et d'optionalité
markdown:e avec explications
markdown:ce avec contraintes et explications
mssql convertit le modèle conceptuel en un modèle physique pour Microsoft SQL Server mssql version de base
mssql:b avec boilerplate
mysql convertit le modèle conceptuel en un modèle physique pour MySQL mysql version de base
mysql:b avec boilerplate
oracle convertit le modèle conceptuel en un modèle physique pour Oracle DB oracle version de base
oracle:b avec boilerplate
postgresql convertit le modèle conceptuel en un modèle physique pour PostgreSQL postgresql version de base
postgresql:b avec boilerplate
prompt génère un prompt pour demander à une IA de compléter le MCD prompt:cards avec les explications des cardinalités
prompt:types avec les types des attributs
relation convertit le modèle conceptuel en schéma relationnel avec le gabarit donné relation:path/to/my_template.yaml chemin relatif, extension obligatoire
share encode le MCD dans une URL pour Mocodo online qr --defer génère un QR code via un service web
sql convertit le modèle conceptuel en un modèle physique pour SQL
sqlite convertit le modèle conceptuel en un modèle physique pour SQLite sqlite version de base
sqlite:b avec boilerplate
text convertit le modèle conceptuel en un schéma relationnel au format texte text version de base
text:c avec contraintes d'unicité et d'optionalité
html:e avec explications
html:ce avec contraintes et explications
uml convertit le modèle conceptuel en diagramme de classes UML uml format PlantUML
uml:plantuml idem
uml --defer calcule le rendu graphique via un service web
uml:plantuml=- supprime les styles par défaut
uml:plantuml='skinparam backgroundColor yellow\nskinparam classAttributeFontName Arial\n' ajoute des styles personnalisés

Opérations de réécriture¶

Sous-option Description Exemples Explications
arrange réarrange la disposition, soit par Branch & Bound, soit avec un algorithme génétique arrange B&B sans contraintes
arrange:timeout=60 B&B limité à une minute
arrange:wide B&B privilégiant la largeur
arrange:current B&B sur la grille courante
arrange:balanced=0 B&B sur la plus petite grille équilibrée
arrange:balanced=1 B&B sur la seconde plus petite grille équilibrée
arrange:algo=ga algorithme génétique
ascii réécrit les éléments donnés en ASCII ascii:roles,labels rôles, libellés des boîtes et des attributs en ASCII
camel réécrit les éléments donnés en camelCase
capitalize réécrit les éléments donnés en capitalisant la première lettre de chaque mot
casefold réécrit les éléments donnés en minuscules, mais plus agressivement que « lower »
create essaie d'inférer les types, entités, CIFs ou flèches de DF à partir des éléments existants guess:types deviner les types manquants
create:types= remplacer les types manquants par []
create:types=TODO remplacer les types manquants par [TODO]
make:entities réparer l'oubli d'entités référencées dans des associations
create:dfs mettre des DF partout où c'est possible
add:df_arrows ajouter des flèches aux DF 11
add:cifs ajouter les CIF correspondant aux agrégats
add:cifs=light même chose en visualisation allégée
add:roles mettre comme rôles le nom des associations partout où c'est utile
delete supprime les éléments donnés quand c'est possible empty ne garde que la structure et le nom des boîtes
delete:types,notes,attrs,cards idem
delete:cards remplace les cardinalités par XX
delete:card_prefixes supprime les marqueurs d'entités faibles et d'agrégats
delete:dfs supprime les entités indépendantes dont tous les attributs sont identifiants (et les DF qui les relient)
drain déplace tout attribut d'association (1,1) vers l'entité appropriée
drown remplace tous les noms d'éléments par un libellé générique numéroté
echo réécrit le texte source tel quel
explode décompose toute association n-aire (*,N) en n associations binaires explode arrange décomposer les non-DF ternaires et plus, puis réarranger
explode:arity=3 arrange idem
explode:weak arrange idem, avec création d'entités faibles
explode:arity=2.5 arrange étendre aux non-DF binaires porteuses d'attributs
explode:arity=2 arrange étendre à toutes les non-DF binaires
fix essaie de corriger les erreurs courantes dans les éléments donnés fix:cards normaliser les cardinalités en 01, 11, 0N et 1N
flip applique au diagramme une symétrie verticale, horizontale ou diagonale flip:v symétrie verticale
flip:h symétrie horizontale
flip:d symétrie selon la seconde diagonale
flip:vhd symétrie selon la première diagonale
flip:dhv idem (ordre indifférent)
grow ajoute des entités et associations aléatoires (par défaut : 10 nouvelles associations) grow arrange ajouter des éléments avec les paramètres par défaut, puis réarranger
grow:n=10 nombre total d'associations à ajouter (défaut)
grow:arity_1=2 nombre d'associations réflexives (défaut)
grow:arity_3=2 nombre d'associations ternaires (défaut)
grow:arity_4=0 nombre d'associations quaternaires (défaut)
grow:doubles=1 nombre d'associations liant deux mêmes entités (défaut)
grow:composite_ids=1 nombre d'identifiants composites (défaut)
grow:ent_attrs=4 nombre maximal d'attributs par entité (défaut)
grow:assoc_attrs=2 nombre maximal d'attributs par association (défaut)
grow:'*1-*N'=3 nombre d'associations *1-*N (défaut)
grow:'01-11'=1 nombre d'associations 01-11 (défaut)
grow:'_11-*N'=1 une entité faible (zéro par défaut)
grow:'/1N-*N'=1 un agrégat (zéro par défaut)
grow:from_scratch arrange à partir d'un MCD vide
grow:grow:n=9,from_scratch,ent_attrs=3 obfuscate:labels=en4 create:roles lower:roles arrange créer un MCD d'entraînement à la conversion en relationnel
lower réécrit les éléments donnés en minuscules lower:attrs,roles attributs et rôles en minuscules
pascal réécrit les élements donnés en PascalCase
prefix préfixe les éléments donnés avec la chaîne donnée prefix:roles='-' force les rôles à remplacer le nom des clés étrangères lors du passage au relationnel
randomize garde la structure, mais randomise les éléments donnés quand c'est possible obfuscate libellés remplacés par du Lorem Ipsum
obfuscate:labels=lorem idem
obfuscate:labels=disparition idem, lexique du roman de Perec
obfuscate:labels=en4 idem, mots anglais de 4 lettres (SFW)
obfuscate:attrs=fr,boxes=fr5 idem, mots français de longueur quelconque pour les attributs, de 5 lettres pour les boîtes
randomize:types types randomisés avec les fréquences de default_datatypes_fr.tsv.
replace réécrit les éléments donnés en appliquant le motif « recherche/remplacement » donné replace:boxes='DIRIGER/RÉPONDRE DE' renomme une boîte
replace:texts='personel/personnel' corrige une faute d'orthographe
replace:replace:texts='_/ ' remplace les tirets bas par des espaces
replace:types='VARCHAR/VARCHAR2' modifie un nom de type
replace:cards=0N/1N remplace toutes les cardinalités 0N par 1N
replace:cards=1N//1N crée des agrégats un peu partout
replace:cards='0/X' replace:cards='11/X1' replace:cards='1N/XN' masque les cardinalités minimales
delete:card_prefixes replace:cards=11/_11 ajoute des marqueurs d'entités faibles
slice réécrit les éléments donnés en n'en gardant qu'une tranche donnée slice:boxes=5:10 de l'indice 5 (inclus) à l'indice 10 (exclu)
slice:boxes=5: supprime les 5 premiers caractères
slice:boxes=:5 ne garde que les 5 premiers caractères
slice:boxes=:-5 supprime les 5 derniers caractères
slice:boxes=: équivalent de echo
slice:boxes= idem
slice:boxes idem
snake réécrit les éléments donnés en snake_case
split décompose toute association n-aire (*,1) en n-1 associations binaires split arrange décomposer, puis réarranger
suffix suffixe les éléments donnés avec la chaîne donnée suffix:boxes=1 Ajoute un suffixe numérique au nom des boîtes en vue de mettre un MCD et sa copie sur le même diagramme.
swapcase réécrit les éléments donnés en inversant la casse de chaque lettre
title réécrit les éléments donnés en mettant la première lettre de chaque mot en majuscule
truncate tronque les éléments donnés à la longueur donnée (par défaut : 64) truncate:boxes=10 tronque les noms des boîtes à 10 caractères
upper réécrit les éléments donnés en majuscules upper:boxes noms des boîtes en majuscules

Réécriture d'éléments donnés¶

Dans l'aide-mémoire, de nombreuses opérations de réécriture sont décrites comme s'appliquant à des « éléments donnés ». Il s'agit de certains ensembles de tokens produits par l'analyse syntaxique. Plus précisément :

  • arrows : flèches de pattes (suffixes < ou > des cardinalités).
  • attrs : libellés des attributs d'entités ou d'associations.
  • boxes : libellés des entités et associations.
  • cards : cardinalités (11, 1N, etc., sans préfixe ni suffixe).
  • card_prefixes : préfixes de cardinalités (_ pour les entités faibles, / pour les agrégats).
  • constraint_notes : messages affichés au survol d'une contrainte.
  • labels : libellés des entités, des associations et des attributs.
  • leg_notes : notes de pattes (rôles ou messages affichés au survol).
  • notes : équivalent de roles + constraint_notes.
  • roles : alias de leg_notes.
  • texts : équivalent de labels + notes.
  • types : types de données.

Fonctionnement de la commande magique¶

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

  • 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. (relisez-les avec la commande magique %load) ;
  • certains des fichiers générés sont affichés dans la sortie de la cellule, d'autres pas, selon les règles suivantes (rw et cv dénotent respectivement une opération de réécriture et de conversion) :
commande tracé
du MCD
résultat des
réécritures
résultats des
conversions
mocodo initial - -
mocodo -t ou mocodo --mld initial - MLD en
Markdown
mocodo -t rw1 rw2 ... final final -
mocodo -t cv1 cv2 ... - - tous
mocodo -t rw1 rw2 ... cv1 cv2 ... final - tous

Ces règles d'affichage par défaut devraient répondre aux besoins les plus courants, mais l'option --select peut prendre le pas :

  • sans arguments, rien n'est affiché ;
  • l'argument mcd affiche le diagramme conceptuel ;
  • l'argument rw (ou un alias de commodité parmi source, text, code, mocodo) affiche le résultat de la dernière réécriture ;
  • l'argument cv (ou un alias de commodité parmi mld, ddl, sql) affiche les résultats des conversions ;
  • ces arguments peuvent être librement combinés et ordonnés ;
  • l'argument all affiche tout ce qui est disponible, dans l'ordre mcd, rw et cv ;

Les conversions génèrent par défaut un fichier-texte. Un dessin s'affichera à la place :

  • pour l'argument diagram ;
  • avec l'option --defer, pour autant qu'un web-service de rendu soit défini pour le fichier en question.

Il est possible de mettre -t en majuscule. Dans ce cas :

  • s'il y a une ou plusieurs opérations de réécriture, le résultat de la dernière réécriture remplace le contenu de la cellule et la sortie est effacée ;
  • sinon, s'il y a une ou plusieurs opérations de conversion et que Pyperclip est installé, le résultat de la dernière conversion est copié dans le presse-papier.

Gabarits de passage au relationnel¶

L'algorithme convertissant la représentation interne d'un schéma relationnel en une représentation externe dans tel ou tel format est totalement découplé dudit format. Cela signifie que vous pouvez modifier ou créer un format sans écrire une seule ligne de code, mais en remplissant une espèce de formulaire, ou gabarit (template en anglais).

Si vous n'avez aucune velléité de le faire ou que vous n'êtes pas ami avec les expressions régulières, vous pouvez sauter cette section. Sinon, accrochez-vous, ça va devenir un peu technique.

Format des gabarits¶

Les gabarits de Mocodo étaient à l'origine écrits en JSON. Par conséquent, un grand nombre des caractères utilisés dans les expressions régulières devaient être échappés, ce qui rendait celles-ci (encore) plus difficiles à écrire, à relire et à tester. La version 4 passe à YAML, qui n'a pas cet inconvénient. Voici par exemple un extrait de gabarit dans l'ancienne syntaxe :

    {
      "order": 400,
      "comment": "Move all foreign keys constraints at the end of the document",
      "search": "(?sm)(CREATE TABLE ([^\n]+) \\(\n(?:[^\n]+\n)*)  (FOREIGN KEY[^\n]+),\n(.*)",
      "replace": "\\1\\4\nALTER TABLE \\2 ADD \\3;",
      "iterated": true
    },

... et le même dans la nouvelle :

  - order: 400
    comment: 'Move all foreign keys constraints at the end of the document'
    search: '(?sm)(CREATE TABLE ([^\n]+) \(\n(?:[^\n]+\n)*)  (FOREIGN KEY[^\n]+),\n(.*)'
    replace: '\1\4\nALTER TABLE \2 ADD \3;'
    iterated: true

Si vous avez écrit vos propres gabarits JSON, vous pouvez les convertir automatiquement en YAML à l'aide du script json_to_yaml_templates.py fourni dans le répertoire dev.

Remarque. Si les gabarits de Mocodo constituent des fichiers YAML valides, l'inverse n'est pas forcément vrai. Mocodo utilise un sous-ensemble sain de YAML adapté à ses besoins. Il a son propre parser avec les particularités suivantes :

  • Un gabarit est un dictionnaire dont les valeurs sont :
    • soit des types scalaires (chaînes, nombres, booléens, null) ;
    • soit des listes de dictionnaires à valeurs scalaires.
  • Toute valeur chaîne doit être délimitée par des simples quotes ('). Les quotes internes sont échappées en les doublant ('').
  • Les expressions régulières de recherche et de remplacement suivent les mêmes règles d'échappement que les r-strings de Python.
  • Les autres chaînes (notamment les chaînes de composition) ne demandent pas à échapper les anti-slashes, mais à doubler les accolades (règles des fr-strings). Exception : pour les distinguer du retour-chariot et de la tabulation, il faudra échapper les \n et les \t si on veut les laisser littéralement. Vous en avez un exemple pour \newcommand et \title dans le boilerplate du gabarit pour LATEX.

Dérivation de gabarits¶

Depuis la version 3.1, il est possible de définir un gabarit dérivé d'un autre (qui lui-même peut dériver d'un autre, etc.). Dans le but de réduire les redondances et de faciliter les tests et la maintenance, la version 4.0 fait un usage intensif de cette fonctionnalité :

In [188]:
display.SVG("../../mocodo/resources/relation_templates/_graph.svg")
Out[188]:
No description has been provided for this image

Les teintes les plus foncées correspondent approximativement aux gabarits les plus complexes. Les autres ne sont souvent que des alias, par exemple, tex.yaml renvoie directement à latex.yaml :

In [189]:
display.Code("../../mocodo/resources/relation_templates/tex.yaml")
Out[189]:
parent: 'latex'

La clé "parent" donne le chemin ou le nom du gabarit dont on souhaite créer une version dérivée :

  • une chaîne terminée par .yaml est interprétée comme un chemin ;
  • sinon, comme le nom d'un gabarit de la distribution.

Tous les gabarits textuels (text.yaml, latex.yaml, markdown.yaml, html.yaml et leurs alias) dérivent des gabarits html-c.yaml (version avec affichage des contraintes) et html-ce.yaml (version avec affichage des contraintes et des explications).

Par exemple, le gabarit latex se borne à ajouter un message d'aide pour la ligne de commande et à empêcher l'ajout des contraintes d'unicité et d'optionalité :

In [190]:
display.Code("../../mocodo/resources/relation_templates/latex.yaml")
Out[190]:
help_en: 'convert the conceptual model into a relational schema in LaTeX format'
help_fr: 'convertit le modèle conceptuel en un schéma relationnel au format LaTeX'
help_zh: '将概念模型转换为 LaTeX 格式的关系模式'
fr_examples:
  - order: 1
    example: 'latex'
    explanation: 'version de base'
  - order: 2
    example: 'latex:b'
    explanation: 'avec _boilerplate_'
  - order: 3
    example: 'latex:c'
    explanation: 'avec contraintes d''unicité et d''optionalité'
  - order: 4
    example: 'latex:e'
    explanation: 'avec explications'
  - order: 5
    example: 'latex:bce'
    explanation: 'avec _boilerplate_, contraintes et explications'
parent: 'latex-c'
add_unicity_constraints:
add_optionality_constraints:

Si maintenant on regarde le contenu de son parent latex-c :

In [191]:
display.Code("../../mocodo/resources/relation_templates/latex-c.yaml")
Out[191]:
parent: 'html-c'
extension: 'tex'
highlight: 'latex'
column_separator: ', '
compose_relation: '  \item \relat{{{this_relation_name}}} ({columns})'
compose_relational_schema: '% Generated by Mocodo {version}\n\n\begin{{itemize}}\n{relations}\n\end{{itemize}}\n'
transform_relation:
  - order: 1000
    comment: 'Compose normal attributes'
    search: '<span class=''normal''>(.+?)</span>'
    replace: '\\attr{\1}'
  - order: 1100
    comment: 'Compose primary keys'
    search: '<span class=''primary''>(.+?)</span>'
    replace: '\\prim{\1}'
  - order: 1200
    comment: 'Compose foreign primary keys'
    search: '<span class=''foreign primary''>#(.+?)</span>'
    replace: '\\foreign{\\prim{\1}}'
  - order: 1300
    comment: 'Compose foreign attributes'
    search: '<span class=''foreign''>#(.+?)</span>'
    replace: '\\foreign{\1}'
  - order: 1400
    comment: 'Exponents'
    search: '(<sup>.*u)(\d)(.*</sup>)'
    replace: '\1_\2\3'
    iterated: true
  - order: 1500
    comment: 'Exponents'
    search: ' <sup>(.+?)</sup>'
    replace: '$^{\1}$'
  - order: 1600
    comment: 'Escape underlines'
    search: '_'
    replace: '\_'

... on voit que les opérations consistent simplement à modifier le séparateur de colonne, à composer les tables et le schéma relationnel complet avec un boilerplate, et enfin à remplacer les balises HTML par leur équivalent en LATEX. Toute la logique complexe est traitée dans le gabarit html-c.

Exemples de création de gabarit dérivé ¶

Le gabarit SQL par défaut rend explicite la contrainte NOT NULL des clés primaires :

In [192]:
%%mocodo -t sql
PERSONNE: id. personne [VARCHAR(8)], nom [VARCHAR(255)]

sandbox_ddl.sql
CREATE TABLE PERSONNE (
  PRIMARY KEY (id_personne),
  id_personne VARCHAR(8) NOT NULL,
  nom         VARCHAR(255)
);

Supposons que cette redondance nous défrise, et voyons comment l'éliminer. Pour cela, examinons le contenu du gabarit sql.yaml :

La contrainte d'optionalité {optionality} apparaît à côté de PRIMARY KEY en lignes 28 et 31. Nous pouvons donc simplement remplacer les valeurs associées à compose_primary_key et compose_primary_foreign_key par des copies supprimant cette mention :

In [193]:
%%file new_sql.yaml
parent: 'sql'
compose_primary_key: '{label} {datatype}\nPRIMARY KEY ({label})'
compose_primary_foreign_key: '{label} {datatype}\nPRIMARY KEY ({label})\nFOREIGN KEY ({label}) REFERENCES {outer_source} ({non_disambiguated_label})'
Overwriting new_sql.yaml

Pour tester ce nouveau gabarit, nous devons ajouter la sous-option -t relation avec en sous-argument le chemin complet du fichier créé :

In [194]:
%mocodo -i sandbox -t relation:new_sql.yaml

sandbox_ddl.sql
CREATE TABLE PERSONNE (
  PRIMARY KEY (id_personne),
  id_personne VARCHAR(8),
  nom         VARCHAR(255)
);

Mission accomplie !

Nous aurions pu procéder autrement. Reprenons le gabarit original :

Le dictionnaire transform_relation spécifie une séquence de réécritures à appliquer à chacune des clauses CREATE TABLE (composées ligne 37). La première accumule toutes les lignes contenant PRIMARY KEY en fin de table (où elles seront concaténées avant d'être ramenées au début). Nous devons donc intervenir avant que NOT NULL ne soit séparé de PRIMARY KEY. Pour cela, définissons un gabarit qui se borne à insérer avant cette transformation (de numéro d'ordre 100) une suppression des NOT NULL incriminés :

In [195]:
%%file new_sql.yaml
parent: 'sql'
transform_relation:
  - order: 50
    comment: 'Suppress PK NN redundancy.'
    search: ' NOT NULL\nPRIMARY KEY'
    replace: '\nPRIMARY KEY'
Overwriting new_sql.yaml

Le résultat est le même :

In [196]:
%mocodo -i sandbox -t relation:new_sql.yaml

sandbox_ddl.sql
CREATE TABLE PERSONNE (
  PRIMARY KEY (id_personne),
  id_personne VARCHAR(8),
  nom         VARCHAR(255)
);

NB. Les gabarits définis par l'utilisateur n'ont pas vocation à être placés dans le répertoire relation_templates de la distribution. Votre nouveau gabarit new_sql ne peut donc pas être invoqué aussi simplement que les gabarits officiels (i.e., avec -t new_sql). Si vous faites une modification ou un ajout que vous voulez voir inclus dans la distribution, n'hésitez pas à faire une PR.

Mécanisme de mise à jour¶

Le mécanisme de mise à jour des clés dépend de la scalarité de leur valeur associée.

Cas scalaire.

Pour les valeurs scalaires (chaînes, nombres, booléens, null), selon la présence d'une entrée donnée dans le gabarit enfant et/ou le gabarit parent, l'association clé-valeur correspondante sera créée, mise à jour ou conservée :

enfant parent résultat
oui non création
oui oui mise à jour
non oui conservation

Il n'y a pas de moyen de supprimer une association clé-valeur, mais étant donné que toutes celles qui sont absentes se voient substituer une association par défaut, il est équivalent de spécifier explicitement la valeur-défaut.

Cas non scalaire.

Dans les gabarits de relations de Mocodo, une seule catégorie de valeur non scalaire est possible : la liste de dictionnaires. Dans l'exemple précédent, c'est le cas de transform_relation.

Une clé "order" est systématiquement présente dans chacun des dictionnaires de la liste. Selon la présence d'un dictionnaire de numéro d'ordre donné dans le gabarit enfant et/ou le gabarit parent, ce dictionnaire sera inséré, supprimé, mis à jour ou conservé :

enfant parent résultat
oui non insertion
oui oui si les clés sont parmi {"order", "comment"} : suppression
s'il y a plusieurs clés : mise à jour
non oui conservation

Nouveauté de la version 4.0. Si une clé d'un gabarit enfant est associée à une liste vide, cette association remplace l'éventuelle association existante.

Remarque. Les numéros d'ordre utilisés dans les dictionnaires sont des multiples de 100. Si vous voulez créer des gabarits dérivés, évitez par précaution les multiples de 10 : cela augmentera les chances que votre gabarit survive à une mise à jour de l'un de ses ancêtres. Vous pouvez aussi partir d'une copie de ceux-ci, sachant que vous renoncez alors aux bénéfices de leurs éventuelles mises à jour.

Annexe C : Crédits¶

  • Auteur
    • Aristide Grange, Université de Lorraine, Metz, LCOMS.
  • Administration système
    • Cyril Minette.
  • Outils
    • Aspect visuel
      • Color Brewer (Cynthia Brewer).
      • Real Favicon Generator (Philippe Bernard).
      • reset.css (Eric Meyer).
    • JavaScript
      • JQuery (John Resig).
      • JS-Cookie (Klaus Hartl).
      • Ace Editor (Cloud9 IDE et Mozilla).
    • Python
      • Distance de Damerau-Levenshtein (Michael Homer).
      • Lark Parser (Erez Shinan).
      • CairoSVG (CourtBouillon).
      • Pyperclip (Al Sweigart).
    • Services de rendu
      • Kroki.io (Guillaume Grossetie).
      • QR Code Generator (Foundata GmbH).
  • Divers
    • Modern SQL (Markus Winand).
    • DBML (Holistics).
    • D2 (Terrastruct).
    • Basthon (Romain Casati).