laowantong / mocodo

Modélisation Conceptuelle de Données. Nickel. Ni souris.

Home Page:https://www.mocodo.net

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Mécanisme de suppression des tables indépendantes réduites à leur clé primaire

fduchatea opened this issue · comments

Dans un diagramme E/A, il est fréquent d'avoir des associations ternaires impliquant une entité temporelle (date, période).

Par exemple, une réservation entre une cliente, un hôtel à une date donnée :

Hotels : idH, nomH, adresseH, catH, nbChambres
Dates : dateR
Clientes : idC, nomC, prenomC, adresseC, telC
Réservations, 0n Clientes, 0n Hotels, 0n Dates : dureeR

Lors de la trduction en relationnel, il est probable que l'entité Dates ne devienne pas une relation. Mocodo le prend en compte et commente la relation Dates (dans le code Latex) :

  \textsc{Clientes} & (\prim{idC}, \attr{nomC}, \attr{prenomC}, \attr{adresseC}, \attr{telC})\\
% \textsc{Dates} & (\prim{dateR})\\
  \textsc{Hotels} & (\prim{idH}, \attr{nomH}, \attr{adresseH}, \attr{catH}, \attr{nbChambres}, \foreign{idS})\\
  \textsc{Réservations} & (\foreign{\prim{idC}}, \foreign{\prim{idH}}, \foreign{\prim{dateR}}, \attr{dureeR})\\

Par contre, dans la relation Réservations, l'attribut dateR est à la fois clé primaire et clé étrangère (aussi bien dans la sortie Latex que celle en texte brut). Comme la relation Dates n'est pas créée, je pense que cet attribut devrait être simplement clé primaire, comme ceci :

  \textsc{Clientes} & (\prim{idC}, \attr{nomC}, \attr{prenomC}, \attr{adresseC}, \attr{telC})\\
% \textsc{Dates} & (\prim{dateR})\\
  \textsc{Hotels} & (\prim{idH}, \attr{nomH}, \attr{adresseH}, \attr{catH}, \attr{nbChambres}, \foreign{idS})\\
  \textsc{Réservations} & (\foreign{\prim{idC}}, \foreign{\prim{idH}}, prim{dateR}, \attr{dureeR})\\

Dans la sortie ddiagramme relationnel, la contrainte de clé étrangère semble être désactivée :

:
Réservations: #idC->Clientes->idC, _#idH->Hotels->idH, _dateR, dureeR
:
Hotels: idH, nomH, adresseH, catH, nbChambres
:

:
Clientes: idC, nomC, prenomC, adresseC, telC
:::

Peut-on uniformiser les sorties, en choisissant idéalement de supprimer la contrainte de clé étrangère vers des entités non créées ?

Oui, bonne idée. Je pense que ça devrait être faisable sans code en modifiant seulement les fichiers de spécification présents dans le dossier relation_templates. Le format est expliqué dans la doc je crois. Si vous vous sentez capable de le faire, une PR est bienvenue. Sinon, je m'en occuperai la prochaine fois que j'aurai un peu de temps pour Mocodo.

J'ai regardé/testé et ça devrait le faire avec les gabarits (et ça fait réviser les regexp 😉 ).
Donc ok pour m'en occuper, au moins pour la sortie Latex et texte.

En y réfléchissant, je suis quand même partagé. Prenez l'exemple donné dans le README. Mocodo génère et commente les tables correspondant à DATE et à MATIÈRE. Actuellement, si je veux effectivement supprimer DATE, mais garder MATIÈRE, je dois faire les retouches suivantes :

  • Décommenter MATIÈRE.
  • Supprimer le # de #date.

Si Mocodo supprimait systématiquement les # supprimables, je devrais faire les retouches suivantes :

  • Décommenter MATIÈRE.
  • Ajouter un # à matière.

L'avantage ne me saute pas aux yeux. Il est vrai que dans ce cas, cela uniformiserait les traitements par rapport au diagramme relationnel, point que vous soulevez.

