<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 # Table des matières
- 1. Introduction
- 2. Installation du programme
  - 2.1. Installation complète (recommandé)
  - 2.2. Vérification
  - 2.3. Installation minimale
- 3. Utilisation
  - 3.1. Utiliser Mocodo online
  - 3.2. Utiliser Mocodo en ligne de commande
    - 3.2.1. Au plus simple
    - 3.2.2. Liste des arguments
      - 3.2.2.1. Options sur Mocodo lui-même
      - 3.2.2.2. Entrée-sortie
      - 3.2.2.3. Aspect de la sortie graphique
      - 3.2.2.4. Sortie relationnelle
      - 3.2.2.5. Modifications du texte d'entrée
      - 3.2.2.6. Réarrangement par séparation et évaluation
      - 3.2.2.7. Réarrangement par algorithme génétique
      - 3.2.2.8. Réarrangement par résolution d'un programme linéaire
      - 3.2.2.9. Options spécifiques aux Notebooks
    - 3.2.3. Paramétrage à long terme
  - 3.3. Utiliser Mocodo sous Jupyter Notebook
    - 3.3.1. Invocation
    - 3.3.2. Principes de fonctionnement
    - 3.3.3. Exemples d'invocation
    - 3.3.4. Modification in situ d'une cellule
    - 3.3.5. Paramétrage à long terme
- 4. Description d'un MCD
  - 4.1. Besoins élémentaires
    - 4.1.1. Entités, associations, attributs, identifiants, cardinalités
    - 4.1.2. Dépendances fonctionnelles
    - 4.1.3. Associations réflexives
    - 4.1.4. Placement sur plusieurs rangées
  - 4.2. Besoins plus avancés
    - 4.2.1. Identifiants multiples
    - 4.2.2. Entités faibles (identification relative)
    - 4.2.3. Flèches sur les pattes
    - 4.2.4. Styles
    - 4.2.5. Types de données
    - 4.2.6. Format des cardinalités
    - 4.2.7. Rectification automatique des cardinalités mal formées
    - 4.2.8. Symbole de dépendance fonctionnelle
    - 4.2.9. Créer plusieurs entités ou associations de même nom
  - 4.3. Besoins spécifiques à la pédagogie
    - 4.3.1. Créer une vue en extension
    - 4.3.2. Afficher l'explication des cardinalités
    - 4.3.3. Créer un MCD à compléter
      - 4.3.3.1. Supprimer le marquage d'un identifiant
      - 4.3.3.2. Masquer un couple de cardinalités
      - 4.3.3.3. Masquer un attribut
      - 4.3.3.4. Ne faire apparaître que le squelette du schéma conceptuel
    - 4.3.4. Obfuscation
