Après le break du message précédent, je voudrais reprendre le cours de mon message du 10/11/2011 et traiter du temps et des contraintes qu’il induit, de l’identification relative et de l’invariance dans le contexte de Merise.
Début d’une visite guidée (en espérant qu'il n'y a pas trop d'erreurs dans les copier/coller...) Intéressons-nous à la règle de gestion suivante :
« Toutes les précautions sont prises sur les planning-types pour qu’un même formateur ne risque pas d’avoir deux séminaires à assurer en même temps. »
C’est une variante d’une règle plus générale (qu’on pourrait élever au rang de métarègle) :
Quelqu’un ne peut pas faire deux choses à la fois.
Règle générale et informelle mais que l’on rencontre souvent, à laquelle on ne fait pas forcément attention, et qu’il n’est pas toujours facile de garantir au plan de la modélisation conceptuelle selon Merise. Par exemple, Bloups est confronté au problème de la bilocation, car selon sa modélisation, un artiste pourrait se produire en même temps dans deux salles de spectacle différentes, à l’occasion de ses tournées de concert (rechercher le mot "bilocation" dans la discussion Billetterie en ligne). Un avion peut décoller en même temps de deux aéroports, (rechercher le mot "Schrödinger" dans la discussion avec snoopo Comment utiliser un agrégat ? Dans la même course de chevaux, il est préférable qu’un jockey ne puisse pas monter deux chevaux en même temps, et/ou que deux chevaux n’y aient pas le même numéro, etc., cf. la discussion avec lazare (Courses hippiques).
S’il est compliqué d’interdire la bilocation lors de l’étape de la modélisation conceptuelle des données, on peut heureusement rattraper le coup très facilement lors de l’étape suivante (modèle logique), à condition d’avoir pris soin de noter dans ses tablettes (et tant qu’à faire sur le diagramme conceptuel, comme dans la figure 3 ci-dessous) la contrainte selon laquelle un type séminaire ne peut pas avoir lieu en même temps dans deux sessions différentes.
Dans ce qui suit, on considèrera que l’attribut CodeSeminaire de l’entité-type de l’entité-type SEMINAIRE respecte les principes d’invariance et d’absence de sens déjà mentionnés dans la discussion. Si tel n’était pas le cas, on le doublerait d’un attribut (appelons-le IdSeminaire) qui servirait d’identifiant « principal » tandis que CodeSeminaire serait ravalé au rang d’identifiant alternatif, mais ceci n’aurait strictement aucune incidence sur la modélisation.
Revenons à nos moutons et considérons à nouveau le diagramme conceptuel relatif aux relations entre les types de séminaires et les sessions (diagramme dans lequel l’entité-type SEMINAIRE devrait s’appeler TYPE_SEMINAIRE, mais ça n’est qu’un banal problème de vocabulaire) :
L’observation d’Yves Tabourier a trait au « manque d’intérêt » des cardinalités 1,1 dans les associations-types de dimension > 2 (ternaires et au-delà). Indépendamment de l’existence de la dépendance fonctionnelle {SEMINAIRE, DATE} -> {SESSION}, du fait que la cardinalité portée par la patte connectant l’entité-type SESSION et l’association-type ternaire Planifier est une cardinalité 1,1 alors cette ternaire doit logiquement être décomposée en deux binaires :
DATE étant une pseudo entité-type qui ne sert après tout que pour pouvoir représenter la ternaire, elle peut disparaître (quant à lui, l’attribut Date migre dans l’en-tête de l’entité-type SESSION sous le nom de DateSession). Le diagramme devient :
Toutefois, en supprimant la patte qui manque d’intérêt, on perd la dépendance fonctionnelle {SEMINAIRE, DATE} → {SESSION}, c'est-à-dire qu’on perd la règle de gestion selon laquelle pour une date et un type de séminaire donnés, il n’y a qu’une session. Si l’on procède à la dérivation du diagramme conceptuel en diagramme logique, on obtient ceci :
Et il faut rattraper le coup, retrouver la règle de gestion perdue : on intervient manuellement en faisant de la paire {CodeSeminaire, DateSession} une clé alternative de la table SESSION (mickey <ak>) :
On pourrait en rester là, mais on peut s’intéresser à l’étude de variations sur le thème de base. Ainsi, on a supposé que l’attribut CodeSeminaire de l’entité-type SEMINAIRE respectait les principes d’invariance et d’absence de sens, et que si ça n’était pas le cas, on définirait un attribut IdSeminaire servant d’identifiant « principal » tandis que CodeSeminaire serait ravalé au rang d’identifiant alternatif. Si à son tour, l’attribut NumeroSession de l’entité-type de l’entité-type SESSION respecte les principes d’invariance et d’absence de sens, d’accord on peut effectivement en rester là. Sinon, on doit observer qu’il y a une incidence sur la modélisation, car changer la valeur d’un numéro de session aurait des conséquences qui pourraient être gênantes, par exemple sur les commandes (à l’image du changement de numéro Siren des entreprises évoqué précédemment) : si l’attribut NumeroSession de l’en-tête de la table SESSION change de valeur pour une ligne donnée, alors il faut répercuter ce changement dans toutes les tables qui font référence à la table SESSION (table COMMANDE par exemple). Pour éviter ce genre d’opération lourde, il est plus que fortement recommandé de définir un attribut invariant et dépourvu de sens (appelons-le IdSession), qui devienne l’identifiant de l’entité-type SESSION, l’attribut NumeroSession étant alors ravalé au rang d’identifiant alternatif :
Le diagramme logique devient le suivant (où l’on n’oublie pas de faire de la paire {CodeSeminaire, DateSession} une clé alternative, symbolisée par le mickey <ak2>) :
Note concernant la décomposition de l’association-type ternaire PLANIFIER.
Pour les courageux... Revenons sur le diagramme de la figure 1. Les diagrammes des figures 2 et suivantes sont la conséquence de l’application du principe selon lequel une ternaire dont une patte est porteuse d’une cardinalité 1,1 est à décomposer en deux binaires, avec pour effet immédiat la perte de la dépendance fonctionnelle {SEMINAIRE, DATE} -> {SESSION}. Si on ne veut pas se résoudre à décomposer, on peut tenter de mettre en œuvre le diagramme conceptuel suivant :
Mais il existe maintenant une association-type R connectée à l’association-type PLANIFIER, ce qui n’est pas particulièrement merisien (à moins de passer par exemple à Merise orienté objet). On peut contourner l’obstacle en déguisant l’association-type PLANIFIER en une entité-type identifiée relativement à SEMINAIRE d’une part et à DATE d’autre part :
L’identification relative est symbolisée ici par la mise entre parenthèses de la cardinalité 1,1 (convention de l’AGL Power AMC). Au besoin je rappelle que ce type d’identification a pour effet que PLANIFIER hérite d’une part de l’identifiant de SEMINAIRE et d’autre part de celui de DATE : on a bien déguisé l’association-type PLANIFIER en entité-type.
Par voie de conséquence, la structure de PLANIFIER au niveau logique est la suivante :
Mais se posent maintenant deux problèmes au niveau logique :
1) Il y a une bijection entre les tables PLANIFIER et SESSION, ce qui est souvent sujet à débat (à cause du cycle apparaissant au niveau logique) ;
2) On devra une fois de plus prendre en compte manuellement la dépendance fonctionnelle :
Pour retrouver le diagramme de la figure 5, il faut :
Supprimer la table SESSION,
Renommer PLANIFIER en SESSION,
Renommer Date en DateSession (ce que l’on aurait pu faire au niveau conceptuel),
Faire passer la paire {CodeSeminaire, DateSession} du statut de clé primaire à celui de clé alternative,
Élever {NumeroSession} au rang de clé primaire.
Comme dit l’autre, ça fait pas mal de choses à faire, il vaut mieux laisser tomber cette approche et procéder comme illustré dans les figures 2 à 5.
Ne baissons pas les bras, il existe d’autres possibilités de modélisation... Supposons que l’utilisateur tienne à ce que le numéro de session puisse être porteur de sens et/ou être modifié (le problème est du reste plus simple à traiter si l’utilisateur ne tient pas particulièrement à ce numéro). Sémantiquement parlant, l’entité-type SESSION peut être perçue comme une propriété multivaluée de l’entité-type SEMINAIRE, elle est alors ce qu’il est convenu d’appeler une entité-type faible (weak entity chez Johnny), symbolisée par l’emploi de l’identification relative. Le diagramme conceptuel devient alors le suivant :
SequenceurSession est un nouvel attribut jouant le rôle de numéroteur relatif à CodeSeminaire, et l’identifiant de SESSION est alors défini par la paire {CodeSeminaire, SequenceurSession}. Le singleton {NumeroSession} est ravalé au rang de clé alternative, ce qui ne pose aucun problème.
Mai là encore, la paire {CodeSeminaire, DateSession} doit faire l’objet d’une clé alternative au niveau logique, et malheureusement on doit encore se résoudre à la définir à la main (il ne faudrait quand même pas perdre la règle selon laquelle un type de séminaire ne peut pas être donné deux fois le même jour...). Le diagramme logique est le suivant :
A cette occasion, regardons un exemple de valeur prise par la table SESSION (les noms des attributs composant la clé primaire {CodeSeminaire, SequenceurSession} sont soulignés, les noms des attributs composant la clé alternative {CodeSeminaire, DateSession} sont en italiques et le nom de l’attribut composant la clé alternative {NumeroSession} est en gras) :
1 2 3 4 5 6 7 8 9 10 11
| Table SESSION
CodeSeminaire SequenceurSession DateSession NumeroSession HeureDebut
1 1 14/03/2011 1 08:30
1 2 07/11/2011 2 09:00
1 3 19/12/2011 3 09:00
2 1 09/11/2011 4 09:30
2 2 19/12/2011 5 08:30
... ... ... ... ...
Clés : {CodeSeminaire, SequenceurSession}, {NumeroSession}, {CodeSeminaire, DateSession} |
Bien noter que la numérotation de l’attribut SequenceurSession commence à 1 pour chaque type de séminaire. Une référence utile pour voir comment fonctionne l’incrémentation automatique d’un numéroteur relatif tel que SequenceurSession : l’article de CinePhil sur le sujet.
Après ces quelques variations, on conclut que si on modélise en utilisant soit les diagrammes des figures 2 à 5, soit les diagrammes de figures 12 et 13, on n’échappe pas à une intervention manuelle au niveau logique (prise en compte en l’occurrence de la dépendance fonctionnelle {SEMINAIRE, DATE} -> {SESSION}). Ceci est une conséquence du paradigme merisien “One fact, one place” : un attribut (CodeSeminaire au hasard...) ne peut pas figurer deux fois dans le diagramme conceptuel. Par contre, on est beaucoup moins gêné aux entournures au niveau logique, ce qui nous permet de rattraper le coup.
A supposer que l’utilisateur ne tienne pas à avoir la maîtrise du contenu du numéro de session, donc que ça lui soit égal que ce contenu soit invariant, on peut faire l’économie de l’attribut SequenceurSession, et le remplacer par l’attribut NumeroSession. Le diagramme conceptuel est alors le suivant :
L’attribut NumeroSession joue le rôle de numéroteur relatif à CodeSeminaire, et l’identifiant de SESSION est alors défini par la paire {CodeSeminaire, NumeroSession}.
Mais bien sûr, là encore, la paire {CodeSeminaire, DateSession} devra faire l’objet d’une clé alternative au niveau logique, ajoutée manuellement (rabâchons encore et encore qu’il ne faut pas perdre la règle selon laquelle un type de séminaire ne peut pas faire l’objet de deux sessions en même temps...). Quoi qu’il en soit, le diagramme logique correspondant est le suivant :
Le contenu (ou extension) de la table devient le suivant (en notant que les noms des attributs composant la clé primaire {CodeSeminaire, NumeroSession} sont soulignés, tandis que les noms des attributs composant la clé alternative {CodeSeminaire, DateSession} sont en italiques) :
1 2 3 4 5 6 7 8 9 10 11
| Table SESSION
CodeSeminaire NumeroSession DateSession HeureDebut
1 1 14/03/2011 08:30
1 2 07/11/2011 09:00
1 3 19/12/2011 09:00
2 1 09/11/2011 09:30
2 2 19/12/2011 08:30
... ... ... ...
Clés : {CodeSeminaire, NumeroSession}, {CodeSeminaire, DateSession} |
On ne parle plus de la session <1>, de la session <2>, etc. dans l’absolu, mais de la session <1,1>, de la session <1,2>, c'est-à-dire de la 1re session du type de séminaire 1, de la 2e session du type de séminaire 2, etc., puis de la 1re session du type de séminaire 2, de la 2e session du type de séminaire 2, etc.
La session <1,1> n’a lieu qu’à une seule date, à savoir le 14 mars 2011, etc.
En fait, il est possible d’éviter une intervention manuelle au niveau logique pour assurer la dépendance fonctionnelle, il suffit de ravaler l’attribut NumeroSession au rang d’identifiant alternatif et de considérer que l’identifiant (relatif) de l’entité-type SESSION est constitué de la paire {CodeSeminaire, DateSession} :
D’où le diagramme logique dans lequel on n’a pas à intervenir :
Mais, toujours du fait des conséquences sur les commandes, il est prudent de s’assurer que la clé primaire de la table SESSION soit invariante, donc que les dates de session ne soient jamais modifiées et là rien n’est moins sûr, sauf peut-être dans les cas d’école...
Fin de la visite guidée...
Note concernant les données temporelles :
On vient de se donner beaucoup de peine pour voir différentes façons de garantir la règle de gestion :
« Toutes les précautions sont prises sur les planning-types pour qu’un même formateur ne risque pas d’avoir deux séminaires à assurer en même temps. »
Mais en réalité on ne garantit pas la règle ! En effet, on garantit seulement que pour un type de séminaire donné T1, deux sessions S1 et S2 ne peuvent pas commencer le même jour. Supposons maintenant que S1 commence tel lundi pour une durée de quatre jours : qu’est-ce qui empêche que S2 puisse commencer le lendemain ? Rien en l’état. Il faudra donc prévoir une contrainte permettant de s’assurer qu’il n’y a pas de recouvrement des périodes.
Note concernant l’outil de modélisation :
Vous utilisez AnalyseSI. Je ne sais pas où en est le développement de cet outil, mais j’avais à une époque effectué des tests et ça n’était pas brillant ! Voyez par exemple ici...
Il existe un autre outil gratuit qui fonctionne très bien, Open ModelSphere, voyez des exemples d’utilisation :
tavarlindar (Quelle technique / logiciel pour modéliser un MCD intelligent en 2010 ?)
http://www.developpez.net/forums/d96...a/#post5436291
dxerty (Type association communs).
http://www.developpez.net/forums/d89...s/#post5091059
Locus51 (gestion des adhérents).
http://www.developpez.net/forums/d90...s/#post5112835
Menas (MCD_Spécialisation/Heritage/Sous-types Open ModelSphere).
http://www.developpez.net/forums/d89...n-modelsphere/
ricounet_paris (inscription (souple) de clients).
http://www.developpez.net/forums/d95...s/#post5356557
guipe ( Gestion d'une pharmacie)
http://www.developpez.net/forums/d90...ion-pharmacie/
Etc.
Si vous n’êtes pas inféodé à Merise, vous pouvez éventuellement utiliser MySQL Workbench (gratuit), qui est du niveau logique, mais permet d’éviter les difficultés inhérentes à la modélisation conceptuelle que nous avons rencontrées ci-dessus.
Partager