Si vous voulez restreindre le traitement suggéré aux seules entités DATE, cela introduit un cas particulier. Est-ce vraiment désirable ? Je pose la question, mais n'ai pas d'avis tranché.

Je suis d'accord qu'on peut vouloir conserver certaines entités avec une seule propriété, comme MATIERE.
En général, il est recommandé de ne pas utiliser comme clé primaire un attribut de type chaine de caractères et dont les valeurs peuvent évoluer (conceptuellement, on peut laisser un tel attribut dans le MCD et modifier la clé primaire quand on traduit en Relationnel, mais quand on utilise un outil de modélisation, pas trop le choix de prévoir ça dès le MCD).
Donc j'ai tendance à définir MATIERES(idM, nom), et elle n'est donc commentée en Relationnel.

Dans la même idée, un autre argument contre concerne les entités à plusieurs propriétés qui sont destinées à être supprimées. Par exemple :

PERIODES: dateDébut, dateFin
RESERVATIONS: idX, idY, dateDébut, dateFin

La relation PERIODES ne devrait pas être créée. Mais difficile de détecter ce cas (et ceux avec N propriétés - bien qu'assez rare), et du coup l'intérêt est limité (hormis l'uniformisation des sorties)...

Dans les avantages, on a une sortie Latex ou SQL propre (si on considère le cas DATE qui reste le cas le plus fréquent), même si on génère à nouveau (ajout d'un attribut, changement de couleur, test pour un meilleur arrangement, etc.), ce qui m'arrive assez souvent.

Une solution serait de proposer les 2 gabarits, mais pour éviter la redondance de code, il faudrait pouvoir définir un "gabarit parent" (idée que je vais détailler dans une autre issue pour ne pas mélanger).
Je pense continuer à mettre à jour le gabarit Latex - que je pourrai toujours utiliser personnellement - et on en rediscute.

Oui, très juste. PÉRIODE peut être supprimée parce qu'elle se trouve réduite à sa clé primaire, laquelle est composite et non formée de clés étrangères. Je ne sais plus quel critère j'ai utilisé pour la mise en commentaire, il faudrait que je regarde le code : si c'est « table réduite à une seule colonne », ça ne couvre pas ces cas.

Pour MATIÈRE, j'ai quand même une petite réticence sur votre modélisation. Certes, on recommande de prendre comme clés des attributs artificiels (typiquement aléatoires), en tout cas non liés aux données-métiers. Mais identifier MATIÈRE par le nom de la matière peut avoir un intérêt au moment de la saisie : le SGBD peut ouvrir un menu pop up permettant de choisir la matière dans une liste déroulante, constituée des valeurs des clés primaires dans la table MATIÈRE.

En fait, pour en revenir à Mocodo, peut-être la meilleure solution consisterait-elle à étendre la syntaxe de façon à pouvoir préciser le traitement souhaité dès la définition du MCD. Après tout, on peut déjà faire ce genre de choses en précisant sur certaines pattes quel suffixe sera ajouté à l'attribut migrant pour rétablir la sémantique d'une association disparue (p. ex., [mère] dans le MCD par défaut de mocodo.net. Ceci pour dire qu'il y a déjà un mélange entre les niveaux conceptuels et relationnels dans les « MCD » de Mocodo. Si on opte pour cette solution, il faut imaginer une syntaxe non intrusive et qui ne crée pas de problème de rétro-compatibilité.

La solution d'une duplication des gabarits, avec éventuellement héritage, est également possible, en effet.

Je ne pense avoir le temps de me replonger dans le code avant mi-décembre, cependant.

Réflexion faite, je penche vers une extension de la syntaxe du MCD, p. ex., les trois dernières lignes de l'exemple du README deviendraient :

Date: Date
+Matière: Libellé matière
Enseigner, 11 Prof, 1N Matière

Le « + » signifierait : forcer la conservation de cette table lors du passage au relationnel. Par défaut, les tables réduites à une clé primaire n'incluant aucune clé étrangère seraient supprimées, ainsi que leur # dans les tables où elles sont étrangères.

Pour la mise en commentaire, le gabarit latex.json ne commente que les tables avec un seul attribut. Mais vu la définition du search, je me demande comment c'est possible (le '.' matche n'importe quel caractère sauf retour ligne, et le '+' étant greedy, ça devrait matcher toutes les relations ?)

  "transform_single_column_relation": [
    {
      "search": "  (.+)",
      "replace": "% \\1"
    }

identifier MATIÈRE par le nom de la matière peut avoir un intérêt au moment de la saisie : le SGBD peut ouvrir un menu pop up

J'avoue ne pas souvent saisir de données via l'interface du SGBD. Mais c'est plutôt un problème technique : dans l'interface, on pourrait détecter que l'attribut référencé pointe vers une clé primaire (auto-incrémentée) et afficher en complément dans la liste la valeur d'un attribut unique de cette table pour permettre un choix pertinent (dans un monde idéal avec des contraintes définies).

Ok pour l'extension du MCD.
Pour être complet (et prendre en compte l'exemple PERIODES qui doit disparaitre), il faudrait un symbole pour les tables non conservées.
Du coup, je me demande si c'est pas trop complexe d'avoir les '+' et un symbole '-'. Peut-être se contenter d'un symbole '-' uniquement (et par défaut, ne rien supprimer lors de la transformation) ?

OK, je n'avais pas regardé. Si c'est transform_single_column_relation, ça signifie que je n'avais pas envisagé les autres cas, et il faudra probablement changer ça dans le code.

Je pense que cette regex (en tout cas) est relancée sur chaque table, donc pas de débordement possible.

À voir pour le reste.

Je n'avais pas fait attention au nom de la propriété. J'imagine que c'est au niveau de l'algo qu'on applique cette transformation uniquement aux relations à un seul attribut.

J'ai une solution qui semble fonctionner.

  • Je ne gère plus la suppression des tables au niveau des gabarits. Cela évite des acrobaties avec les expressions régulières pour « naturaliser » les clés étrangères concernées.
  • Les tables en question ne sont plus commentées, mais supprimées.
  • Si on veut empêcher la suppression, on préfixe d'un « + » les entités à préserver.

Ok pour la solution avant le traitement par les gabarits. Ca a en plus l'avantage de ne pas devoir écrire les transformations dans chaque gabarit.
J'avais écrit les transformations pour le gabarit Latex et c'est vrai que ce n'est pas forcément très maintenable :

  "transform_relational_schema": [
    {
	  "comment": "Detect and delete foreign key constraints for commented single-column relations (when placed before the constrained relation)",
      "search": "(?sm)(<SINGLE_RELATION_TO_BE_COMMENTED>(.+?)</SINGLE_RELATION_TO_BE_COMMENTED>)(.+)\\\\foreign.(.+)<CONSTRAINT_MAY_BE_DELETED>\\2</CONSTRAINT_MAY_BE_DELETED>.",
      "replace": "\\2\\3\\4",
      "iterated": true
    },
    {
	  "comment": "Detect and delete foreign key constraints for commented single-column relations (when placed after the constrained relation)",
	  "comment": ".(.+)(<SINGLE_RELATION_TO_BE_COMMENTED>\\3</SINGLE_RELATION_TO_BE_COMMENTED>)",
      "search": "(?sm)(.+)\\\\foreign.(.+?)<CONSTRAINT_MAY_BE_DELETED>(.+?)</CONSTRAINT_MAY_BE_DELETED>.(.+)(<SINGLE_RELATION_TO_BE_COMMENTED>\\3</SINGLE_RELATION_TO_BE_COMMENTED>)(.+)",
      "replace": "\\1\\2\\4\\5\\6",
      "iterated": true
    }, ...

Je testerai prochainement cette dernière version (après la rédaction des sujets d'examen).