Step1:  L'appel ci-dessus a également construit le dictionnaire des données
Step2:  Num. classe
Num. salle
Vol. horaire
Code catégorie
Nom catégorie
Num. élève
Nom élève
Note
Num. prof
Nom prof
Date
Libellé matière
Ainsi que le diagramme relationnel, qui peut être visualisé par un nouvel appel
Step3:  La devise de Mocodo, « nickel, ni souris », en résume les principaux points forts
Step4:  Pour charger automatiquement mocodo_magic à chaque ouverture d'un notebook (ce qui dispense d'évaluer %load_ext mocodo_magic) 
Step5:  ... remplacerait celle-ci par celle-là
Step6:  3.3.5. Paramétrage à long terme <a id='magic_long_term_settings'></a>
Si vous voulez éviter de préciser à chaque fois les mêmes arguments (par exemple un changement de couleurs), vous pouvez placer un fichier params.json dans le répertoire mocodo_notebook. Mocodo peut même vous aider à le faire en exécutant la cellule suivante
Step8:  Son évaluation remplace son propre contenu par des lignes de code similaires à
Step9:  Modifiez la variable params à votre gré en respectant la syntaxe JSON (attention en particulier au dernier couple clef-valeur, qui n'est pas terminé par une virgule). Exécutez la cellule pour créer un fichier de nom et emplacement adéquats (notez que la valeur de --print_params a été passée à false pour vous éviter de le faire à la main).
4. Description d'un MCD <a id='erd_description'></a>
4.1. Besoins élémentaires <a id='elementary_needs'></a>
4.1.1. Entités, associations, attributs, identifiants, cardinalités <a id='elements'></a>
Step10:  La syntaxe ne devrait pas poser problème
Step11:  Si on a plusieurs dépendances fonctionnelles à représenter, on devra suffixer le DF par un numéro (cf. cet exemple).
4.1.3. Associations réflexives <a id='reflexives_associations'></a>
Step12:  4.1.4. Placement sur plusieurs rangées <a id='placement_sur_plusieurs_rangees'></a>
L'ordre et la séparation des lignes de la description permet de spécifier à coût zéro un plongement grossier, mais qui s'avère en général suffisant
Step13:  Les boîtes sont placées aux intersections d'une grille invisible assurant que leurs centres soient alignés aussi bien horizontalement que verticalement. C'est ce qui en général est le plus satisfaisant esthétiquement, mais d'autres retouches peuvent être opérées manuellement dans le fichier de sortie.
Le plongement fait l'objet d'une « compression » horizontale et verticale. Par exemple, ci-dessus, il y a un espace horizontal négatif entre le bord droit de l'entité de gauche et le bord gauche de l'entité de droite.
4.2. Besoins plus avancés <a id='besoins_plus_avances'></a>
4.2.1. Identifiants multiples <a id='identifiants_multiples'></a>
Préfixer d'un caractère de soulignement (_) le(s) second, troisième, etc. attributs pour les ajouter à l'identifiant.
Step14:  4.2.2. Entités faibles (identification relative) <a id='entites_faibles'></a>
Préfixer d'un caractère de soulignement (_) une cardinalité (1,1) pour indiquer que l'entité distinguée est faible. Dans le diagramme, les identifiants (ou discriminants) d'une telle entité seront soulignés en pointillés, tandis que le (1,1) sera souligné d'un trait plein.
Step15:  Nouveauté de la version 2.1. Traditionnellement, l'identification relative est dénotée par des parenthèses autour des cardinalités. Cette notation (ou toute autre) peut maintenant être obtenue avec l'option --strenghten_card
Step16:  Une association ne peut renforcer plus d'une entité faible. Ainsi, une erreur se produit si l'on remplace le 1N par _11
Step17:  4.2.3. Flèches sur les pattes <a id='fleches_sur_les_pattes'></a>
Suffixer d'un chevron (&lt; ou &gt;) 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é.
Step18:  La position de la flèche sur la patte peut être réglée individuellement dans la table d'association ratio du script Python généré (par défaut, sandbox_svg.py ou sandbox_nodebox.py) ou sous l'onglet Retouches de la version en ligne. La valeur correspondante peut varier de 0.0 (flèche cachée sous la boîte d'origine) à 1.0 (par défaut, pointe de la flèche au contact du bord de la boîte de destination, compte non tenu de l'arrondi s'il s'agit d'une association).
4.2.4. Styles <a id='styles'></a>
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). Une changement d'échelle d'un facteur multiplicatif positif peut être précisé avec l'argument --scale.
Vous pouvez bien sûr créer vos propres styles en vous inspirant des fichiers fournis. Si vous êtes particulièrement content d'un style, soumettez-le pour inclusion dans une prochaine distribution.
4.2.5. Types de données <a id='types_de_donnees'></a>
Chaque attribut peut être assorti d'annotations entre crochets. Ignorées au niveau du tracé du MCD, elles sont interprétées comme des types de données lors de la génération d'un code-source SQL.
4.2.6. Format des cardinalités <a id='card_format'></a>
Par défaut, les cardinalités sont séparées par une virgule.
Nouveauté de la version 2.1. On peut maintenant opter pour un format quelconque
Step19:  4.2.7. Rectification automatique des cardinalités mal formées <a id='rectification_automatique_des_cardinalites_mal_formees'></a>
Certaines fautes de frappe fréquentes (inversion des cardinalités minimale et maximale, lettre « O » au lieu du chiffre « 0 ») sont silencieusement rectifiées
Step20:  4.2.8. Symbole de dépendance fonctionnelle <a id='df_symbol'></a>
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
Step21:  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 le dictionnaire de shapes
Step22:  Ajouter une autre entité DATE (sous le nom de DATE2) permettra à Mocodo de calculer une mise en page à la fois plus agréable à l'œil et plus compacte ($4\times3$ au lieu de $5\times4$). La sémantique est inchangée.
Step23:  4.3. Besoins spécifiques à la pédagogie <a id='besoins_specifiques_a_la_pedagogie'></a>
Si vous n'êtes pas enseignant de bases de données, vous pouvez passer directement à la section suivante.
4.3.1. Créer une vue en extension <a id='creer_une_vue_en_extension'></a>
La technique de duplication que l'on vient de voir 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)
Step24:  4.3.2. Afficher l'explication des cardinalités <a id='leg_annotation_description'></a>
Les débutants ont souvent des doutes sur la sémantique de telle ou telle cardinalité. Cette information peut désormais être incluse dans le texte-source, en annotant les pattes correspondantes, pour apparaître à la demande lors du rendu (utile pour créer des exercices à faire en TD ou en autonomie).
Survolez les cardinalités du MCD ci-dessous pour faire apparaître leur description.
Step25:  Les annotations s'insèrent entre cardinalités et nom de l'entité. Elles sont délimitées par des crochets droits.
Avec l'option --disambiguation=annotations (par défaut), elles sont également exploitables lors du passage au relationnel pour préciser la sémantique d'une clef étrangère.
L'affichage est désactivé avec l'option --hide_annotations.
Limitations.
Ne fonctionne pas sous Inkscape.
Ne semble pas fonctionner dans une page HTML statique (comme la version HTML de ce document sous GitHub).
Semble nécessiter une réévaluation de la cellule pour fonctionner dans un notebook fermé, puis rouvert.
Sans effet sur le diagramme conceptuel généré avec l'option --image_format=nodebox.
4.3.3. Créer un MCD à compléter <a id='creer_un_mcd_a_completer'></a>
Les MCD à trous sont des exercices classiques d'introduction aux bases de données.
4.3.3.1. Supprimer le marquage d'un identifiant <a id='supprimer_le_marquage_d_un_identifiant'></a>
Pour éviter le marquage automatique du premier attribut d'une entité comme identifiant, il suffit de le préfixer par un _ (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).
Step26:  4.3.3.2. Masquer un couple de cardinalités <a id='masquer_un_couple_de_cardinalites'></a>
Vous pouvez masquer n'importe quelles cardinalités en les remplaçant pas XX (ci-dessous à gauche) 
Step27:  4.3.3.3. Masquer un attribut <a id='masquer_un_attribut'></a>
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.
Step28:  4.3.3.4. Ne faire apparaître que le squelette du schéma conceptuel <a id='mcd_skeleton'></a>
Enfin, vous pouvez transformer en exercice à trous n'importe quel MCD en rendant complètement transparentes les couleurs des attributs, associations et cardinalités. Le style blank a été prédéfini à cet effet
Step29:  Attention, n'utilisez pas cette méthode si vous souhaitez diffuser l'exercice sous forme électronique
Step30:  4.3.4. Obfuscation
Step31:  Nouveauté de la version 2.0.20. Pour remplacer le texte de la cellule par le résultat de son évaluation, ajoutez l'option --replace.
En argument, vous pouvez ajouter le chemin d'un fichier texte UTF-8 quelconque où puiser les mots de substitution. Par exemple, le texte même de cette documentation
Step32:  Mocodo essaie d'abord de trouver ce fichier à l'endroit indiqué. En cas d'échec, il le cherche (avec extension .txt facultative) parmi les textes distribués avec le logiciel, à savoir
Step33:  L'algorithme a écarté les mots dish (confusion possible avec wash), folk (confusion possible avec milk), peer (confusion possible avec ever), hall (confusion possible avec haul), baby (confusion possible avec lady).
5. Tracé d'un MCD <a id='MCD_drawing'></a>
5.1. Insertion manuelle d'espacements <a id='insertion_manuelle_d_espacements'></a>
Le tracé réalisé par Mocodo pour des MCD de plusieurs rangées laisse parfois à désirer 
Step34:  On voit que, par défaut, Mocodo centre les rangées qui contiennent moins de boîtes que les autres. Cela donne un bon résultat pour la première rangée, mais pas pour la troisième.
L'utilisateur peut cependant spécifier les espacements qu'il désire en complétant les rangées les moins fournies, par des boîtes invisibles dont le seul rôle est de « pousser » les autres à l'emplacement voulu. Ainsi, il va préciser que l'association Curae doit commencer sur la troisième colonne en insérant des lignes réduites au caractère deux-points, et en profiter pour insérer un espace entre Lorem et Tellus 
Step35:  Il est possible de « compresser » les suites de deux-points en supprimant les retours-chariots, autrement dit, de remplacer $n$ lignes réduites à deux-points par une ligne réduite à une séquence de $n$ deux-points. Ce raccourci est illustré dans le prochain exemple.
5.2. Ajustement automatique dans une grille minimale <a id='reformatage_automatique'></a>
Nouveauté de la version 2.2. On cherche en général à faire tenir le MCD dans la plus petite grille possible, tout en maintenant un rapport « équilibré » entre hauteur et largeur. Par exemple, un MCD de 13 boîtes (entités ou associations) peut tenir dans les grilles
Step36:  L'algorithme se contente de supprimer ou d'insérer des sauts de ligne dans le texte-source, sans modifier l'ordre des clauses. On devra donc encore en général opérer sur le résultat un réarrangement automatique (voir plus loin).
Step37:  Si ce réarrangement échoue ou laisse à désirer, il est possible de spécifier chacune des ièmes grilles suivantes avec l'option --fit=i
Step38:  Remarques.
- Quand le paramètre de --fit définit une grille trop grande, le réarrangement automatique retombe fréquemment sur une sous-grille de celle-ci.
- Dans Mocodo online, cliquer sur le bouton de réarrangement automatique enchaîne directement les opérations --fit et --arrange.
5.3. Basculement des cardinalités et inflexion des pattes rectilignes <a id='inflexion'></a>
Step39:  Nouveauté de la version 2.1. Mocodo est capable de détecter certaines configurations de pattes dont les cardinalités présentent un risque élevé de collision. Il procède alors à deux types d'ajustements
Step40:  Si on ouvre le script intermédiaire avec un éditeur de texte, on verra que ses premières instructions exposent les principaux paramètres de position
Step41:  Sous Nodebox, il suffit alors de choisir Run dans le menu Python.
Si vous travaillez avec des fichiers SVG, il faut exécuter le script ..._svg.py. Il regénère alors le fichier SVG qui contient le dessin. Il ne reste plus qu'à l'ouvrir, par exemple avec un navigateur.
Les lignes suivantes (qu'il est inutile de comprendre) permettent de faire la même chose à l'intérieur de cette documentation.
Step42:  Selon le même principe, on peut faire glisser les flèches le long des arcs (dictionnaire ratio) ou modifier les couleurs (dictionnaire colors).
Cette technique inhabituelle nous semble une application naturelle du dynamisme du langage Python. Mais c'est à vous de décider si vous êtes plus efficace en ajustant des valeurs numériques, ou en faisant glisser des objets dans votre cliquodrome favori, comme décrit dans la section suivante.
5.4.2. Par édition de la sortie au format SVG <a id='par_edition_de_la_sortie_au_format_svg'></a>
Un fichier SVG peut être visualisé dans tout navigateur moderne.
Pour aller au-delà de la simple visualisation, il faudra faire appel à un logiciel de dessin vectoriel dédié, comme Inkscape (libre) ou Adobe Illustrator, Freehand, CorelDRAW, etc.
Les éléments du fichier SVG produit pourront alors être repositionnés à la souris. Certains sont associés, pour permettre leur déplacement en bloc. Dans la version actuelle, les liens ne suivent pas ces déplacements, ce qui peut obliger à des manipulations supplémentaires.
5.5. Réarrangement par symétrie <a id='rearrangement_par_symetrie'></a>
Mocodo permet de calculer facilement le symétrique d'un MCD, par exemple celui donné ci-dessous
Step43:  Nouveauté de la version 2.0.20. Pour remplacer le texte de la cellule par le résultat de son évaluation, ajoutez l'option --replace.
5.5.1. Symétrie selon l'axe vertical <a id='symetrie_selon_l_axe_vertical'></a>
Step44:  5.5.2. Symétrie selon l'axe horizontal <a id='symetrie_selon_l_axe_horizontal'></a>
Step45:  5.5.3. Symétries selon les diagonales (transposition) <a id='symetries_selon_les_diagonales_transposition'></a>
Step46:  Pour une symétrie selon l'anti-diagonale, appliquer successivement les trois symétries précédentes dans n'importe quel ordre.
5.5.3.1. Astuce
Step47:  On commence par transposer
Step48:  Il suffit alors d'insérer un deux-points au début de chacune des trois premières rangées, puis de retransposer dans l'autre sens
Step49:  On peut se convaincre en examinant le nouveau texte d'entrée que le résultat aurait été beaucoup plus pénible à obtenir en procédant directement.
5.6. Réarrangement automatique <a id='rearrangement_automatique'></a>
Il est possible de demander à Mocodo de chercher tout seul une « bonne » permutation des boîtes, ce qui à la main deviendrait vite difficile.
Le critère que nous avons retenu pour évaluer la qualité d'une permutation est double
Step50:  Le réarrangement automatique se fera toujours à l'intérieur d'une grille ayant autant de colonnes et de rangées que le texte de départ (ici, $4\times5$). On peut quelquefois essayer de réduire cette grille. Par exemple, le MCD ci-dessus comporte 13 boîtes. Elles pourraient donc théoriquement tenir dans une grille $5\times3=15$. Modifions le texte à la main pour avoir 3 blocs d'au plus 5 lignes, et vérifier qu'un tel réarrangement est possible
Step51:  5.6.1.2. Par croissance organique <a id='organic'></a>
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.
Step52:  Cela donne un autre plongement du MCD sur une grille $4\times5$, ce qui comme on l'a vu n'est pas optimal. En fait, le résultat d'une réorganisation organique peut souvent être trivialement amélioré, par exemple ici en faisant pivoter Augue et en décalant DF
Step53:  De fait, le réarrangement organique fournit souvent un bon point de départ pour chercher soi-même une permutation plus esthétique ou mettant en évidence certaines propriétés du MCD.
#### Limitations
Pour permettre au programme de rendre plus rapidement de bonnes solutions, on a borné arbitrairement le nombre d'appels à la fonction chargée de construire une permutation à partir du placement de la première boîte. De ce fait, l'algorithme n'est plus exact, en ce sens que la meilleure solution peut occasionnellement lui échapper. Si vous soupçonnez que c'est le cas, faites un autre essai, éventuellement en augmentant la borne (par défaut 10000)
Step54:  Son réarrangement échoue donc
Step55:  5.6.2. Méthode heuristique <a id='methode_heuristique'></a>
Dans tous ces cas, on pourra se rabattre sur l'heuristique. Celle-ci, au lieu d'interdire les croisements, cherche simplement à en minimiser le nombre.
Step56:  L'amélioration ne saute pas forcément aux yeux, mais il n'y a plus que 3 croisements au lieu de 9. Ce plongement constitue en tout cas un bon point de départ pour un réarrangement manuel. Pour arriver à une représentation lisible, il ne reste plus qu'à insérer quelques boîtes invisibles
Step57:  5.6.3. Méthode exacte générique <a id='methode_exacte_generique'></a>
Nouveauté de la version 2.2. Cette méthode, invoquée avec le paramètre arrange=lp, trouvera nécessairement l'une des meilleures solutions, pour peu que celle-ci existe et que vous ayez du temps devant vous.
L'idée est de convertir le problème en programme linaire, de l'envoyer à un solveur externe, et de récupérer le résultat à la fin.
Actuellement, le solveur peut être CPLEX
Step58:  ... Ou Gurobi
Step59:  Remarques.
Ces résultats, même s'ils semblent différents, sont exactement équivalents en termes de longueur cumulée des liens.
Les deux solveurs sont des logiciels commerciaux, qui ne sont donc pas livrés avec Mocodo. Toutefois, si vous êtes étudiant ou chercheur en université, vous pouvez faire une demande de licence académique gratuite auprès de leurs éditeurs respectifs.
Actuellement, le temps de résolution par solveur générique est souvent rédhibitoire. L'option n'a été introduite qu'à des fins de recherche, et ne présente pas d'intérêt pratique pour l'utilisateur final.
5.7. Conversion dans d'autres formats graphiques <a id='conversion_dans_d_autres_formats_graphiques'></a>
L'exportation est déléguée à votre éditeur SVG ou à Nodebox. Le format PDF assure la meilleure qualité, aussi bien pour la visualisation sur écran, que pour la projection ou l'impression. Si vous devez absolument utiliser un format bitmap, préférez PNG ou GIF.
6. Passage au relationnel <a id='passage_au_relationnel'></a>
Le passage au relationnel se fait en deux étapes
Step60:  Notez la désambiguïsation automatique par numérotation du deuxième attribut de BIBENDUM.
6.1.1.2. Exemple du traitement des associations DF <a id='exemple_du_traitement_des_associations_df'></a>
Illustrons l'autre cas sur un MCD quasiment identique, à ceci près que certaines cardinalités maximales ont été ramenées à 1. En tant que dépendances fonctionnelles, toutes les associations vont alors disparaître.
Step61:  Notez les points suivants
Step62:  Dans ce joli exemple dû à Idris NEUMANN, Initiation à la conception de bases de données relationnelles avec MERISE, les renforcements successifs aboutissent à faire entrer l'identifiant de RUE dans celui de APPARTEMENT, alors même que ces entités sont séparées par non moins de trois associations.
Ce processus apparaît clairement sur le diagramme relationnel généré par la commande précédente
Step63:  6.1.1.4. Rétablissement explicite de la sémantique des DF disparues <a id='retablissement_semantique_df'></a>
Mocodo permet de modifier légèrement le nom d'une clef étrangère, de façon à réintroduire la sémantique perdue lors de la disparition de l'association de dépendance fonctionnelle par laquelle elle a migré.
Step64:  Par exemple, ci-dessus, la conversion en relationnel produit dans la relation ÉTUDIANT des clefs étrangères date et date.1 qui ne peuvent être laissées en l'état. Éventuellement, on peut souhaiter expliciter la présence d'un numéro d'enseignant dans ÉTUDIANT.
Dans les deux cas, il suffit d'employer le système d'annotation de pattes introduit plus haut
Step65:  De façon moins cruciale, la technique s'applique aussi aux autres types d'association
Step66:  Pour désactiver cette fonctionnalité (notamment dans le cas où vous annotez chaque cardinalité d'une explication destinée aux novices), passez l'option --disambiguation=numbers_only.
6.1.2. Cas irréguliers <a id='cas_irreguliers'></a>
Les règles de gestion peuvent parfois conduire à remettre en cause l'application mécanique de l'algorithme de conversion. Mocodo est capable de traiter certaines exceptions, pourvu qu'elles lui soient indiquées.
6.1.2.1. Réduire une clef primaire <a id='reduire_une_clef_primaire'></a>
Il arrive qu'un sous-ensemble strict de l'ensemble des identifiants des entités mises en jeu dans une association dont toutes les pattes portent la cardinalité N, suffise à constituer la clef primaire de la table issue de cette association
Step67:  La barre oblique de EROS n'apparaît pas dans le MCD, mais conduit à la réduction de la clef primaire de LIGULA aux seuls identifiants des deux autres entités mises en jeu.
6.1.2.2. Minimiser le nombre de champs vides <a id='minimiser_le_nombre_de_champs_vides'></a>
On a vu qu'en l'absence d'une cardinalité (1,1), Mocodo traitait par défaut la cardinalité (0,1) comme une dépendance fonctionnelle. Or, lorsque le 0 est grand devant le 1 en termes de fréquence d'apparition, la plupart des occurrences de la clef étrangère ainsi constituée restent vides. On aura alors intérêt à forcer la conversion de l'association en table. Cela se fait en préfixant d'une barre oblique l'une au moins des entités non distinguées par le (0,1).
Step68:  6.2. Construction de représentations externes <a id='external_representations'></a>
La représentation interne peut être dérivée en représentation externe par l'application d'une spécification de format, ou gabarit (template en anglais). Les schémas relationnels affichés au-dessous des diagrammes conceptuels dans la présente section sont un exemple de sortie au format HTML.
6.2.1. Gabarits inclus dans la distribution <a id='gabarits_inclus_dans_la_distribution'></a>
6.2.1.1. Formats linéaires <a id='linear_formats'></a>
Dans sa représentation la plus compacte, un schéma relationnel s'écrit comme une suite de lignes de la forme
Step69:  ```
% Copy this before \begin{document}
\usepackage[normalem]{ulem}
\newenvironment{mld}
  {\par\begin{minipage}{\linewidth}\begin{tabular}{rp{0.7\linewidth}}}
  {\end{tabular}\end{minipage}\par}
\newcommand{\relat}[1]{\textsc{#1}}
\newcommand{\attr}[1]{\emph{#1}}
\newcommand{\prim}[1]{\uline{#1}}
\newcommand{\foreign}[1]{#\textsl{#1}}
% Copy that after \begin{document}
\begin{mld}
  Client & (\prim{Réf. client}, \attr{Nom}, \attr{Prénom}, \attr{Adresse})\
  Commande & (\prim{Num commande}, \attr{Date}, \attr{Montant}, \foreign{Réf. client})\
  Inclure & (\foreign{\prim{Num commande}}, \foreign{\prim{Réf. produit}}, \attr{Quantité})\
  Produit & (\prim{Réf. produit}, \attr{Libellé}, \attr{Prix unitaire})\
\end{mld}
```
Les formats linéaires actuellement pris en charge par Mocodo sont les suivants
Step70:  CLIENT (<u>Réf. client</u>, Nom, Prénom, Adresse)
- Le champ Réf. client constitue la clef 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 (<u>Num commande</u>, Date, Montant, Réf. client)
- Le champ Num commande constitue la clef 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 clef étrangère. Il a migré à partir de l'entité CLIENT par l'association de dépendance fonctionnelle DF en perdant son caractère identifiant.  
INCLURE (<u>Num commande</u>, <u>Réf. produit</u>, Quantité)
- Le champ Num commande fait partie de la clef primaire de la table. C'est une clef étrangère qui a migré directement à partir de l'entité COMMANDE.
- Le champ Réf. produit fait partie de la clef primaire de la table. C'est une clef é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 (<u>Réf. produit</u>, Libellé, Prix unitaire)
- Le champ Réf. produit constitue la clef 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.
Tout ce texte est généré automatiquement, mais avec des raffinements destinés à le rendre plus lisible pour un humain. Par exemple, les trois attributs non identifiants de l'entité CLIENT sont décrits en une seule ligne au lieu de trois.
6.2.1.3. Diagramme relationnel <a id='relational_diagram'></a>
La plupart des SGBD offrent une représentation hybride (graphique / texte) de la base, sous la forme d'un ensemble de tables rectangulaires liées par des flèches. Mocodo génère maintenant un fichier d'extension .mld qu'il est capable de reprendre en entrée pour tracer ce type de graphe.
Step71:  Si l'on ouvre le fichier généré (cf. ci-dessus), on constate que la syntaxe d'un MLD est 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 qui se notent
Step72:  Mais cette fois, comme le « MCD » d'entrée ne comporte aucune association, le diagramme relationnel généré ne comporte aucune flèche.
Step73:  Le reprendre comme texte d'entrée produit donc le même diagramme, mais sans les flèches. Leur rétablissement pourrait faire l'objet d'un exercice facile.
Sous Mocodo online, vous obtiendrez le premier diagramme relationnel en trois étapes
Step74:  Quoique ces informations supplémentaires ne soient pas apparues dans le diagramme conceptuel, elles ont été exploitées par la commande, qui a produit dans le répertoire mocodo_notebook un fichier directement exécutable par MySQL
Step75:  ``sql
CREATE DATABASE IF NOT EXISTSCLIENT_COMMANDE_PRODUITDEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
USECLIENT_COMMANDE_PRODUIT`;
CREATE TABLE CLIENT (
  réf_client varchar(8),
  nom varchar(20),
  adresse varchar(40),
  PRIMARY KEY (réf_client)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE COMMANDE (
  num_commande tinyint(4),
  date date,
  montant decimal(5,2) DEFAULT '0.00',
  réf_client varchar(8),
  PRIMARY KEY (num_commande)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE INCLURE (
  num_commande tinyint(4),
  réf_produit varchar(8),
  quantité tinyint(4),
  PRIMARY KEY (num_commande, réf_produit)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE PRODUIT (
  réf_produit varchar(8),
  libellé varchar(20),
  prix_unitaire decimal(5,2),
  PRIMARY KEY (réf_produit)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE COMMANDE ADD FOREIGN KEY (réf_client) REFERENCES CLIENT (réf_client);
ALTER TABLE INCLURE ADD FOREIGN KEY (réf_produit) REFERENCES PRODUIT (réf_produit);
ALTER TABLE INCLURE ADD FOREIGN KEY (num_commande) REFERENCES COMMANDE (num_commande);
```
Nouveauté de la version 2.0.17. Les clefs étrangères composites sont gérées (cf. issue 14) et les types manquants remplacés par VARCHAR(42)
Step76:  ```sql
.open "APPARTEMENTS";
CREATE TABLE "APPARTEMENT" (
  "code_rue" VARCHAR(42),
  "num_immeuble" VARCHAR(42),
  "num_étage" VARCHAR(42),
  "num_appart" VARCHAR(42),
  "nb_pièces_appart" VARCHAR(42),
  PRIMARY KEY ("code_rue", "num_immeuble", "num_étage", "num_appart"),
  FOREIGN KEY ("code_rue", "num_immeuble", "num_étage") REFERENCES "ÉTAGE" ("code_rue", "num_immeuble", "num_étage")
);
CREATE TABLE "ÉTAGE" (
  "code_rue" VARCHAR(42),
  "num_immeuble" VARCHAR(42),
  "num_étage" VARCHAR(42),
  "nb_appart_étage" VARCHAR(42),
  PRIMARY KEY ("code_rue", "num_immeuble", "num_étage"),
  FOREIGN KEY ("code_rue", "num_immeuble") REFERENCES "IMMEUBLE" ("code_rue", "num_immeuble")
);
CREATE TABLE "IMMEUBLE" (
  "code_rue" VARCHAR(42),
  "num_immeuble" VARCHAR(42),
  "nb_étages_immeuble" VARCHAR(42),
  PRIMARY KEY ("code_rue", "num_immeuble"),
  FOREIGN KEY ("code_rue") REFERENCES "RUE" ("code_rue")
);
CREATE TABLE "RUE" (
  "code_rue" VARCHAR(42),
  "nom_rue" VARCHAR(42),
  PRIMARY KEY ("code_rue")
);
```
6.2.1.5. Dictionnaire des données (bonus) <a id='dictionnaire_des_donnees_bonus'></a>
Qui peut le plus peut le moins
Step77:  | Attribut | Informations |
|----------|-------------|
| Réf. client | varchar(8) |
| Nom | varchar(20) |
| Adresse | varchar(40) |
| Num commande | tinyint(4) |
| Date | date |
| Montant | decimal(5,2) DEFAULT '0.00' |
| Quantité | tinyint(4) |
| Réf. produit | varchar(8) |
| Libellé | varchar(20) |
| Prix unitaire | decimal(5,2) |
Si l'une au moins des annotations est omise, la présentation générée sera sensiblement différente
Step78:  Réf. client
Nom
Prénom
Adresse
Num commande
Date
Montant
Quantité 
Step79:  Le contexte d'un attribut donne accès à 32 identificateurs
Step80:  json
{
  "title"
Step81:  | Identificateur | Attribut concerné | Défaut | Exemple | 
|--|--|--|--|
| compose_primary_key | identifiant resté sur place lors de la transformation d'une entité en table | "_{label}_" | land de Form |
| compose_normal_attribute | simple attribut resté sur place lors de la transformation d'une entité en table | "{label}" | hide de Form |
| compose_foreign_key | clef étrangère ayant migré par une dépendance fonctionnelle disparue, tout en perdant son caractère identifiant | "#{label}" | clue de Form |
| compose_foreign_attribute | attribut étranger ayant migré d'une dépendance fonctionnelle disparue | même valeur que compose_normal_attribute | goat de Form |
| compose_foreign_primary_key | clef étrangère primaire migré dans une association devenue table, tout en gardant son caractère identifiant  | "_#{label}_" | wage et land de Tuck |
| compose_association_attribute | simple attribut resté sur place lors de la transformation d'une association en table | même valeur que compose_normal_attribute | thin de Tuck |
<ASSISTANT_TASK:>
Python Code:
%%mocodo --mld --colors ocean --shapes copperplate --relations diagram markdown_data_dict
DF, 11 Élève, 1N Classe
Classe: Num. classe, Num. salle
Faire Cours, 1N Classe, 1N Prof: Vol. horaire
Catégorie: Code catégorie, Nom catégorie
Élève: Num. élève, Nom élève
Noter, 1N Élève, 0N Prof, 0N Matière, 1N Date: Note
Prof: Num. prof, Nom prof
Relever, 0N Catégorie, 11 Prof
Date: Date
Matière: Libellé matière
Enseigner, 11 Prof, 1N Matière
Explanation: # Table des matières
- 1. Introduction
- 2. Installation du programme
  - 2.1. Installation complète (recommandé)
  - 2.2. Vérification
  - 2.3. Installation minimale
- 3. Utilisation
  - 3.1. Utiliser Mocodo online
  - 3.2. Utiliser Mocodo en ligne de commande
    - 3.2.1. Au plus simple
    - 3.2.2. Liste des arguments
      - 3.2.2.1. Options sur Mocodo lui-même
      - 3.2.2.2. Entrée-sortie
      - 3.2.2.3. Aspect de la sortie graphique
      - 3.2.2.4. Sortie relationnelle
      - 3.2.2.5. Modifications du texte d'entrée
      - 3.2.2.6. Réarrangement par séparation et évaluation
      - 3.2.2.7. Réarrangement par algorithme génétique
      - 3.2.2.8. Réarrangement par résolution d'un programme linéaire
      - 3.2.2.9. Options spécifiques aux Notebooks
    - 3.2.3. Paramétrage à long terme
  - 3.3. Utiliser Mocodo sous Jupyter Notebook
    - 3.3.1. Invocation
    - 3.3.2. Principes de fonctionnement
    - 3.3.3. Exemples d'invocation
    - 3.3.4. Modification in situ d'une cellule
    - 3.3.5. Paramétrage à long terme
- 4. Description d'un MCD
  - 4.1. Besoins élémentaires
    - 4.1.1. Entités, associations, attributs, identifiants, cardinalités
    - 4.1.2. Dépendances fonctionnelles
    - 4.1.3. Associations réflexives
    - 4.1.4. Placement sur plusieurs rangées
  - 4.2. Besoins plus avancés
    - 4.2.1. Identifiants multiples
    - 4.2.2. Entités faibles (identification relative)
    - 4.2.3. Flèches sur les pattes
    - 4.2.4. Styles
    - 4.2.5. Types de données
    - 4.2.6. Format des cardinalités
    - 4.2.7. Rectification automatique des cardinalités mal formées
    - 4.2.8. Symbole de dépendance fonctionnelle
    - 4.2.9. Créer plusieurs entités ou associations de même nom
  - 4.3. Besoins spécifiques à la pédagogie
    - 4.3.1. Créer une vue en extension
    - 4.3.2. Afficher l'explication des cardinalités
    - 4.3.3. Créer un MCD à compléter
      - 4.3.3.1. Supprimer le marquage d'un identifiant
      - 4.3.3.2. Masquer un couple de cardinalités
      - 4.3.3.3. Masquer un attribut
      - 4.3.3.4. Ne faire apparaître que le squelette du schéma conceptuel
    - 4.3.4. Obfuscation: remplacer tous les libellés par du faux-texte
- 5. Tracé d'un MCD
  - 5.1. Insertion manuelle d'espacements
  - 5.2. Ajustement automatique dans une grille minimale
  - 5.3. Basculement des cardinalités et inflexion des pattes rectilignes
  - 5.4. Retouches fines
    - 5.4.1. Par modification du script intermédiaire
    - 5.4.2. Par édition de la sortie au format SVG
  - 5.5. Réarrangement par symétrie
    - 5.5.1. Symétrie selon l'axe vertical
    - 5.5.2. Symétrie selon l'axe horizontal
    - 5.5.3. Symétries selon les diagonales (transposition)
      - 5.5.3.1. Astuce: édition rapide d'une ou plusieurs colonnes
  - 5.6. Réarrangement automatique
    - 5.6.1. Méthode exacte spécialisée
      - 5.6.1.1. À l'intérieur d'une grille prédéfinie
      - 5.6.1.2. Par croissance organique
    - 5.6.2. Méthode heuristique
    - 5.6.3. Méthode exacte générique
  - 5.7. Conversion dans d'autres formats graphiques
- 6. Passage au relationnel
  - 6.1. Construction de la représentation interne
    - 6.1.1. Cas réguliers
      - 6.1.1.1. Exemple du traitement des associations non DF
      - 6.1.1.2. Exemple du traitement des associations DF
      - 6.1.1.3. Exemple du traitement des entités faibles (identification relative)
      - 6.1.1.4. Rétablissement explicite de la sémantique des DF disparues
    - 6.1.2. Cas irréguliers
      - 6.1.2.1. Réduire une clef primaire
      - 6.1.2.2. Minimiser le nombre de champs vides
  - 6.2. Construction de représentations externes
    - 6.2.1. Gabarits inclus dans la distribution
      - 6.2.1.1. Formats linéaires
      - 6.2.1.2. Formats linéaires avec explications
      - 6.2.1.3. Diagramme relationnel
      - 6.2.1.4. Sorties SQL
      - 6.2.1.5. Dictionnaire des données (bonus)
    - 6.2.2. Modification ou création de nouveaux gabarits
      - 6.2.2.1. Algorithme
      - 6.2.2.2. Identificateurs disponibles pour la composition de chaînes
      - 6.2.2.3. Composition des attributs selon leur nature
      - 6.2.2.4. Gabarit vide
- 7. Crédits
1. Introduction <a id='introduction'></a>
Mocodo est un logiciel d'aide à l'enseignement et à la conception des bases de données relationnelles.
En entrée, il prend une description textuelle des entités et associations du modèle conceptuel de données (MCD).
En sortie, il produit son diagramme entité-association en SVG et son schéma relationnel (MLD) en SQL, $\mathrm\LaTeX$, Markdown, etc.
Ci-dessous, un exemple d'appel du programme (première ligne) sur un texte d'entrée (lignes suivantes), puis, en sortie, le MCD et le MLD correspondants:
End of explanation
# %load mocodo_notebook/sandbox_data_dict.md
Explanation: L'appel ci-dessus a également construit le dictionnaire des données:
End of explanation
%mocodo --input mocodo_notebook/sandbox.mld --colors desert
Explanation: Num. classe
Num. salle
Vol. horaire
Code catégorie
Nom catégorie
Num. élève
Nom élève
Note
Num. prof
Nom prof
Date
Libellé matière
Ainsi que le diagramme relationnel, qui peut être visualisé par un nouvel appel:
End of explanation
%%mocodo
MISSION: accomplie
Explanation: La devise de Mocodo, « nickel, ni souris », en résume les principaux points forts:
description textuelle des données. L'utilisateur n'a pas à renseigner, placer et déplacer des éléments comme avec une lessive ordinaire. Il ne fournit rien de plus que les informations définissant son MCD. L'outil s'occupe tout seul du plongement;
propreté du rendu. La sortie se fait en vectoriel, prête à être affichée, imprimée, agrandie, exportée dans une multitude de formats sans perte de qualité;
rapidité des retouches. L'utilisateur rectifie les alignements en insérant des éléments invisibles, en dupliquant des coordonnées ou en ajustant des facteurs mutiplicatifs: là encore, il travaille sur une description textuelle, et non directement sur le dessin.
Mocodo est libre, gratuit et multiplateforme. Si vous l'aimez, répandez la bonne nouvelle en incluant l'un de ses logos dans votre support: cela multipliera ses chances d'attirer des contributeurs qui le feront évoluer.
2. Installation du programme <a id='installation_du_programme'></a>
2.1. Installation complète (recommandé) <a id='installation_complete_recommande'></a>
Installez la distribution Anaconda, qui contient Python (2 ou 3), IPython et bien plus encore.
Tapez ensuite sous un terminal la ligne de commande:pip install mocodo_magic
Cette commande installera Mocodo, ainsi que l'extension IPython qui permettra de l'utiliser dans un document comme celui-ci (il s'agit d'un Jupyter notebook).
2.2. Vérification <a id='verification'></a>
Toujours sous un terminal, tapez:
mocodo
Si votre système se plaint que cette commande n'existe pas, localisez le fichier mocodo et ajoutez le chemin du répertoire contenant à votre PATH:
- sous Linux ou Mac OS X;
- sous Windows.
Pour mettre la « commande magique » mocodo à disposition d'un notebook donné, évaluez dans celui-ci la cellule suivante:
%reload_ext mocodo_magic
Techniquement, %load_ext mocodo_magic suffit, mais cette forme vous épargnera un message d'erreur si vous réévaluez ultérieurement la cellule. Pour tester, évaluez une cellule avec:
End of explanation
%%mocodo --flip=v --replace
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
Explanation: Pour charger automatiquement mocodo_magic à chaque ouverture d'un notebook (ce qui dispense d'évaluer %load_ext mocodo_magic) :
exécuter sous un terminal :
    ipython profile create
éditer le fichier créé (p. ex.: ~/.ipython/profile_default/ipython_config.py) pour remplacer les lignes suivantes :
    ## A list of dotted module names of IPython extensions to load.
    #c.InteractiveShellApp.extensions = []
par celles-ci :
        ## A list of dotted module names of IPython extensions to load.
        c.InteractiveShellApp.extensions = [
            "mocodo_magic",
        ]
2.3. Installation minimale <a id='installation_minimale'></a>
Si vous êtes sous Mac OS X ou Linux, vous avez déjà Python. Dans le cas contraire, vous devrez probablement l'installer.
Une fois Python installé, tapez sous un terminal:
pip install mocodo
Vous ne bénéficierez pas de Jupyter Notebook, mais vous pourrez utiliser Mocodo en ligne de commande.
3. Utilisation <a id='using_mocodo'></a>
Vous pouvez utiliser Mocodo:
dans un navigateur récent, sans rien installer, avec Mocodo online;
sur votre machine, comme n'importe quel programme Python;
dans un document Jupyter Notebook (à l'instar de cette documentation).
3.1. Utiliser Mocodo online <a id='utiliser_mocodo__online_'></a>
Faites pointer votre navigateur sur http://mocodo.net: vous pouvez commencer à taper votre MCD. Appuyez à tout moment sur le bouton de génération pour visualiser le diagramme conceptuel et en déduire les relations. Une fois que le résultat vous convient, appuyez sur le bouton de téléchargement pour récupérer une archive ZIP contenant tous les fichiers d'entrée et de sortie désiré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, vous pouvez installer Mocodo sur votre machine.
3.2. Utiliser Mocodo en ligne de commande <a id='utiliser_mocodo_en_ligne_de_commande'></a>
3.2.1. Au plus simple <a id='au_plus_simple'></a>
Tout a été fait pour faciliter au maximum la prise en main. Ainsi, pour peu que vous sachiez lancer une console (cmd sous Windows, Terminal sous Mac OS X), il vous suffit d'y entrer:
mocodo
Invoqué sous cette forme, le script récupère le texte d'entrée du MCD dans le répertoire courant sous le nom de sandbox.mcd. Si ce fichier n'existe pas, il y sera automatiquement créé avec un MCD d'exemple. Par la suite, vous n'aurez qu'à le garder ouvert sous un éditeur de texte, afin de le modifier selon vos besoins avant de lancer la commande.
3.2.2. Liste des arguments <a id='parametrage_occasionnel'></a>
La commande mocodo admet de nombreux arguments optionnels. Voici la traduction en français de la liste affichée par l'argument --help. Destinée à servir de référence, elle peut être sautée sans inconvénient à la première lecture. Nous avons ajouté des liens vers des exemples d'utilisation dans ce document; notez cependant que les %% ou % qui préfixent la « commande magique » mocodo doivent être omis de la ligne de commande.
3.2.2.1. Options sur Mocodo lui-même <a id='options_sur_mocodo_lui_meme'></a>
--help.
  Affiche un message d'aide, puis termine.
--version.
  Affiche le numéro de version, puis termine.
--language CODE.
  Outrepasse la localisation automatique des messages avec le code de langage donné (p. ex., fr, en, ...) (défaut: langue du système).
--restore.
  Recrée une version originelle des fichiers sandbox.mcd et params.json dans le répertoire d'entrée, puis termine (défaut: False).
3.2.2.2. Entrée-sortie <a id='entree_sortie'></a>
--params_path PATH.
  Le chemin du fichier de paramètres. S'il est omis, utilise params.json dans le répertoire d'entrée. Si ce fichier n'existe pas, utilise les paramètres par défaut (défaut: params.json).
--input PATH.
  Le chemin du fichier d'entrée. Les fichiers de sortie seront par défaut générés dans le même répertoire (défaut: sandbox.mcd). 
--output_dir PATH.
  Le répertoire où générer les fichiers de sortie (défaut: le répertoire où se trouve le fichier d'entrée). 
--encodings [STR [STR ...]].
  Un ou plusieurs encodages à essayer successivement pour lire le fichier d'entrée (défaut: utf8, puis encodage historique de la plateforme).
--extract.
  Crée un fichier JSON séparé pour les paramètres géométriques (défaut: False).
--image_format {svg,nodebox}.
  Outrepasse la sélection automatique du format d'image produit par le script généré (défaut: dépendant de votre système et de votre installation).
--print_params.
  Affiche le contenu du fichier de paramètres, puis termine (défaut: False).
3.2.2.3. Aspect de la sortie graphique <a id='aspect_de_la_sortie_graphique'></a>
--df STR.
  Acronyme à encercler dans une dépendance fonctionnelle (défaut: DF).
--card_format STR.
  Chaîne de format pour les cardinalités minimale et maximale (défaut: {min_card},{max_card}).
--strengthen_card STR.
  Chaîne pour les cardinalités relatives (défaut: _1,1_).
--flex FLOAT.
  Infléchit les pattes rectilignes dont les cardinalités sont susceptibles de collision (défaut: 0.75).
--tkinter.
  Utilise Tkinter pour calculer les dimensions des libellés (défaut: False).
--colors PATH.
  Palette de couleurs à utiliser lors de la génération du dessin. Nom (sans extension) d'un fichier du répertoire colors, ou chemin vers un fichier personnel (défaut: bw).
--shapes PATH.
  Spécification des polices, des dimensions, etc. Nom (sans extension) d'un fichier du répertoire shapes, ou chemin vers un fichier personnel (défaut: dépendant de votre système).
--scale SCALE.
  Facteur d'échelle multiplicatif (défaut: 1.0).
--hide_annotations.
  Ignore le survol des éléments annotés (défaut: False).
3.2.2.4. Sortie relationnelle <a id='sortie_relationnelle'></a>
--relations [NAME [NAME ...]].
  Un ou plusieurs gabarits pour les schémas relationnels générés. Cf. répertoire relation_templates (défaut: html text).
--disambiguation {numbers_only,annotations}.
  Méthode de désambiguïsation des attributs migrants homonymes (défaut: annotations).
--title STR.
  Nom de la base (utilisé pour la sortie SQL) (défaut: Sans titre).
--guess_title.
  Utiliser le nom de l'entité la plus référencée comme titre (défaut: False).
3.2.2.5. Modifications du texte d'entrée <a id='modifications_du_texte_d_entree'></a>
--arrange [{bb,ga,lp}].
  Met en page le diagramme, soit par séparation et évaluation, soit avec un algorithme génétique, soit avec un solveur de programmes linéaires, puis termine (défaut: None).
--timeout SECONDS.
  Limite la durée du calcul de la mise en page (défaut: None).
--verbose.
  Affiche des détails oiseux lors du réarrangement (défaut: False).
--flip {h,v,d}.
  Affiche une version retournée horizontalement / verticalement / diagonalement du texte d'entrée, puis termine (défaut: None).
--fit [INT].
  Reformate le texte d'entrée dans la ième plus petite grille possible, puis termine (défaut: None).
--obfuscate [PATH].
  Affiche une version du texte d'entrée vidée de sa sémantique, puis termine. Cf. répertoire lorem (défaut: None).
--obfuscation_max_length INT.
  Longueur maximale des mots de substitution (défaut: None).
--obfuscation_min_distance INT.
  Distance de Damerau Levenshtein minimale entre deux mots de substitution (défaut: 3).
--seed FLOAT.
  Valeur du germe du générateur aléatoire (défaut: None).
3.2.2.6. Réarrangement par séparation et évaluation <a id='rearrangement_par_separation_et_evaluation'></a>
Sous-options accessibles avec l'option --arrange=bb.
--call_limit INT.
  Nombre maximal d'appels pour une boîte de départ donnée (défaut: 10000).
--min_objective INT.
  Meilleur objectif esthétique pour la mise en page (défaut: 0).
--max_objective INT.
  Pire objectif esthétique pour la mise en page (défaut: 15).
--organic.
  Réarrangement non limité à la grille originelle (défaut: False).
3.2.2.7. Réarrangement par algorithme génétique <a id='rearrangement_par_algorithme_genetique'></a>
Sous-options accessibles avec l'option --arrange=ga.
--population_size INT.
    Nombre d'individus à faire évoluer (défaut: 1000).
--crossover_rate RATE.
    Taux de croisement, entre 0 et 1 (défaut: 0.9).
--mutation_rate RATE.
    Taux de mutation, entre 0 et 1 (défaut: 0.06).
--sample_size INT.
    Taille de l'échantillon pour les tournois (défaut: 7).
--max_generations INT.
    Nombre maximal de générations (défaut: 300).
--plateau INT.
    Nombre maximal de générations consécutives sans amélioration (défaut: 30).
3.2.2.8. Réarrangement par résolution d'un programme linéaire <a id='rearrangement_par_resolution_d_un_programme_lineaire'></a>
Sous-options accessibles avec l'option --arrange=lp.
--engine [{cplex,gurobi}].
    Solveur de programmes linéaires (défaut: None).
3.2.2.9. Options spécifiques aux Notebooks <a id='options_specifiques_aux_notebooks'></a>
Ignorées lors de l'appel en ligne de commande.
--mld.
    Affiche le schéma relationnel en HTML dans la sortie de la cellule (défaut: False).
--no_mcd.
    N'affiche pas le diagramme conceptuel dans la sortie de la cellule (défaut: False).
--replace.
    Remplace le contenu de la cellule par le résultat de son évaluation (défaut: False).
3.2.3. Paramétrage à long terme <a id='parametrage_a_long_terme'></a>
Pour éviter d'avoir à invoquer Mocodo répétitivement avec une longue kyrielle d'options, vous pouvez mettre celles-ci une fois pour toutes dans un fichier params.json situé dans le répertoire courant. La commande:
mocodo --restore
... le fait pour vous avec un fichier de paramètres vide, i.e. , un fichier-texte réduit aux deux caractères {}  (attention, elle rétablit aussi le fichier sandbox.mcd à son contenu par défaut). Vous êtes encouragés à modifier ce fichier de paramètres selon vos goûts et vos besoins. De la sorte, le style de vos MCD pourra être maintenu à moindre frais à travers tous vos documents. En cas de besoin, vous pourrez toujours ponctuellement passer outre ces réglages en en précisant d'autres en ligne de commande. Plus précisément, chaque paramètre est déterminé:
par sa valuation en ligne de commande;
à défaut, par sa valuation dans le fichier de paramètres indiqué par --params_path;
à défaut d'une telle indication, par sa valuation dans le fichier params.json du répertoire courant;
à défaut, par une valeur défaut éventuellement dépendante de votre système.
Si vous lancez Mocodo avec l'option --print_params, la valeur courante de l'ensemble des paramètres sera affichée. Vous pouvez envoyer la sortie dans un fichier params.json et la modifier à votre gré pour une prise en compte lors du lancement suivant.
3.3. Utiliser Mocodo sous Jupyter Notebook <a id='ipynb_usage'></a>
3.3.1. Invocation <a id='invocation'></a>
Elle nécessite l'installation de l'extension notebook mocodo, laquelle doit en outre être rechargée à chaque ouverture (cf. première cellule de ce document). On a ainsi déclaré une « commande magique » mocodo qui sera invoquée en la préfixant:
de %% pour prendre toutes les lignes suivantes de la cellule comme texte d'entrée du MCD;
de % si l'on récupère l'entrée ailleurs (avec --input), ou qu'on n'en a pas besoin (p. ex., --help ou --print_params).
À part ça, la syntaxe est généralement la même qu'en ligne de commande, ce qui devrait faciliter le passage de l'un à l'autre.
3.3.2. Principes de fonctionnement <a id='principes_de_fonctionnement'></a>
Il peut être utile de comprendre ce qui se passe en coulisses lorsque l'on invoque la commande magique sur une cellule:
dans le répertoire courant est créé au besoin un sous-répertoire mocodo_notebook;
le texte d'entrée y est sauvegardé sous le nom de sandbox.mcd;
la commande est lancée sur ce fichier avec tous les paramètres donnés par l'utilisateur. Cela signifie que tous les fichiers générés le seront au même endroit sous les noms de sandbox.svg, sandbox.html, etc.;
si la commande a produit un dessin, celui-ci est affiché en sortie (sauf avec l'option --no_mcd); avec l'option --mld, le schéma relationnel est également affiché au-dessous (au format HTML);
si elle n'a pas produit de dessin, mais une nouvelle version du texte d'entrée (options --arrange, --flip, --obfuscate, ...), Mocodo est automatiquement relancé sur celle-ci, permettant de visualiser le diagramme et/ou le schéma relationnel correspondants.
Tous les fichiers peuvent être lus dans le répertoire mocodo_notebook (commande magique %load, mise en commentaire dans ce notebook pour éviter de recharger le fichier à chaque exécution).
3.3.3. Exemples d'invocation <a id='exemples_d_invocation'></a>
Les trois exemples de l'introduction illustrent plusieurs de ces techniques usuelles:
%%mocodo --mld --colors ocean --shapes copperplate --relations diagram markdown_data_dict
... invoque le programme en demandant l'affichage du diagramme conceptuel (implicitement), du schéma relationnel (avec --mld), des changements de style (avec --colors et --shapes) et la production d'un diagramme relationnel (--relations diagram) et d'un dictionnaire de données (markdown_data_dict). Le contenu de celui-ci est rechargé et visualisé à l'aide de la commande suivante:
%load mocodo_notebook/sandbox_data_dict.md
Tandis que le diagramme relationnel (MLD) est tracé en relançant Mocodo dessus:
%mocodo --input mocodo_notebook/sandbox.mld --colors desert
3.3.4. Modification in situ d'une cellule <a id='modification__in_situ__d_une_cellule'></a>
Nouveauté de la version 2.0.20 (contribution de Thomas Giro). Avec les options --arrange, --flip et --obfuscate le résultat de l'évaluation de la cellule est un nouveau MCD, normalement affiché au-dessous. Ajoutez l'option --replace pour substituer ce MCD au contenu de la cellule. Réévaluez alors celle-ci pour tracer le MCD résultant, ou annulez la dernière opération pour revenir au contenu originel.
Par exemple, l'évaluation de la cellule suivante:
End of explanation
%%mocodo
PRODUIT: Réf. produit, Libellé, Prix unitaire
INCLURE, 1N COMMANDE, 0N PRODUIT: Quantité
COMMANDE: Num commande, Date, Montant
PASSER, 0N CLIENT, 11 COMMANDE
CLIENT: Réf. client, Nom, Prénom, Adresse
Explanation: ... remplacerait celle-ci par celle-là:
End of explanation
%mocodo --print_params
Explanation: 3.3.5. Paramétrage à long terme <a id='magic_long_term_settings'></a>
Si vous voulez éviter de préciser à chaque fois les mêmes arguments (par exemple un changement de couleurs), vous pouvez placer un fichier params.json dans le répertoire mocodo_notebook. Mocodo peut même vous aider à le faire en exécutant la cellule suivante:
End of explanation
# You may edit and run the following lines
import codecs, json
params = u
{
  "arrange": null, 
  "call_limit": 10000, 
  "colors": "bw", 
  "crossover_rate": 0.9, 
  "df": "DF", 
  "disambiguation": "annotations", 
  "encodings": [
    "utf8", 
    "macroman"
  ], 
  "extract": false, 
  "flip": null, 
  "guess_title": false, 
  "hide_annotations": false, 
  "image_format": "svg", 
  "input": "mocodo_notebook/sandbox.mcd", 
  "language": "fr", 
  "max_generations": 300, 
  "max_objective": 15, 
  "min_objective": 0, 
  "mld": false, 
  "mutation_rate": 0.06, 
  "no_mcd": false, 
  "obfuscate": null, 
  "obfuscation_max_length": null, 
  "organic": false, 
  "output_dir": "mocodo_notebook", 
  "plateau": 30, 
  "population_size": 1000, 
  "print_params": false, 
  "relations": [
    "html", 
    "text"
  ], 
  "replace": false, 
  "restore": false, 
  "sample_size": 7, 
  "scale": 1.0, 
  "seed": null, 
  "sep": ",", 
  "shapes": "copperplate", 
  "timeout": null, 
  "title": "Sans titre", 
  "tkinter": false, 
  "verbose": false
}
try:
    json.loads(params)
except:
    raise RuntimeError("Invalid JSON. Find out why on http://jsonlint.com")
with codecs.open("mocodo_notebook/params.json", "w", "utf8") as f:
    f.write(params.strip())
Explanation: Son évaluation remplace son propre contenu par des lignes de code similaires à:
End of explanation
%%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
Explanation: Modifiez la variable params à votre gré en respectant la syntaxe JSON (attention en particulier au dernier couple clef-valeur, qui n'est pas terminé par une virgule). Exécutez la cellule pour créer un fichier de nom et emplacement adéquats (notez que la valeur de --print_params a été passée à false pour vous éviter de le faire à la main).
4. Description d'un MCD <a id='erd_description'></a>
4.1. Besoins élémentaires <a id='elementary_needs'></a>
4.1.1. Entités, associations, attributs, identifiants, cardinalités <a id='elements'></a>
End of explanation
%%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
Explanation: La syntaxe ne devrait pas poser problème:
- une entité est définie par son nom, deux-points, sa liste d'attributs séparés par des virgules;
- une association est définie par son nom, virgule, les cardinalités et l'entité de sa première patte, virgule, les cardinalités et l'entité de sa deuxième patte, etc., deux-points, sa liste d'attributs séparés par des virgules.
À noter :
- le premier attribut d'une entité est considéré par défaut comme son identifiant, et donc souligné;
- pour les associations sans attributs, le deux-points est facultatif;
- la première ligne:
        %%mocodo
  ... ne fait pas partie de la description. Dans ce document, elle permet de faire appel à une « commande magique », qui lance Mocodo sur les lignes qui la suivent. Sauf sous Jupyter Notebook, vous pouvez l'omettre dans votre texte d'entrée.
  De façon générale, la ou les premières lignes d'un MCD qui commencent par le symbole de pourcentage (%) sont ignorées. Cela permet de placer en en-tête un commentaire qui pourra être préservé lors des éventuels réarrangements ultérieurs.
- Les accents présents dans votre fichier d'entrée sont correctement gérés pourvu que vous ayez enregistré celui-ci dans l'encodage attendu par Mocodo en entrée: c'est par défaut Unicode UTF-8. Une tolérance existe: si Mocodo échoue à décoder votre fichier avec utf8, il se rabattra sur le codec d'Europe de l'Ouest associé historiquement à votre plateforme: iso-8859-15 pour Windows et Linux, mac-roman pour Mac OS X. Si les accents n'apparaissent pas correctement, vous aurez encore trois solutions:
  1. soit (fortement conseillé), ré-enregistrer votre fichier en UTF-8 au lieu d'un encodage historique;
  3. soit (ponctuellement), passer l'encodage de votre fichier en argument avec --encodings;
  2. soit (à long terme), modifier dans params.json la liste des encodages pris en charge.
4.1.2. Dépendances fonctionnelles <a id='functional_dependencies'></a>
End of explanation
%%mocodo
HOMME: Num. SS, Nom, Prénom
ENGENDRER, 0N HOMME, 11 HOMME
Explanation: Si on a plusieurs dépendances fonctionnelles à représenter, on devra suffixer le DF par un numéro (cf. cet exemple).
4.1.3. Associations réflexives <a id='reflexives_associations'></a>
End of explanation
%%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
Explanation: 4.1.4. Placement sur plusieurs rangées <a id='placement_sur_plusieurs_rangees'></a>
L'ordre et la séparation des lignes de la description permet de spécifier à coût zéro un plongement grossier, mais qui s'avère en général suffisant:
les boîtes (entités et associations) définies sur des lignes consécutives sont tracées sur une même rangée;
un saut de ligne indique une nouvelle rangée.
End of explanation
%%mocodo
GRATTE-CIEL: latitude, _longitude, nom, hauteur, année de construction
Explanation: Les boîtes sont placées aux intersections d'une grille invisible assurant que leurs centres soient alignés aussi bien horizontalement que verticalement. C'est ce qui en général est le plus satisfaisant esthétiquement, mais d'autres retouches peuvent être opérées manuellement dans le fichier de sortie.
Le plongement fait l'objet d'une « compression » horizontale et verticale. Par exemple, ci-dessus, il y a un espace horizontal négatif entre le bord droit de l'entité de gauche et le bord gauche de l'entité de droite.
4.2. Besoins plus avancés <a id='besoins_plus_avances'></a>
4.2.1. Identifiants multiples <a id='identifiants_multiples'></a>
Préfixer d'un caractère de soulignement (_) le(s) second, troisième, etc. attributs pour les ajouter à l'identifiant.
End of explanation
%%mocodo
ŒUVRE: Cote œuvre, Titre, Date parution
DF, 1N ŒUVRE, _11 EXEMPLAIRE
EXEMPLAIRE: Num. exemplaire, État du livre, Date d'achat
Explanation: 4.2.2. Entités faibles (identification relative) <a id='entites_faibles'></a>
Préfixer d'un caractère de soulignement (_) une cardinalité (1,1) pour indiquer que l'entité distinguée est faible. Dans le diagramme, les identifiants (ou discriminants) d'une telle entité seront soulignés en pointillés, tandis que le (1,1) sera souligné d'un trait plein.
End of explanation
%%mocodo --strengthen_card (1,1)
ŒUVRE: Cote œuvre, Titre, Date parution
DF, 1N ŒUVRE, _11 EXEMPLAIRE
EXEMPLAIRE: Num. exemplaire, État du livre, Date d'achat
Explanation: Nouveauté de la version 2.1. Traditionnellement, l'identification relative est dénotée par des parenthèses autour des cardinalités. Cette notation (ou toute autre) peut maintenant être obtenue avec l'option --strenghten_card:
End of explanation
%%mocodo
ŒUVRE: Cote œuvre, Titre, Date parution
DF, _11 ŒUVRE, _11 EXEMPLAIRE
EXEMPLAIRE: Num. exemplaire, État du livre, Date d'achat
Explanation: Une association ne peut renforcer plus d'une entité faible. Ainsi, une erreur se produit si l'on remplace le 1N par _11:
End of explanation
%%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
Explanation: 4.2.3. Flèches sur les pattes <a id='fleches_sur_les_pattes'></a>
Suffixer d'un chevron (&lt; ou &gt;) 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é.
End of explanation
%%mocodo --card_format={min_card}/{max_card}
CLIENT: Réf. client, Nom, Prénom, Adresse
PASSER, 0N CLIENT, 11 COMMANDE
COMMANDE: Num commande, Date, Montant
INCLURE, 1N COMMANDE, 0N PRODUIT: Quantité
PRODUIT: Réf. produit, Libellé, Prix unitaire
Explanation: La position de la flèche sur la patte peut être réglée individuellement dans la table d'association ratio du script Python généré (par défaut, sandbox_svg.py ou sandbox_nodebox.py) ou sous l'onglet Retouches de la version en ligne. La valeur correspondante peut varier de 0.0 (flèche cachée sous la boîte d'origine) à 1.0 (par défaut, pointe de la flèche au contact du bord de la boîte de destination, compte non tenu de l'arrondi s'il s'agit d'une association).
4.2.4. Styles <a id='styles'></a>
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). Une changement d'échelle d'un facteur multiplicatif positif peut être précisé avec l'argument --scale.
Vous pouvez bien sûr créer vos propres styles en vous inspirant des fichiers fournis. Si vous êtes particulièrement content d'un style, soumettez-le pour inclusion dans une prochaine distribution.
4.2.5. Types de données <a id='types_de_donnees'></a>
Chaque attribut peut être assorti d'annotations entre crochets. Ignorées au niveau du tracé du MCD, elles sont interprétées comme des types de données lors de la génération d'un code-source SQL.
4.2.6. Format des cardinalités <a id='card_format'></a>
Par défaut, les cardinalités sont séparées par une virgule.
Nouveauté de la version 2.1. On peut maintenant opter pour un format quelconque:
End of explanation
%%mocodo
CLIENT: Réf. client, Nom, Prénom, Adresse
PASSER, oN CLIENT, 11 COMMANDE
COMMANDE: Num commande, Date, Montant
INCLURE, lN COMMANDE, ON PRODUIT: Quantité
PRODUIT: Réf. produit, Libellé, Prix unitaire
Explanation: 4.2.7. Rectification automatique des cardinalités mal formées <a id='rectification_automatique_des_cardinalites_mal_formees'></a>
Certaines fautes de frappe fréquentes (inversion des cardinalités minimale et maximale, lettre « O » au lieu du chiffre « 0 ») sont silencieusement rectifiées:
| formes erronées | forme rectifiée |
|-----------------|-----------------|
| O1, o1, 10, 1O, 1o | 01 |
| ON, oN, NO, No, N0 | 0N |
| On, on, no, nO, n0 | 0n|
| N1 | 1N |
| n1 | 1n |
Les cardinalités (N,N), qui selon une certaine école dénotent une cardinalité minimale supérieure à 1, sont laissées telles quelles.
End of explanation
%%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
Explanation: 4.2.8. Symbole de dépendance fonctionnelle <a id='df_symbol'></a>
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:
End of explanation
%%mocodo
:
Rhoncus: dolor a, bibendum, euismod, consectetuer, leo
Porttitor, 1N Rhoncus, 1N Curabitur
:
:
Ultricies, 11 Rhoncus, 0N Egestas
Imperdiet, 0N Egestas, 0N Curabitur, 0N DATE
Curabitur: blandit, suscipit
Mollis, 0N Curabitur, 0N Curabitur
:
:
Egestas: vivamus, semper, aliquam
Pharetra, 0N Curabitur, 0N DATE, 0N Vitae justo: massa
Vitae justo: lobortis, purus
adipiscing, 0N Curabitur, 0N Vitae justo, 0N DATE
:
:
DATE: date
:
:
Explanation: 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 le dictionnaire de shapes:
"df_text_height_ratio"             : 1.00,
4.2.9. Créer plusieurs entités ou associations de même nom <a id='box_duplication'></a>
Normalement on doit choisir des noms différents pour toutes les boîtes (entités et associations) du MCD, à l'exception des associations de dépendance fonctionnelle figurées par un sigle. On a vu que dans ce cas, il suffisait d'ajouter à leur nom un suffixe numérique: celui-ci n'apparaîtra pas en sortie. Cette possibilité vaut pour n'importe quelle boîte.
Elle servira typiquement à « distribuer » une entité DATE réduite à son identifiant date, mais associée à de nombreuses entités qui n'ont rien à voir entre elles. Sachant qu'une telle entité est amenée à disparaître lors du passage au relationnel, il n'y a aucun inconvénient à en créer plusieurs, et cela peut avoir l'avantage de faciliter (ou même de rendre possible) l'obtention d'une bonne mise en page.
Par exemple, la mise en page du MCD suivant est indûment complexifiée par le haut degré de l'entité DATE.
End of explanation
%%mocodo
Egestas: vivamus, semper, aliquam
DATE: date
Pharetra, 0N Curabitur, 0N DATE, 0N Vitae justo: massa
Vitae justo: lobortis, purus
Ultricies, 11 Rhoncus, 0N Egestas
Imperdiet, 0N Egestas, 0N Curabitur, 0N DATE
Curabitur: blandit, suscipit
adipiscing, 0N Curabitur, 0N Vitae justo, 0N DATE2
Rhoncus: dolor a, bibendum, euismod, consectetuer, leo
Porttitor, 1N Rhoncus, 1N Curabitur
Mollis, 0N Curabitur, 0N Curabitur
DATE2: date
Explanation: Ajouter une autre entité DATE (sous le nom de DATE2) permettra à Mocodo de calculer une mise en page à la fois plus agréable à l'œil et plus compacte ($4\times3$ au lieu de $5\times4$). La sémantique est inchangée.
End of explanation
%%mocodo
ŒUVRE1: cote, titre, date de publication
::::
ŒUVRE2: 612.NAT.34, J'apprends à lire à mes souris blanches, mai 1975
:
    
DF1, 1N ŒUVRE1, _11 EXEMPLAIRE1
:::
DF2, XX ŒUVRE2, XX EXEMPLAIRE2
DF3, XX ŒUVRE2, XX EXEMPLAIRE3
DF4, XX ŒUVRE2, XX EXEMPLAIRE4
EXEMPLAIRE1: numéro d'exemplaire, état, date d'achat
:::
EXEMPLAIRE2: 1, bon état, 12/6/1975
EXEMPLAIRE3: 2, bon état, 1/8/1977
EXEMPLAIRE4: 3, reliure rongée, 3/4/2005
Explanation: 4.3. Besoins spécifiques à la pédagogie <a id='besoins_specifiques_a_la_pedagogie'></a>
Si vous n'êtes pas enseignant de bases de données, vous pouvez passer directement à la section suivante.
4.3.1. Créer une vue en extension <a id='creer_une_vue_en_extension'></a>
La technique de duplication que l'on vient de voir 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):
End of explanation
%%mocodo
CLIENT: Réf. client, Nom, Prénom, Adresse
PASSER, 0N [Un client peut passer un nombre quelconque de commandes.] CLIENT, 11 [Toute commande est passée par un en un seul client.] COMMANDE
COMMANDE: Num commande, Date, Montant
INCLURE, 1N [Une commande peut inclure plusieurs produits distincts, et en inclut au moins un.] COMMANDE, 0N [Certains produits ne sont jamais commandés, d'autres le sont plusieurs fois.] PRODUIT: Quantité
PRODUIT: Réf. produit, Libellé, Prix unitaire
Explanation: 4.3.2. Afficher l'explication des cardinalités <a id='leg_annotation_description'></a>
Les débutants ont souvent des doutes sur la sémantique de telle ou telle cardinalité. Cette information peut désormais être incluse dans le texte-source, en annotant les pattes correspondantes, pour apparaître à la demande lors du rendu (utile pour créer des exercices à faire en TD ou en autonomie).
Survolez les cardinalités du MCD ci-dessous pour faire apparaître leur description.
End of explanation
%%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
Explanation: Les annotations s'insèrent entre cardinalités et nom de l'entité. Elles sont délimitées par des crochets droits.
Avec l'option --disambiguation=annotations (par défaut), elles sont également exploitables lors du passage au relationnel pour préciser la sémantique d'une clef étrangère.
L'affichage est désactivé avec l'option --hide_annotations.
Limitations.
Ne fonctionne pas sous Inkscape.
Ne semble pas fonctionner dans une page HTML statique (comme la version HTML de ce document sous GitHub).
Semble nécessiter une réévaluation de la cellule pour fonctionner dans un notebook fermé, puis rouvert.
Sans effet sur le diagramme conceptuel généré avec l'option --image_format=nodebox.
4.3.3. Créer un MCD à compléter <a id='creer_un_mcd_a_completer'></a>
Les MCD à trous sont des exercices classiques d'introduction aux bases de données.
4.3.3.1. Supprimer le marquage d'un identifiant <a id='supprimer_le_marquage_d_un_identifiant'></a>
Pour éviter le marquage automatique du premier attribut d'une entité comme identifiant, il suffit de le préfixer par un _ (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).
End of explanation
%%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
Explanation: 4.3.3.2. Masquer un couple de cardinalités <a id='masquer_un_couple_de_cardinalites'></a>
Vous pouvez masquer n'importe quelles cardinalités en les remplaçant pas XX (ci-dessous à gauche) :
End of explanation
%%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
Explanation: 4.3.3.3. Masquer un attribut <a id='masquer_un_attribut'></a>
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.
End of explanation
%%mocodo --colors=blank
CLIENT: Réf. client, Nom, Prénom, Adresse
PASSER, 0N CLIENT, 11 COMMANDE
COMMANDE: Num commande, Date, Montant
INCLURE, 1N COMMANDE, 0N PRODUIT: Quantité
PRODUIT: Réf. produit, Libellé, Prix unitaire
Explanation: 4.3.3.4. Ne faire apparaître que le squelette du schéma conceptuel <a id='mcd_skeleton'></a>
Enfin, vous pouvez transformer en exercice à trous n'importe quel MCD en rendant complètement transparentes les couleurs des attributs, associations et cardinalités. Le style blank a été prédéfini à cet effet:
End of explanation
%%mocodo
CLIENT: ,          ,,
PASSER, XX CLIENT, XX COMMANDE
COMMANDE: ,               ,
INCLURE, XX COMMANDE, XX PRODUIT: 
PRODUIT: ,            ,
Explanation: Attention, n'utilisez pas cette méthode si vous souhaitez diffuser l'exercice sous forme électronique: l'information textuelle est toujours présente, susceptible d'être sélectionnée et collée ailleurs pour être lue. Vous pouvez bien sûr empêcher cette possibilité en convertissant la figure dans un format bitmap (comme PNG ou GIF); mais le plus simple est de combiner les deux méthodes précédentes:
End of explanation
%%mocodo --obfuscate
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
Explanation: 4.3.4. Obfuscation: remplacer tous les libellés par du faux-texte <a id='obfuscation'></a>
L'obfuscation d'un MCD consiste à vider celui-ci de sa sémantique de surface, en substituant à tous les libellés des chaînes aléatoires. Le résultat sera par exemple utilisé pour montrer que les principales règles de passage du schéma conceptuel au schéma relationnel peuvent être appliquées « bêtement », c'est-à-dire sans comprendre le fonctionnement de l'organisme modélisé.
Ainsi, dans l'exemple ci-dessous, les libellés du MCD CLIENT-COMMANDE-PRODUIT sont remplacés par des mots tirés au hasard:
End of explanation
%%mocodo --obfuscate=fr_refman.ipynb --obfuscation_max_length=10 --seed=5 --no_mcd
CLIENT: Réf. client, Nom, Prénom, Adresse
PASSER, 0N CLIENT, 11 COMMANDE
COMMANDE: Num commande, Date, Montant
INCLURE, 1N COMMANDE, 0N PRODUIT: Quantité
PRODUIT: Réf. produit, Libellé, Prix unitaire
Explanation: Nouveauté de la version 2.0.20. Pour remplacer le texte de la cellule par le résultat de son évaluation, ajoutez l'option --replace.
En argument, vous pouvez ajouter le chemin d'un fichier texte UTF-8 quelconque où puiser les mots de substitution. Par exemple, le texte même de cette documentation:
End of explanation
%%mocodo --obfuscate=four_letter_words --seed=42 --no_mcd
CLIENT: Réf. client, Nom, Prénom, Adresse
PASSER, 0N CLIENT, 11 COMMANDE
COMMANDE: Num commande, Date, Montant
INCLURE, 1N COMMANDE, 0N PRODUIT: Quantité
PRODUIT: Réf. produit, Libellé, Prix unitaire
Explanation: Mocodo essaie d'abord de trouver ce fichier à l'endroit indiqué. En cas d'échec, il le cherche (avec extension .txt facultative) parmi les textes distribués avec le logiciel, à savoir:
"lorem_ipsum.txt": le faux-texte le plus courant.
"disparition.txt": le lexique du célèbre roman lipogrammatique de Georges Perec.
"four_letter_words.txt": une sélection (SFW) de mots anglais de quatre lettres.
En cas de nouvel échec, il se rabat sur "lorem_ipsum.txt".
L'option obfuscation_max_length permet de limiter la longueur des libellés de substitution (par défaut, c'est la longueur du plus long mot du faux-texte).
Notez enfin que l'algorithme s'assure que la distance de Damerau-Levenshtein entre deux libellés de substitution quelconques est d'au moins 3 (valeur par défaut du paramètre obfuscation_min_distance). En clair, cela signifie que, si vous donnez en examen un exercice de conversion en relationnel basé sur un tel MCD, les erreurs de transcription d'un étudiant stressé, inattentif, illettré, dyslexique, roublard, ou tout cela à la fois, ne vous empêcheront pas de retrouver son intention première. Par exemple, au cours du processus d'obfuscation suivant:
End of explanation
%%mocodo
Quis, 01 Risus, 1N Ipsum a
Ipsum a: semper, massa
Odio, 1N Ipsum a, 0N Posuere: suscipit
Ac, 01 Risus, 0N Risus
Risus: euismod, semper, dederit, ribandum
Diam leo, 1N Risus, 0N Posuere
Posuere: semper, massa
Pretium, 0N Posuere, 0N Posuere
Curae, 0N Risus, 0N Tellus: pede
METUS, 11 Tellus, 0N Posuere
Ultrices: libero
Lorem, 0N Ultrices, 0N Tellus, 0N Risus: lacus, feugiat
Tellus: domus, tempero
Explanation: L'algorithme a écarté les mots dish (confusion possible avec wash), folk (confusion possible avec milk), peer (confusion possible avec ever), hall (confusion possible avec haul), baby (confusion possible avec lady).
5. Tracé d'un MCD <a id='MCD_drawing'></a>
5.1. Insertion manuelle d'espacements <a id='insertion_manuelle_d_espacements'></a>
Le tracé réalisé par Mocodo pour des MCD de plusieurs rangées laisse parfois à désirer :
End of explanation
%%mocodo
Quis, 01 Risus, 1N Ipsum a
Ipsum a: semper, massa
Odio, 1N Ipsum a, 0N Posuere: suscipit
Ac, 01 Risus, 0N Risus
Risus: euismod, semper, dederit, ribandum
Diam leo, 1N Risus, 0N Posuere
Posuere: semper, massa
Pretium, 0N Posuere, 0N Posuere
:
:
Curae, 0N Risus, 0N Tellus: pede
METUS, 11 Tellus, 0N Posuere
:
Ultrices: libero
Lorem, 0N Ultrices, 0N Tellus, 0N Risus: lacus, feugiat
:
Tellus: domus, tempero
Explanation: On voit que, par défaut, Mocodo centre les rangées qui contiennent moins de boîtes que les autres. Cela donne un bon résultat pour la première rangée, mais pas pour la troisième.
L'utilisateur peut cependant spécifier les espacements qu'il désire en complétant les rangées les moins fournies, par des boîtes invisibles dont le seul rôle est de « pousser » les autres à l'emplacement voulu. Ainsi, il va préciser que l'association Curae doit commencer sur la troisième colonne en insérant des lignes réduites au caractère deux-points, et en profiter pour insérer un espace entre Lorem et Tellus :
End of explanation
%%mocodo --fit
Lacus, 01 Blandit, 1N Elit
Elit: ligula, tellus
Metus, 1N Elit, 0N Congue: nibh
    
Bibendum, 01 Blandit, 0N Blandit
Blandit: consequat, ligula, nibh, consequat
Ipsum, 1N Blandit, 0N Congue
Congue: ligula, tellus
Augue, 0N Congue, 0N Congue
Velit, 0N Blandit, 0N Nonummy: sollicitudin
    
DF, 11 Nonummy, 0N Congue
Posuere: pede
Vivamus, 0N Posuere, 0N Nonummy, 0N Blandit: eleifend, iaculis
    
Nonummy: consequat, ligula
Explanation: Il est possible de « compresser » les suites de deux-points en supprimant les retours-chariots, autrement dit, de remplacer $n$ lignes réduites à deux-points par une ligne réduite à une séquence de $n$ deux-points. Ce raccourci est illustré dans le prochain exemple.
5.2. Ajustement automatique dans une grille minimale <a id='reformatage_automatique'></a>
Nouveauté de la version 2.2. On cherche en général à faire tenir le MCD dans la plus petite grille possible, tout en maintenant un rapport « équilibré » entre hauteur et largeur. Par exemple, un MCD de 13 boîtes (entités ou associations) peut tenir dans les grilles:
$13\times1$;
$7\times2$, ce qui laisse 1 case vide;
$5\times3$, ce qui laisse 2 cases vides;
$4\times4$, ce qui laisse 3 cases vides;
etc.
Les deux premières grilles étant non équilibrées, on retiendra la plus petite des suivantes, de dimensions $5\times3$.
La table ci-dessous énumère les dimensions des grilles minimales d'équilibre supérieur à 0,5 pour tous les MCD comportant moins de 100 boîtes:
|  | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 1 | 1 |  |  |  |  |  |  |  |  |  |  |  |  |
| 2 |  | 2, 3, 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 |  |  |
On peut y vérifier par exemple que le MCD de taille 13 se trouve effectivement aux coordonnées (5, 3).
Avec l'option --fit, Mocodo est maintenant capable de reformater automatiquement un MCD pour le faire entrer dans la grille minimale correspondante:
End of explanation
%%mocodo --arrange
Lacus, 01 Blandit, 1N Elit
Elit: ligula, tellus
Metus, 1N Elit, 0N Congue: nibh
Bibendum, 01 Blandit, 0N Blandit
Blandit: consequat, ligula, nibh, consequat
Ipsum, 1N Blandit, 0N Congue
Congue: ligula, tellus
Augue, 0N Congue, 0N Congue
Velit, 0N Blandit, 0N Nonummy: sollicitudin
DF, 11 Nonummy, 0N Congue
Posuere: pede
Vivamus, 0N Posuere, 0N Nonummy, 0N Blandit: eleifend, iaculis
Nonummy: consequat, ligula
::
Explanation: L'algorithme se contente de supprimer ou d'insérer des sauts de ligne dans le texte-source, sans modifier l'ordre des clauses. On devra donc encore en général opérer sur le résultat un réarrangement automatique (voir plus loin).
End of explanation
%%mocodo --fit=1
Lacus, 01 Blandit, 1N Elit
Elit: ligula, tellus
Metus, 1N Elit, 0N Congue: nibh
    
Bibendum, 01 Blandit, 0N Blandit
Blandit: consequat, ligula, nibh, consequat
Ipsum, 1N Blandit, 0N Congue
Congue: ligula, tellus
Augue, 0N Congue, 0N Congue
Velit, 0N Blandit, 0N Nonummy: sollicitudin
    
DF, 11 Nonummy, 0N Congue
Posuere: pede
Vivamus, 0N Posuere, 0N Nonummy, 0N Blandit: eleifend, iaculis
    
Nonummy: consequat, ligula
%%mocodo --arrange
Lacus, 01 Blandit, 1N Elit
Elit: ligula, tellus
Metus, 1N Elit, 0N Congue: nibh
Bibendum, 01 Blandit, 0N Blandit
Blandit: consequat, ligula, nibh, consequat
Ipsum, 1N Blandit, 0N Congue
Congue: ligula, tellus
Augue, 0N Congue, 0N Congue
Velit, 0N Blandit, 0N Nonummy: sollicitudin
DF, 11 Nonummy, 0N Congue
Posuere: pede
Vivamus, 0N Posuere, 0N Nonummy, 0N Blandit: eleifend, iaculis
Nonummy: consequat, ligula
:::
Explanation: Si ce réarrangement échoue ou laisse à désirer, il est possible de spécifier chacune des ièmes grilles suivantes avec l'option --fit=i:
End of explanation
%%mocodo
Augue, 0N Congue, 0N Congue
Congue: ligula, tellus
DF, 11 Nonummy, 0N Congue
Nonummy: consequat, ligula
Posuere: pede
:
Metus, 1N Elit, 0N Congue: nibh
Ipsum, 1N Blandit, 0N Congue
Velit, 0N Blandit, 0N Nonummy: sollicitudin
Vivamus, 0N Posuere, 0N Nonummy, 0N Blandit: eleifend, iaculis
:
Elit: ligula, tellus
Lacus, 01 Blandit, 1N Elit
Blandit: consequat, ligula, nibh, consequat
Bibendum, 01 Blandit, 0N Blandit
Explanation: Remarques.
- Quand le paramètre de --fit définit une grille trop grande, le réarrangement automatique retombe fréquemment sur une sous-grille de celle-ci.
- Dans Mocodo online, cliquer sur le bouton de réarrangement automatique enchaîne directement les opérations --fit et --arrange.
5.3. Basculement des cardinalités et inflexion des pattes rectilignes <a id='inflexion'></a>
End of explanation
%%mocodo --shapes trebuchet
Velit, 0N Blandit, 0N Nonummy: sollicitudin
Blandit: consequat, ligula, nibh, consequat
:::
Nonummy: consequat, ligula
    
Vivamus, 0N Nonummy, 0N Blandit: eleifend, iaculis
Explanation: Nouveauté de la version 2.1. Mocodo est capable de détecter certaines configurations de pattes dont les cardinalités présentent un risque élevé de collision. Il procède alors à deux types d'ajustements:
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 MCD ci-dessus, la présence de la patte oblique CONGUE-IPSUM envoie les cardinalités de CONGUE-METUS et CONGUE-DF à l'opposé de leur position par défaut (à droite d'une patte verticale ou en bas d'une patte horizontale).
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 BLANDIT-VIVAMUS 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 minimiser les risques de collision, et non les prévenir totalement. Ils peuvent même en produire d'autres. Ainsi, autour des entités particulièrement pattues, des collisions qui ne se seraient pas produites par défaut seront parfois observées. L'utilisateur a alors deux possibilités:
modifier à la main les coordonnées des cardinalités en conflit, comme expliqué dans la section suivante;
diminuer la valeur du paramètre --flex (par défaut, 0.75) pour réduire la courbure de l'inflexion automatique, en allant jusqu'à 0 pour la désactiver totalement (exemple).
5.4. Retouches fines <a id='retouches_fines'></a>
5.4.1. Par modification du script intermédiaire <a id='par_modification_du_script_intermediaire'></a>
Mocodo, au lieu de générer directement un dessin statique, génère d'abord un script Python, qui lui-même générera le dessin attendu. Cela se fait de façon transparente, sans intervention de l'utilisateur. L'avantage de cette couche supplémentaire est que le script intermédiaire exprime la plupart des positions, non en absolu, mais en relation à d'autres positions, peu nombreuses et qui constituent de fait les véritables paramètres du dessin. Sa capacité à évaluer des formules le rend beaucoup plus souple et puissant que si les valeurs résultantes étaient stockées en dur.
Le script intermédiaire s'appelle par défaut:
sandbox_nodebox.py sur Mac OS X avec NodeBox 1.x installé ;
sandbox_svg.py dans toutes les autres configurations.
Montrons comment retoucher le MCD suivant:
End of explanation
%%file mocodo_notebook/replace.tmp
(width,height) = (340,153)     # réduire de 40 pixels en largeur et de 80 pixels en hauteur
cx = {
    u"Velit"  :  170,          # décaler de 20 pixels vers la gauche
    u"Blandit":   47,
    u"Nonummy":  293,          # décaler de 40 pixels vers la gauche
    u"Vivamus":  170,          # décaler de 20 pixels vers la gauche
}
cy = {
    u"Velit"  :   35,
    u"Blandit":   72,          # remonter de 40 pixels
    u"Nonummy":   72,          # remonter de 40 pixels
    u"Vivamus":  109,          # remonter de 40 pixels
}
shift = {
    u"Velit,Blandit"  :  -30, # mettre la cardinalité au-dessus de la patte
    u"Velit,Nonummy"  :  -30, # mettre la cardinalité au-dessus de la patte
    u"Vivamus,Nonummy":    0,
    u"Vivamus,Blandit":    0,
}
Explanation: Si on ouvre le script intermédiaire avec un éditeur de texte, on verra que ses premières instructions exposent les principaux paramètres de position:
python
(width,height) = (384,233)
cx = {
    u"Velit"  :  192,
    u"Blandit":   47,
    u"Nonummy":  337,
    u"Vivamus":  192,
}
cy = {
    u"Velit"  :   35,
    u"Blandit":  112,
    u"Nonummy":  112,
    u"Vivamus":  189,
}
shift = {
    u"Velit,Blandit"  :    0,
    u"Velit,Nonummy"  :    0,
    u"Vivamus,Nonummy":    0,
    u"Vivamus,Blandit":    0,
}
Un couple de dimensions width et height définit la taille du MCD;
deux dictionnaires 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.
Voici les modifications que nous décidons d'apporter au fichier (ignorez la première ligne):
End of explanation
!cd mocodo_notebook ; sed -i.tmp -e '10,28d' -e '8r replace.tmp' sandbox_svg.py ; rm *.tmp
!python mocodo_notebook/sandbox_svg.py
from IPython.core.display import SVG
SVG("mocodo_notebook/sandbox.svg")
Explanation: Sous Nodebox, il suffit alors de choisir Run dans le menu Python.
Si vous travaillez avec des fichiers SVG, il faut exécuter le script ..._svg.py. Il regénère alors le fichier SVG qui contient le dessin. Il ne reste plus qu'à l'ouvrir, par exemple avec un navigateur.
Les lignes suivantes (qu'il est inutile de comprendre) permettent de faire la même chose à l'intérieur de cette documentation.
End of explanation
%%mocodo
Assistas, 01 Hci poilu, 0N Hci poilu
Hci poilu: graffiti, champignon, troussa, graffiti
Rayonnait, 0N Hci poilu, 0N Lappa: monobloc
Brisa: souffrait
Pillards, 0N Brisa, 0N Lappa, 0N Hci poilu: disions, lascar
Lappa: graffiti, champignon
Puni, 11 Lappa, 0N Lappa
Explanation: Selon le même principe, on peut faire glisser les flèches le long des arcs (dictionnaire ratio) ou modifier les couleurs (dictionnaire colors).
Cette technique inhabituelle nous semble une application naturelle du dynamisme du langage Python. Mais c'est à vous de décider si vous êtes plus efficace en ajustant des valeurs numériques, ou en faisant glisser des objets dans votre cliquodrome favori, comme décrit dans la section suivante.
5.4.2. Par édition de la sortie au format SVG <a id='par_edition_de_la_sortie_au_format_svg'></a>
Un fichier SVG peut être visualisé dans tout navigateur moderne.
Pour aller au-delà de la simple visualisation, il faudra faire appel à un logiciel de dessin vectoriel dédié, comme Inkscape (libre) ou Adobe Illustrator, Freehand, CorelDRAW, etc.
Les éléments du fichier SVG produit pourront alors être repositionnés à la souris. Certains sont associés, pour permettre leur déplacement en bloc. Dans la version actuelle, les liens ne suivent pas ces déplacements, ce qui peut obliger à des manipulations supplémentaires.
5.5. Réarrangement par symétrie <a id='rearrangement_par_symetrie'></a>
Mocodo permet de calculer facilement le symétrique d'un MCD, par exemple celui donné ci-dessous:
End of explanation
%%mocodo --flip=v
Assistas, 01 Hci poilu, 0N Hci poilu
Hci poilu: graffiti, champignon, troussa, graffiti
Rayonnait, 0N Hci poilu, 0N Lappa: monobloc
Brisa: souffrait
Pillards, 0N Brisa, 0N Lappa, 0N Hci poilu: disions, lascar
Lappa: graffiti, champignon
Puni, 11 Lappa, 0N Lappa
Explanation: Nouveauté de la version 2.0.20. Pour remplacer le texte de la cellule par le résultat de son évaluation, ajoutez l'option --replace.
5.5.1. Symétrie selon l'axe vertical <a id='symetrie_selon_l_axe_vertical'></a>
End of explanation
%%mocodo --flip=h
Assistas, 01 Hci poilu, 0N Hci poilu
Hci poilu: graffiti, champignon, troussa, graffiti
Rayonnait, 0N Hci poilu, 0N Lappa: monobloc
Brisa: souffrait
Pillards, 0N Brisa, 0N Lappa, 0N Hci poilu: disions, lascar
Lappa: graffiti, champignon
Puni, 11 Lappa, 0N Lappa
Explanation: 5.5.2. Symétrie selon l'axe horizontal <a id='symetrie_selon_l_axe_horizontal'></a>
End of explanation
%%mocodo --flip=d
Assistas, 01 Hci poilu, 0N Hci poilu
Hci poilu: graffiti, champignon, troussa, graffiti
Rayonnait, 0N Hci poilu, 0N Lappa: monobloc
Brisa: souffrait
Pillards, 0N Brisa, 0N Lappa, 0N Hci poilu: disions, lascar
Lappa: graffiti, champignon
Puni, 11 Lappa, 0N Lappa
Explanation: 5.5.3. Symétries selon les diagonales (transposition) <a id='symetries_selon_les_diagonales_transposition'></a>
End of explanation
%%mocodo --flex=0
AMET, 11> LOREM, 01 CONSECTETUER: adipiscing
CONSECTETUER: elit, sed
TORTOR, 0N RISUS, 11 DIGNISSIM, 1N CONSECTETUER: nec
DF, 11 RISUS, 0N RISUS
LOREM: ipsum, dolor, sit
SOLLICITUDIN, 0N SUSPENDISSE, 0N CONSECTETUER, 0N LOREM: lectus
DIGNISSIM: ligula, massa, varius
RISUS: ultricies, _cras, elementum
DF1, 11 LOREM, 1N SUSPENDISSE
SUSPENDISSE: diam
MAECENAS, 1N DIGNISSIM, 1N DIGNISSIM
SEMPER, 0N RISUS, 1N DIGNISSIM
Explanation: Pour une symétrie selon l'anti-diagonale, appliquer successivement les trois symétries précédentes dans n'importe quel ordre.
5.5.3.1. Astuce: édition rapide d'une ou plusieurs colonnes <a id='transposition_trick'></a>
La transposition peut être utilisée pour réaliser plus facilement certaines opérations d'édition en colonne, en particulier sous Mocodo online. Par exemple, supposons que l'on souhaite décaler vers le haut la dernière colonne du MCD ci-dessous:
End of explanation
%%mocodo --no_mcd --flip=d
AMET, 11> LOREM, 01 CONSECTETUER: adipiscing
CONSECTETUER: elit, sed
TORTOR, 0N RISUS, 11 DIGNISSIM, 1N CONSECTETUER: nec
DF, 11 RISUS, 0N RISUS
LOREM: ipsum, dolor, sit
SOLLICITUDIN, 0N SUSPENDISSE, 0N CONSECTETUER, 0N LOREM: lectus
DIGNISSIM: ligula, massa, varius
RISUS: ultricies, _cras, elementum
DF1, 11 LOREM, 1N SUSPENDISSE
SUSPENDISSE: diam
MAECENAS, 1N DIGNISSIM, 1N DIGNISSIM
SEMPER, 0N RISUS, 1N DIGNISSIM
Explanation: On commence par transposer:
End of explanation
%%mocodo --flip=d
:
AMET, 11> LOREM, 01 CONSECTETUER: adipiscing
LOREM: ipsum, dolor, sit
DF1, 11 LOREM, 1N SUSPENDISSE
:
CONSECTETUER: elit, sed
SOLLICITUDIN, 0N SUSPENDISSE, 0N CONSECTETUER, 0N LOREM: lectus
SUSPENDISSE: diam
:
TORTOR, 0N RISUS, 11 DIGNISSIM, 1N CONSECTETUER: nec
DIGNISSIM: ligula, massa, varius
MAECENAS, 1N DIGNISSIM, 1N DIGNISSIM
DF, 11 RISUS, 0N RISUS
RISUS: ultricies, _cras, elementum
SEMPER, 0N RISUS, 1N DIGNISSIM
Explanation: Il suffit alors d'insérer un deux-points au début de chacune des trois premières rangées, puis de retransposer dans l'autre sens:
End of explanation
%%mocodo --arrange --seed=1
Lacus, 01 Blandit, 1N Elit
Elit: ligula, tellus
Metus, 1N Elit, 0N Congue: nibh
Bibendum, 01 Blandit, 0N Blandit
Blandit: consequat, ligula, nibh, consequat
Ipsum, 1N Blandit, 0N Congue
Congue: ligula, tellus
Augue, 0N Congue, 0N Congue
Velit, 0N Blandit, 0N Nonummy: sollicitudin
DF, 11 Nonummy, 0N Congue
Posuere: pede
Vivamus, 0N Posuere, 0N Nonummy, 0N Blandit: eleifend, iaculis
Nonummy: consequat, ligula
Explanation: On peut se convaincre en examinant le nouveau texte d'entrée que le résultat aurait été beaucoup plus pénible à obtenir en procédant directement.
5.6. Réarrangement automatique <a id='rearrangement_automatique'></a>
Il est possible de demander à Mocodo de chercher tout seul une « bonne » permutation des boîtes, ce qui à la main deviendrait vite difficile.
Le critère que nous avons retenu pour évaluer la qualité d'une permutation est double:
les liens ne doivent pas se couper;
leur longueur cumulée doit être minimale.
Trois algorithmes sont fournis:
un algorithme exact (bb, pour Branch & Bound), qui ne trouve que des solutions satisfaisant aux deux critères;
un algorithme approché (ga, pour Genetic Algorithm), réservé aux cas où il est impossible de satisfaire au premier critère. L'algorithme va alors chercher des solutions où les liens se coupent seulement le moins possible;
un autre algorithme exact (lp, pour Linear Programming), mais reposant sur un solveur générique (actuellement, CPLEX ou Gurobi).
Nouveauté de la version 2.0.20. Pour remplacer le texte de la cellule par le résultat de son évaluation, ajoutez l'option --replace.
5.6.1. Méthode exacte spécialisée <a id='methode_exacte'></a>
5.6.1.1. À l'intérieur d'une grille prédéfinie <a id='non_organic'></a>
Voici à titre d'exemple un résultat trouvé par l'algorithme exact, suivi du MCD correspondant:
End of explanation
%%mocodo --arrange --seed=4
Lacus, 01 Blandit, 1N Elit
Elit: ligula, tellus
Metus, 1N Elit, 0N Congue: nibh
Bibendum, 01 Blandit, 0N Blandit
Blandit: consequat, ligula, nibh, consequat
Ipsum, 1N Blandit, 0N Congue
Congue: ligula, tellus
Augue, 0N Congue, 0N Congue
Velit, 0N Blandit, 0N Nonummy: sollicitudin
DF, 11 Nonummy, 0N Congue
Posuere: pede
Vivamus, 0N Posuere, 0N Nonummy, 0N Blandit: eleifend, iaculis
Nonummy: consequat, ligula
Explanation: Le réarrangement automatique se fera toujours à l'intérieur d'une grille ayant autant de colonnes et de rangées que le texte de départ (ici, $4\times5$). On peut quelquefois essayer de réduire cette grille. Par exemple, le MCD ci-dessus comporte 13 boîtes. Elles pourraient donc théoriquement tenir dans une grille $5\times3=15$. Modifions le texte à la main pour avoir 3 blocs d'au plus 5 lignes, et vérifier qu'un tel réarrangement est possible:
End of explanation
%%mocodo --arrange --organic --seed=14
Lacus, 01 Blandit, 1N Elit
Elit: ligula, tellus
Metus, 1N Elit, 0N Congue: nibh
Bibendum, 01 Blandit, 0N Blandit
Blandit: consequat, ligula, nibh, consequat
Ipsum, 1N Blandit, 0N Congue
Congue: ligula, tellus
Augue, 0N Congue, 0N Congue
Velit, 0N Blandit, 0N Nonummy: sollicitudin
DF, 11 Nonummy, 0N Congue
Posuere: pede
Vivamus, 0N Posuere, 0N Nonummy, 0N Blandit: eleifend, iaculis
Nonummy: consequat, ligula
Explanation: 5.6.1.2. Par croissance organique <a id='organic'></a>
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.
End of explanation
%%mocodo
Augue, 0N Congue, 0N Congue
Congue: ligula, tellus
:
DF, 11 Nonummy, 0N Congue
Metus, 1N Elit, 0N Congue: nibh
Ipsum, 1N Blandit, 0N Congue
Velit, 0N Blandit, 0N Nonummy: sollicitudin
Nonummy: consequat, ligula
Elit: ligula, tellus
Lacus, 01 Blandit, 1N Elit
Blandit: consequat, ligula, nibh, consequat
Vivamus, 0N Posuere, 0N Nonummy, 0N Blandit: eleifend, iaculis
::
Bibendum, 01 Blandit, 0N Blandit
Posuere: pede
Explanation: Cela donne un autre plongement du MCD sur une grille $4\times5$, ce qui comme on l'a vu n'est pas optimal. En fait, le résultat d'une réorganisation organique peut souvent être trivialement amélioré, par exemple ici en faisant pivoter Augue et en décalant DF:
End of explanation
%%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
Explanation: De fait, le réarrangement organique fournit souvent un bon point de départ pour chercher soi-même une permutation plus esthétique ou mettant en évidence certaines propriétés du MCD.
#### Limitations
Pour permettre au programme de rendre plus rapidement de bonnes solutions, on a borné arbitrairement le nombre d'appels à la fonction chargée de construire une permutation à partir du placement de la première boîte. De ce fait, l'algorithme n'est plus exact, en ce sens que la meilleure solution peut occasionnellement lui échapper. Si vous soupçonnez que c'est le cas, faites un autre essai, éventuellement en augmentant la borne (par défaut 10000):
shell
mocodo --arrange --call_limit=100000
Et pour en avoir complètement le cœur net, lancez le solveur de programmes linéaires:
shell
mocodo --arrange=lp
D'autre part, le réarrangement exact ne fonctionnera jamais sur les MCD:
non planaires;
planaires n'admettant aucun plongement planaire dans les limites de la grille spécifiée.
Rappelons qu'un graphe est dit planaire lorsqu'il en existe au moins un arrangement sans croisement. Le graphe non planaire comportant le plus petit nombre de liens est connu sous le nom de $K_{3,3}$:
End of explanation
%%mocodo --arrange
DIGNISSIM: nec sem, nunc, vulputate
IMPERDIET: a praesent, nibh, semper
TINCIDUNT: faucibus, orci, cursus
RHONCUS, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT
SODALES, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT
QUIS ENIM, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT
Explanation: Son réarrangement échoue donc:
End of explanation
%%mocodo --arrange=ga --seed=42
DIGNISSIM: nec sem, nunc, vulputate
IMPERDIET: a praesent, nibh, semper
TINCIDUNT: faucibus, orci, cursus
RHONCUS, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT
SODALES, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT
QUIS ENIM, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT
Explanation: 5.6.2. Méthode heuristique <a id='methode_heuristique'></a>
Dans tous ces cas, on pourra se rabattre sur l'heuristique. Celle-ci, au lieu d'interdire les croisements, cherche simplement à en minimiser le nombre.
End of explanation
%%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
Explanation: L'amélioration ne saute pas forcément aux yeux, mais il n'y a plus que 3 croisements au lieu de 9. Ce plongement constitue en tout cas un bon point de départ pour un réarrangement manuel. Pour arriver à une représentation lisible, il ne reste plus qu'à insérer quelques boîtes invisibles:
End of explanation
%%mocodo --arrange=lp --engine=cplex
Lacus, 01 Blandit, 1N Elit
Elit: ligula, tellus
Metus, 1N Elit, 0N Congue: nibh
Bibendum, 01 Blandit, 0N Blandit
Blandit: consequat, ligula, nibh, consequat
Ipsum, 1N Blandit, 0N Congue
Congue: ligula, tellus
Augue, 0N Congue, 0N Congue
Velit, 0N Blandit, 0N Nonummy: sollicitudin
DF, 11 Nonummy, 0N Congue
Posuere: pede
Vivamus, 0N Posuere, 0N Nonummy, 0N Blandit: eleifend, iaculis
Nonummy: consequat, ligula
Explanation: 5.6.3. Méthode exacte générique <a id='methode_exacte_generique'></a>
Nouveauté de la version 2.2. Cette méthode, invoquée avec le paramètre arrange=lp, trouvera nécessairement l'une des meilleures solutions, pour peu que celle-ci existe et que vous ayez du temps devant vous.
L'idée est de convertir le problème en programme linaire, de l'envoyer à un solveur externe, et de récupérer le résultat à la fin.
Actuellement, le solveur peut être CPLEX:
End of explanation
%%mocodo --arrange=lp --engine=gurobi
Lacus, 01 Blandit, 1N Elit
Elit: ligula, tellus
Metus, 1N Elit, 0N Congue: nibh
Bibendum, 01 Blandit, 0N Blandit
Blandit: consequat, ligula, nibh, consequat
Ipsum, 1N Blandit, 0N Congue
Congue: ligula, tellus
Augue, 0N Congue, 0N Congue
Velit, 0N Blandit, 0N Nonummy: sollicitudin
DF, 11 Nonummy, 0N Congue
Posuere: pede
Vivamus, 0N Posuere, 0N Nonummy, 0N Blandit: eleifend, iaculis
Nonummy: consequat, ligula
Explanation: ... Ou Gurobi:
End of explanation
%%mocodo --mld
LACUS: blandit, elit
LIGULA, 0N LACUS, 1N EROS, 0N TELLUS: metus
EROS: congue, nibh, tincidunt    
BIDENDUM, 0N TELLUS, 1N TELLUS: consequat
TELLUS: integer, odio
FAUCIBUS, 1N TELLUS, 0N EROS: ipsum
Explanation: Remarques.
Ces résultats, même s'ils semblent différents, sont exactement équivalents en termes de longueur cumulée des liens.
Les deux solveurs sont des logiciels commerciaux, qui ne sont donc pas livrés avec Mocodo. Toutefois, si vous êtes étudiant ou chercheur en université, vous pouvez faire une demande de licence académique gratuite auprès de leurs éditeurs respectifs.
Actuellement, le temps de résolution par solveur générique est souvent rédhibitoire. L'option n'a été introduite qu'à des fins de recherche, et ne présente pas d'intérêt pratique pour l'utilisateur final.
5.7. Conversion dans d'autres formats graphiques <a id='conversion_dans_d_autres_formats_graphiques'></a>
L'exportation est déléguée à votre éditeur SVG ou à Nodebox. Le format PDF assure la meilleure qualité, aussi bien pour la visualisation sur écran, que pour la projection ou l'impression. Si vous devez absolument utiliser un format bitmap, préférez PNG ou GIF.
6. Passage au relationnel <a id='passage_au_relationnel'></a>
Le passage au relationnel se fait en deux étapes:
- la création d'une représentation interne complète du MLD;
- la traduction de celle-ci en une représentation externe dans le ou les formats de sortie souhaités.
6.1. Construction de la représentation interne <a id='construction_de_la_representation_interne'></a>
6.1.1. Cas réguliers <a id='regular_mld_conversion'></a>
La séquence d'opérations suivante est réalisée:
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 clef primaire de la relation.
Toute relation issue d'une entité faible est renforcée, c'est-à-dire que la clef primaire de l'entité qu'elle détermine fonctionnellement vient s'adjoindre à sa clef primaire, au besoin de façon récursive.
Les associations sont traitées ainsi:
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 clef primaire est constituée de l'ensemble des clefs primaires des relations issues des entités mises en jeu;
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:
en tant que clefs étrangères, l'ensemble des clefs primaires des autres entités mises en jeu;
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).
6.1.1.1. Exemple du traitement des associations non DF <a id='exemple_du_traitement_des_associations_non_df'></a>
Illustrons le premier cas du troisième point sur un MCD comportant des associations triple, double et réflexive dont toutes les cardinalités maximales sont à N.
End of explanation
%%mocodo --mld
LACUS: blandit, elit
LIGULA, 11 LACUS, 1N EROS, 0N TELLUS: metus
EROS: congue, nibh, tincidunt    
BIDENDUM, 0N TELLUS, 11 TELLUS: consequat
TELLUS: integer, odio
FAUCIBUS, 11 TELLUS, 01 EROS: ipsum
Explanation: Notez la désambiguïsation automatique par numérotation du deuxième attribut de BIBENDUM.
6.1.1.2. Exemple du traitement des associations DF <a id='exemple_du_traitement_des_associations_df'></a>
Illustrons l'autre cas sur un MCD quasiment identique, à ceci près que certaines cardinalités maximales ont été ramenées à 1. En tant que dépendances fonctionnelles, toutes les associations vont alors disparaître.
End of explanation
%%mocodo --mld --relations diagram
Appartement: num appart., nb pièces appart.
Composer, 0N Étage, _11 Appartement
Étage: num étage, nb appart. étage
Appartenir, 1N Immeuble, _11 Étage
Immeuble: num immeuble, nb étages immeuble
Se situer, 0N Rue, _11 Immeuble
Rue: code rue, nom rue
Explanation: Notez les points suivants:
- la cardinalité (1,1) est par défaut prioritaire sur (0,1) lors du traitement de l'association FAUCIBUS;
- Mocodo n'impose pas de borne supérieure à l'arité d'une association de dépendance fonctionnelle, ici par exemple LIGULA est ternaire (alternative: modélisation par plusieurs dépendances fonctionnelles);
- Mocodo n'interdit pas à une association de dépendance fonctionnelle de porter des attributs (alternative: les mettre dans l'entité distinguée par (1,1)).
Les deux alternatives mentionnées, plus orthodoxes mais plus lourdes, produisent de toute façon le même schéma relationnel. Autre point litigieux, cette fois non pris en charge par Mocodo: dans les dépendances fonctionnelles à double sens ((1,1) des deux côtés), la priorité est donnée de façon non spécifiée à l'un des (1,1).
6.1.1.3. Exemple du traitement des entités faibles (identification relative) <a id='weak_entities_relational'></a>
Nouveauté. Les renforcements en cascade sont correctement gérés dans tous les cas, et les renforcements cycliques produisent un message d'erreur.
End of explanation
%mocodo --input mocodo_notebook/sandbox.mld
Explanation: Dans ce joli exemple dû à Idris NEUMANN, Initiation à la conception de bases de données relationnelles avec MERISE, les renforcements successifs aboutissent à faire entrer l'identifiant de RUE dans celui de APPARTEMENT, alors même que ces entités sont séparées par non moins de trois associations.
Ce processus apparaît clairement sur le diagramme relationnel généré par la commande précédente:
End of explanation
%%mocodo --mld
Soutenir, 01 Étudiant, 0N Date: note stage
Étudiant: num. étudiant, nom, coordonnées
Date: date
Répondre de, 0N Date, 11 Étudiant, 0N Enseignant
Enseignant: num. enseignant, nom, coordonnées
Explanation: 6.1.1.4. Rétablissement explicite de la sémantique des DF disparues <a id='retablissement_semantique_df'></a>
Mocodo permet de modifier légèrement le nom d'une clef étrangère, de façon à réintroduire la sémantique perdue lors de la disparition de l'association de dépendance fonctionnelle par laquelle elle a migré.
End of explanation
%%mocodo --mld --no_mcd
Soutenir, 01 Étudiant, 0N [soutenance] Date: note stage
Étudiant: num. étudiant, nom, coordonnées
Date: date
Répondre de, 0N [visite] Date, 11 Étudiant, 0N [responsable] Enseignant
Enseignant: num. enseignant, nom, coordonnées
Explanation: Par exemple, ci-dessus, la conversion en relationnel produit dans la relation ÉTUDIANT des clefs étrangères date et date.1 qui ne peuvent être laissées en l'état. Éventuellement, on peut souhaiter expliciter la présence d'un numéro d'enseignant dans ÉTUDIANT.
Dans les deux cas, il suffit d'employer le système d'annotation de pattes introduit plus haut:
End of explanation
%%mocodo --mld
CLIENT: Réf. client, Nom, Prénom, Adresse
PASSER, 0N [ayant commandé] CLIENT, 11 [annotation ignorée] COMMANDE
COMMANDE: Num. commande, Date, Montant
INCLURE, 1N [passée] COMMANDE, 0N [commandé] PRODUIT: Quantité
PRODUIT: Réf. produit, Libellé, Prix unitaire
Explanation: De façon moins cruciale, la technique s'applique aussi aux autres types d'association:
End of explanation
%%mocodo --mld
LACUS: blandit, elit
LIGULA, 0N LACUS, 1N /EROS, 0N TELLUS: metus
EROS: congue, nibh, tincidunt
TELLUS: integer, odio
Explanation: Pour désactiver cette fonctionnalité (notamment dans le cas où vous annotez chaque cardinalité d'une explication destinée aux novices), passez l'option --disambiguation=numbers_only.
6.1.2. Cas irréguliers <a id='cas_irreguliers'></a>
Les règles de gestion peuvent parfois conduire à remettre en cause l'application mécanique de l'algorithme de conversion. Mocodo est capable de traiter certaines exceptions, pourvu qu'elles lui soient indiquées.
6.1.2.1. Réduire une clef primaire <a id='reduire_une_clef_primaire'></a>
Il arrive qu'un sous-ensemble strict de l'ensemble des identifiants des entités mises en jeu dans une association dont toutes les pattes portent la cardinalité N, suffise à constituer la clef primaire de la table issue de cette association: cela se fait facilement au niveau relationnel en faisant perdre leur caractère identifiant aux clefs n'appartenant pas à ce sous-ensemble. Pour obtenir le même résultat avec Mocodo, il suffit de préfixer les entités concernées par une barre oblique.
End of explanation
%%mocodo --mld
LACUS: blandit, elit
LIGULA, 01 LACUS, 1N /EROS: metus
EROS: congue, nibh, tincidunt
Explanation: La barre oblique de EROS n'apparaît pas dans le MCD, mais conduit à la réduction de la clef primaire de LIGULA aux seuls identifiants des deux autres entités mises en jeu.
6.1.2.2. Minimiser le nombre de champs vides <a id='minimiser_le_nombre_de_champs_vides'></a>
On a vu qu'en l'absence d'une cardinalité (1,1), Mocodo traitait par défaut la cardinalité (0,1) comme une dépendance fonctionnelle. Or, lorsque le 0 est grand devant le 1 en termes de fréquence d'apparition, la plupart des occurrences de la clef étrangère ainsi constituée restent vides. On aura alors intérêt à forcer la conversion de l'association en table. Cela se fait en préfixant d'une barre oblique l'une au moins des entités non distinguées par le (0,1).
End of explanation
%%mocodo --relations latex
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
# %load mocodo_notebook/sandbox.tex
Explanation: 6.2. Construction de représentations externes <a id='external_representations'></a>
La représentation interne peut être dérivée en représentation externe par l'application d'une spécification de format, ou gabarit (template en anglais). Les schémas relationnels affichés au-dessous des diagrammes conceptuels dans la présente section sont un exemple de sortie au format HTML.
6.2.1. Gabarits inclus dans la distribution <a id='gabarits_inclus_dans_la_distribution'></a>
6.2.1.1. Formats linéaires <a id='linear_formats'></a>
Dans sa représentation la plus compacte, un schéma relationnel s'écrit comme une suite de lignes de la forme:
RELATION ( clef_primaire, attribut_1, attribut_2, ...)
Sauf mention contraire, les MLD affichés dans ce document ont été produits par Mocodo au format HTML. Pour un autre exemple, voici la génération et l'affichage d'une sortie $\mathrm\LaTeX$:
End of explanation
%%mocodo --relations markdown_verbose
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
# %load mocodo_notebook/sandbox_verbose.md
Explanation: ```
% Copy this before \begin{document}
\usepackage[normalem]{ulem}
\newenvironment{mld}
  {\par\begin{minipage}{\linewidth}\begin{tabular}{rp{0.7\linewidth}}}
  {\end{tabular}\end{minipage}\par}
\newcommand{\relat}[1]{\textsc{#1}}
\newcommand{\attr}[1]{\emph{#1}}
\newcommand{\prim}[1]{\uline{#1}}
\newcommand{\foreign}[1]{#\textsl{#1}}
% Copy that after \begin{document}
\begin{mld}
  Client & (\prim{Réf. client}, \attr{Nom}, \attr{Prénom}, \attr{Adresse})\
  Commande & (\prim{Num commande}, \attr{Date}, \attr{Montant}, \foreign{Réf. client})\
  Inclure & (\foreign{\prim{Num commande}}, \foreign{\prim{Réf. produit}}, \attr{Quantité})\
  Produit & (\prim{Réf. produit}, \attr{Libellé}, \attr{Prix unitaire})\
\end{mld}
```
Les formats linéaires actuellement pris en charge par Mocodo sont les suivants:
| Nom | Argument | Usage du fichier généré |
|--|
| HTML | html | À ouvrir directement avec un navigateur internet ou un programme de traitement de texte (dont Microsoft Word, OpenOffice, Apple Pages, etc.). Implicite dans un Notebook. |
| $\mathrm\LaTeX$ | latex | À compiler sous $\mathrm\LaTeX$ pour une sortie de haute qualité aux formats PDF ou PostScript. |
| Markdown | markdown |  À coller dans une cellule de Notebook, dans un champ textuel de GitHub ou Stack Overflow, ou à ouvrir avec l'un des nombreux éditeurs Markdown existants. |
| Texte brut | text | À ouvrir directement avec un éditeur de texte Unicode. |
| Txt2tags | txt2tags | À compiler avec le générateur de documents Txt2tags pour une conversion dans de nombreux autres formats: HTML, XHTML, SGML, LaTeX, Lout, Man page, Wikipedia, Google Code Wiki, DokuWiki, MoinMoin, MagicPoint, PageMaker, texte brut. Non disponible sous Mocodo online. |
6.2.1.2. Formats linéaires avec explications <a id='formats_lineaires_avec_explications'></a>
Deux de ces formats, HTML et Markdown, disposent maintenant d'une version augmentée d'explications détaillées du mécanisme du passage au relationnel. Ce type de sortie, adaptable par l'enseignant, peut être utile aux étudiants qui souhaitent réviser ou travailler en autonomie.
End of explanation
%%mocodo --relations diagram
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
%mocodo --input mocodo_notebook/sandbox.mld
# %load mocodo_notebook/sandbox.mld
%%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
:
Explanation: CLIENT (<u>Réf. client</u>, Nom, Prénom, Adresse)
- Le champ Réf. client constitue la clef 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 (<u>Num commande</u>, Date, Montant, Réf. client)
- Le champ Num commande constitue la clef 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 clef étrangère. Il a migré à partir de l'entité CLIENT par l'association de dépendance fonctionnelle DF en perdant son caractère identifiant.  
INCLURE (<u>Num commande</u>, <u>Réf. produit</u>, Quantité)
- Le champ Num commande fait partie de la clef primaire de la table. C'est une clef étrangère qui a migré directement à partir de l'entité COMMANDE.
- Le champ Réf. produit fait partie de la clef primaire de la table. C'est une clef é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 (<u>Réf. produit</u>, Libellé, Prix unitaire)
- Le champ Réf. produit constitue la clef 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.
Tout ce texte est généré automatiquement, mais avec des raffinements destinés à le rendre plus lisible pour un humain. Par exemple, les trois attributs non identifiants de l'entité CLIENT sont décrits en une seule ligne au lieu de trois.
6.2.1.3. Diagramme relationnel <a id='relational_diagram'></a>
La plupart des SGBD offrent une représentation hybride (graphique / texte) de la base, sous la forme d'un ensemble de tables rectangulaires liées par des flèches. Mocodo génère maintenant un fichier d'extension .mld qu'il est capable de reprendre en entrée pour tracer ce type de graphe.
End of explanation
%%mocodo --relations diagram
:
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
:
Explanation: Si l'on ouvre le fichier généré (cf. ci-dessus), on constate que la syntaxe d'un MLD est 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 qui se notent: E1: ... a1-&gt;E2-&gt;a2.
Les boîtes invisibles automatiquement insérées une colonne sur deux aèrent le résultat de façon à laisser de la place aux flèches.
Remarquons que ce pseudo-MCD est un « point fixe » de l'opération de passage au relationnel, c'est-à-dire qu'il redonne le même MLD que le MCD de départ:
End of explanation
%mocodo --input mocodo_notebook/sandbox.mld
Explanation: Mais cette fois, comme le « MCD » d'entrée ne comporte aucune association, le diagramme relationnel généré ne comporte aucune flèche.
End of explanation
%%mocodo --title=client_commande_produit --relations=mysql
CLIENT: Réf. client [varchar(8)], Nom [varchar(20)], Adresse [varchar(40)]
DF, 0N CLIENT, 11 COMMANDE
COMMANDE: Num commande [tinyint(4)], Date [date], Montant [decimal(5,2) DEFAULT '0.00']
INCLURE, 1N COMMANDE, 0N PRODUIT: Quantité [tinyint(4)]
PRODUIT: Réf. produit [varchar(8)], Libellé [varchar(20)], Prix unitaire [decimal(5,2)]
Explanation: Le reprendre comme texte d'entrée produit donc le même diagramme, mais sans les flèches. Leur rétablissement pourrait faire l'objet d'un exercice facile.
Sous Mocodo online, vous obtiendrez le premier diagramme relationnel en trois étapes:
générez les relations correspondant au MCD de départ (vous aurez coché « diagramme relationnel » dans le menu « Options »);
copiez-collez la sortie « diagramme relationnel » à la place du texte d'entrée;
regénérez les relations.
Les relations sont placées dans le même ordre que les boîtes du MCD d'origine, mais vous devrez souvent les réorganiser (automatiquement ou manuellement) pour obtenir un résultat plus esthétique.
Le diagramme relationnel sans flèches s'obtient en répétant les étapes 2 et 3.
Les versions successives des différents fichiers étant écrasées à chaque regénération, veillez à télécharger l'archive après chaque étape si vous souhaitez garder l'ensemble.
Limitation. Les clefs étrangères composites sont actuellement représentées comme si elles étaient séparées (autant de flèches que de parties).
Nouveauté de la version 2.3.5. Les tables réduites à une clef primaire non composite sont supprimées et les éventuelles clefs étrangères correspondantes perdent leur caractère étranger. Ainsi, dans le diagramme relationnel de l'introduction, les tables MATIÈRE et DATE ont disparu et les clefs étrangères libellé matière et date ne sont pas préfixées d'un dièse ou accompagnées d'une flèche.
6.2.1.4. Sorties SQL <a id='sql_generation'></a>
Mocodo est livré avec des fichiers de spécification pour les dialectes SQL suivants:
| SGBD | Argument | Suffixe et extension |
|--|
| MySQL | --relations mysql | "_mysql.sql" |
| Oracle | --relations oracle | "_oracle.sql" |
| PostgreSQL | --relations postgresql | "_postgresql.sql" |
| SQLite | --relations sqlite | "_sqlite.sql" |
Notez que les contraintes de clefs étrangères sont ajoutées après création de l'ensemble des tables, sauf pour SQLite, qui n'impose pas d'ordre de création spécifique, et qui de toute façon ne prend pas en charge ce type d'altération.
Le type de données peut être inséré entre crochets droits après chaque attribut:
End of explanation
# %load mocodo_notebook/sandbox_mysql.sql
Explanation: Quoique ces informations supplémentaires ne soient pas apparues dans le diagramme conceptuel, elles ont été exploitées par la commande, qui a produit dans le répertoire mocodo_notebook un fichier directement exécutable par MySQL:
End of explanation
%%mocodo --title=appartements --relations=sqlite
Appartement: num appart., nb pièces appart.
Composer, 0N Étage, _11 Appartement
Étage: num étage, nb appart. étage
Appartenir, 1N Immeuble, _11 Étage
Immeuble: num immeuble, nb étages immeuble
Se situer, 0N Rue, _11 Immeuble
Rue: code rue, nom rue
# %load mocodo_notebook/sandbox_sqlite.sql
Explanation: ``sql
CREATE DATABASE IF NOT EXISTSCLIENT_COMMANDE_PRODUITDEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
USECLIENT_COMMANDE_PRODUIT`;
CREATE TABLE CLIENT (
  réf_client varchar(8),
  nom varchar(20),
  adresse varchar(40),
  PRIMARY KEY (réf_client)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE COMMANDE (
  num_commande tinyint(4),
  date date,
  montant decimal(5,2) DEFAULT '0.00',
  réf_client varchar(8),
  PRIMARY KEY (num_commande)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE INCLURE (
  num_commande tinyint(4),
  réf_produit varchar(8),
  quantité tinyint(4),
  PRIMARY KEY (num_commande, réf_produit)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE PRODUIT (
  réf_produit varchar(8),
  libellé varchar(20),
  prix_unitaire decimal(5,2),
  PRIMARY KEY (réf_produit)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE COMMANDE ADD FOREIGN KEY (réf_client) REFERENCES CLIENT (réf_client);
ALTER TABLE INCLURE ADD FOREIGN KEY (réf_produit) REFERENCES PRODUIT (réf_produit);
ALTER TABLE INCLURE ADD FOREIGN KEY (num_commande) REFERENCES COMMANDE (num_commande);
```
Nouveauté de la version 2.0.17. Les clefs étrangères composites sont gérées (cf. issue 14) et les types manquants remplacés par VARCHAR(42):
End of explanation
%%mocodo --no_mcd --relations=markdown_data_dict
CLIENT: Réf. client [varchar(8)], Nom [varchar(20)], Adresse [varchar(40)]
DF, 0N CLIENT, 11 COMMANDE
COMMANDE: Num commande [tinyint(4)], Date [date], Montant [decimal(5,2) DEFAULT '0.00']
INCLURE, 1N COMMANDE, 0N PRODUIT: Quantité [tinyint(4)]
PRODUIT: Réf. produit [varchar(8)], Libellé [varchar(20)], Prix unitaire [decimal(5,2)]
# %load mocodo_notebook/sandbox_data_dict.md
Explanation: ```sql
.open "APPARTEMENTS";
CREATE TABLE "APPARTEMENT" (
  "code_rue" VARCHAR(42),
  "num_immeuble" VARCHAR(42),
  "num_étage" VARCHAR(42),
  "num_appart" VARCHAR(42),
  "nb_pièces_appart" VARCHAR(42),
  PRIMARY KEY ("code_rue", "num_immeuble", "num_étage", "num_appart"),
  FOREIGN KEY ("code_rue", "num_immeuble", "num_étage") REFERENCES "ÉTAGE" ("code_rue", "num_immeuble", "num_étage")
);
CREATE TABLE "ÉTAGE" (
  "code_rue" VARCHAR(42),
  "num_immeuble" VARCHAR(42),
  "num_étage" VARCHAR(42),
  "nb_appart_étage" VARCHAR(42),
  PRIMARY KEY ("code_rue", "num_immeuble", "num_étage"),
  FOREIGN KEY ("code_rue", "num_immeuble") REFERENCES "IMMEUBLE" ("code_rue", "num_immeuble")
);
CREATE TABLE "IMMEUBLE" (
  "code_rue" VARCHAR(42),
  "num_immeuble" VARCHAR(42),
  "nb_étages_immeuble" VARCHAR(42),
  PRIMARY KEY ("code_rue", "num_immeuble"),
  FOREIGN KEY ("code_rue") REFERENCES "RUE" ("code_rue")
);
CREATE TABLE "RUE" (
  "code_rue" VARCHAR(42),
  "nom_rue" VARCHAR(42),
  PRIMARY KEY ("code_rue")
);
```
6.2.1.5. Dictionnaire des données (bonus) <a id='dictionnaire_des_donnees_bonus'></a>
Qui peut le plus peut le moins: en utilisant un gabarit qui ignore toutes les migrations du passage au relationnel, le même algorithme est capable de construire le dictionnaire des données, à savoir la liste des attributs mis en jeu dans votre MCD, avec leur type ou toute autre annotation placée entre crochets droits après l'attribut.
End of explanation
%%mocodo --no_mcd --relations=markdown_data_dict
CLIENT: Réf. client, Nom, Prénom, Adresse
PASSER, 0N CLIENT, 11 COMMANDE
COMMANDE: Num commande, Date, Montant
INCLURE, 1N COMMANDE, 0N PRODUIT: Quantité [nombre d'unités d'un produit donné dans une commande donnée]
PRODUIT: Réf. produit, Libellé, Prix unitaire
# %load mocodo_notebook/sandbox_data_dict.md
Explanation: | Attribut | Informations |
|----------|-------------|
| Réf. client | varchar(8) |
| Nom | varchar(20) |
| Adresse | varchar(40) |
| Num commande | tinyint(4) |
| Date | date |
| Montant | decimal(5,2) DEFAULT '0.00' |
| Quantité | tinyint(4) |
| Réf. produit | varchar(8) |
| Libellé | varchar(20) |
| Prix unitaire | decimal(5,2) |
Si l'une au moins des annotations est omise, la présentation générée sera sensiblement différente:
End of explanation
%%mocodo --title client_commande_produit --relations json
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
Explanation: Réf. client
Nom
Prénom
Adresse
Num commande
Date
Montant
Quantité : nombre d'unités d'un produit donné dans une commande donnée
Réf. produit
Libellé
Prix unitaire
6.2.2. Modification ou création de nouveaux gabarits <a id='modification_ou_creation_de_nouveaux_gabarits'></a>
L'algorithme de génération d'une sortie dans tel ou tel format est totalement découplé de son entrée. 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, qui est un simple fichier JSON. Si vous n'avez aucune velléité de le faire, vous pouvez sauter cette section. Sinon, accrochez-vous, ça va devenir un peu technique.
6.2.2.1. Algorithme <a id='algorithme'></a>
Pour apprendre à spécifier un format, le mieux est d'étudier les gabarits livrés dans le dossier relation_templates. Les quelques indications données ici devraient suffire à vous épargner la lecture du code proprement dit.
Chaque gabarit est un fichier JSON associant des clefs prédéfinies à des valeurs librement modifiables. Dans sa forme la plus simple, à savoir le format « texte brut », le fichier (text.json) se réduit à trois lignes:
json
{
  "extension": ".txt"
}
La clef "extension" est en effet la seule clef obligatoire d'un tel fichier. Ici, elle est associée à la valeur ".txt".
Les autres clefs possibles, toutes facultatives, appartiennent à quatre catégories:
| Catégorie | Forme de la clef | Valeur associée | Description |
|--|
| Transformation | "transform_..." | objet | Opère une recherche-remplacement, éventuellement itérée (jusqu'à ce qu'aucun remplacement ne soit plus possible), sur une partie du texte déjà généré. Les champs "search" et "replace" sont obligatoires, le champ "iterated" (booléen) est facultatif. La syntaxe est celle des expressions régulières de Python. |
| Composition | "compose_..." | chaîne de format | Interpole dans une chaîne certains identificateurs prédéfinis par une valeur dépendant du contexte en cours. La syntaxe est celle utilisée par la méthode .format de Python. |
| Concaténation | "..._separator" | chaîne | Concatène une liste de chaînes en les séparant par une chaîne donnée. |
| Clef de tri | "..._sorting_key" | objet | Extrait la clef de tri pour la liste concernée. L'expression régulière "search" contient une ou des parenthèses capturantes qui sont ensuite rappelées dans l'expression "replace" |
Voici les différentes opérations effectuées par l'algorithme, dans l'ordre de son déroulement:
Toutes les clefs absentes du gabarit sont ajoutées, avec des valeurs par défaut pertinentes.
"transform_attribute" applique une première transformation à chaque attribut (identificateur attribute). Il s'agit en général de supprimer ou remplacer les caractères interdits par le format-cible. Le résultat est référencé par un nouvel identificateur, appelé "raw_label".
Différentes capitalisations de ce libellé sont ajoutées sous les noms de "raw_label_lowercase" (minuscules),  "raw_label_uppercase" (majuscules) et  "raw_label_titlecase" (majuscules initiales).
"compose_label_disambiguated_by_annotation" crée sous le nom de "label" une copie de "raw_label", en introduisant en plus dans les clefs étrangères les annotations des pattes correspondantes. La valeur par défaut est "{raw_label} {leg_annotation}", mais pour plus de liberté on peut très bien imaginer de remplacer le label par l'annotation elle-même (avec "{leg_annotation}"). Cette composition est optionnelle: pour la désactiver, passer l'option disambiguation=numbers_only.
<a id='disambiguation_by_number'></a>"compose_label_disambiguated_by_number" différencie les libellés homonymes d'une même relation en leur ajoutant un numéro. Par exemple, et c'est la valeur par défaut, pour suffixer le libellé par un point suivi de ce numéro, on écrira: "{label}.{disambiguation_number}". L'identificateur "label" est mis à jour avec le résultat. C'est lui que l'utilisateur utilisera en général dans la suite de l'algorithme, mais il a encore accès aux variantes précédentes.
Différentes capitalisations de ce libellé sont ajoutées: "label_lowercase", "label_uppercase" et  "label_titlecase".
"transform_title" reçoit le nom du MCD. Le résultat et ses capitalisations sont associés aux identificateurs "title", "title_lowercase", "title_uppercase" et  "title_titlecase".
Ensuite, pour chacune des relations créées dans la représentation interne:
"transform_relation_name" applique une transformation au nom de la relation et l'associe, avec ses capitalisations, aux identificateurs "this_relation_name", "this_relation_name_lowercase", "this_relation_name_uppercase" et  "this_relation_name_titlecase".
Le numéro d'ordre de la relation est associé à l'identificateur "this_relation_number".
Pour chaque colonne de la relation en cours:
Si l'attribut a migré depuis une entité, le nom de la relation correspondante est associé, avec ses capitalisations, aux identificateurs "primary_relation_name", "primary_relation_name_lowercase", "primary_relation_name_uppercase" et  "primary_relation_name_titlecase". Dans le cas contraire, tous ces identificateurs sont associés à la chaîne vide.
Si l'attribut a migré par une association, le nom de celle-ci est associé, avec ses capitalisations, aux identificateurs "association_name", "association_name_lowercase", "association_name_uppercase" et  "association_name_titlecase". Dans le cas contraire, tous ces identificateurs sont associés à la chaîne vide.
la composition "compose_[attribute_nature]" est appliquée, cf. le paragraphe Composition des attributs selon leur nature. Le résultat est accumulé dans une liste de colonnes, en deux versions: dans l'ordre de leur énumération, ou triée selon la clef spécifiée dans "column_sorting_key".
"column_separator" joint chacune de ces listes de chaînes et associe le résultat à l'identificateur "columns" et "sorted_columns" (respectivement).
"compose_relation" construit une relation complète avec tous ses attributs. Par exemple, et c'est la valeur par défaut, "{this_relation_name} ({columns})" est utilisé dans les formats linéaires.
"transform_single_column_relation" s'applique à ce dernier résultat lorsque la relation est réduite à un seul attribut (l'usage est d'en proposer la suppression en la mettant en commentaire).
"transform_relation" est appliqué systématiquement, et le résultat est accumulé dans une liste de relations, en deux versions: dans l'ordre de leur énumération, ou triée selon la clef spécifiée dans "relation_sorting_key".
"relation_separator" joint chacune de ces listes de chaînes et associe le résultat à l'identificateur "relations" et "sorted_relations" (respectivement).
"compose_relational_schema" construit un schéma relationnel complet avec son titre et toutes ses relations. La valeur par défaut est simplement "{relations}".
"transform_relational_schema" applique une dernière transformation au schéma complet, et renvoie le résultat final.
6.2.2.2. Identificateurs disponibles pour la composition de chaînes <a id='identificateurs_disponibles_pour_la_composition_de_chaines'></a>
Mocodo offline est livré avec un gabarit spécialement conçu pour vous aider à en créer de nouveaux. Il vous permet de tester sur n'importe quel MCD la génération d'un objet JSON contenant la valeur de tous les identificateurs disponibles pour la composition au niveau de chaque attribut.
End of explanation
# %load -r -38 sandbox.json
Explanation: Le contexte d'un attribut donne accès à 32 identificateurs:
4 spécifiques à la base;
5 spécifiques à la relation;
23 spécifiques à l'attribut.
S'y ajoutent "columns", "sorted_columns", et "relations", "sorted_relations", qui n'ont de sens que dans le contexte de "compose_relation" et "compose_relational_schema"(respectivement).
Le fichier JSON est trop long pour être listé dans son intégralité ici, mais en voici le début, qui concerne la clef primaire Réf. client de la relation Client de la base client_commande_produit.
End of explanation
%%mocodo --mld
Riot: clue
Into, 11 Form, 1N Riot: goat
Form: land, hide
Tuck, 1N Read, 1N Form: thin
Read: wage
Explanation: json
{
  "title": "client_commande_produit",
  "title_lowercase": "client_commande_produit",
  "title_uppercase": "CLIENT_COMMANDE_PRODUIT",
  "title_titlecase": "Client_commande_produit",
  "relations": [
    {
      "this_relation_name": "CLIENT",
      "this_relation_name_lowercase": "client",
      "this_relation_name_uppercase": "CLIENT",
      "this_relation_name_titlecase": "Client",
      "this_relation_number": 1,
      "columns": [
        {
          "attribute": "Réf. client",
          "raw_label": "Réf. client",
          "raw_label_lowercase": "réf. client",
          "raw_label_uppercase": "RÉF. CLIENT",
          "raw_label_titlecase": "Réf. client",
          "disambiguation_number": null,
          "label": "Réf. client",
          "label_lowercase": "réf. client",
          "label_uppercase": "RÉF. CLIENT",
          "label_titlecase": "Réf. client",
          "primary": true,
          "foreign": false,
          "nature": "primary_key",
          "data_type": null,
          "association_name": null,
          "association_name_lower_case": null,
          "association_name_uppercase": null,
          "association_name_titlecase": null,
          "leg_annotation": null,
          "primary_relation_name": null,
          "primary_relation_name_lowercase": null,
          "primary_relation_name_uppercase": null,
          "primary_relation_name_titlecase": null
        },
Ce fragment est à première vue très redondant. En cas de doute, reportez-vous aux tests relations_tests.py dans le code-source pour un éventail de cas discriminants.
6.2.2.3. Composition des attributs selon leur nature <a id='composition_nature'></a>
La composition appliquée à un attribut est au cœur de la construction d'une représentation externe. À cette étape, la représentation interne a permis de distinguer 9 catégories d'attributs, 6 courantes et 3 exceptionnelles. Avant de pouvoir exploiter cette classification, il faut la comprendre en détail. Nous allons la présenter à travers deux exemples, le premier répertoriant tous les cas courants, le second tous les cas exceptionnels.
End of explanation
%%mocodo --mld
Riot: clue
Walk, 1N Riot, _11 Hour
Hour: book
Poll, 1N Cast, 1N /Hour
Cast: mere
Army, 1N /Busy, 01 Cast
Busy: fail
Explanation: | Identificateur | Attribut concerné | Défaut | Exemple | 
|--|--|--|--|
| compose_primary_key | identifiant resté sur place lors de la transformation d'une entité en table | "_{label}_" | land de Form |
| compose_normal_attribute | simple attribut resté sur place lors de la transformation d'une entité en table | "{label}" | hide de Form |
| compose_foreign_key | clef étrangère ayant migré par une dépendance fonctionnelle disparue, tout en perdant son caractère identifiant | "#{label}" | clue de Form |
| compose_foreign_attribute | attribut étranger ayant migré d'une dépendance fonctionnelle disparue | même valeur que compose_normal_attribute | goat de Form |
| compose_foreign_primary_key | clef étrangère primaire migré dans une association devenue table, tout en gardant son caractère identifiant  | "_#{label}_" | wage et land de Tuck |
| compose_association_attribute | simple attribut resté sur place lors de la transformation d'une association en table | même valeur que compose_normal_attribute | thin de Tuck |
End of explanation
<END_TASK>