• # un pavé de DB

    Posté par . En réponse à la dépêche Application libre en ligne de suivi des aides aux écoliers avec SQLPage. Évalué à 10. Dernière modification le 03 juillet 2025 à 16:31.

    Préambule: ayant eu plusieurs fois l'occasion de maintenir/concevoir des modèles de DB pour des appli serveurs relativement complexes et au cycle de vie relativement long, je vois des trucs qui me font tiquer (ou qui soulèvent simplement des questions) dans le modèle de DB.

    Je sais que la modélisation de DB, c'est pas le truc le plus évident, et c'est souvent le parent pauvre du dév. Donc je salue le travail accompli, et livre des commentaires que j'espère constructifs.

    Disclaimer: pas d'argument d'autorité ici, p-e que certaines de mes remarques auront un ton péremptoire (parce que c'est comme ça que j'écris) mais ce ne sont que des propositions/questions. D'autant que je ne connais pas le domaine, il y a des informations que j'ignore qui modifieraient probablement mes remarques.

    PS: J'avais raté la mention de SQL page sur la nouvelle que tu références. Je suis allé jeter un oeil, et le modèle de DB proposée par école inclusive, et mes remarques ne semblent pas s'y appliquer.

    (quand j'écris truc.machin, ça veut dire que je fais référence à la colonne machin de la table truc. Par exemple, la colonne id de la table eleve => eleve.id)

    sur la forme, je recommande d'essayer d'être homogène sur le nommage des tables et colonnes. Donc:

    • tout au singulier (actions -> action, niveaux -> niveau, _sql_migrations -> _sql_migration)

    • pas de nom de colonne qui font référence au nom de la table. Par exemple, enseignant.name_ens -> enseignant.name, ça suffit. En SQL, si on prend l'habitude de toujours référencer les colonnes avec leur origine, ce n'est jamais ambigu. D'autre part, quand un colonne référence le nom de table, c'est pénible si on a plus tard une bonne raison de renommer la table. On se retrouve alors avec deux mauvaises options, soit renommer la colonne (et propager ça dans tout le code), soit ne pas la renommer, et se retrouver avec un nom de colonne incohérent.

    • suffixe _id
      tant que possible, réserver le suffixe _id aux colonnes qui pointent vers des clefs étrangères. (ici, parcours.dispositif_id, est-ce que ça fait référence à une table dispositif non représentée dans cette capture d'écran ? Si oui, ok, sinon, voir si on peut trouver un autre nom de colonne)

    • et systématiser son usage. (enseignant.etab_ens -> enseignant->etab_id, ...)

    • ajouter des id techniques sur les toutes les tables (par exemple, niveau.id) et donc, eleve.niveau -> eleve.niveau_id. Si, pour une raison quelconque, en ajoutant des colonnes, on doit faire porter la contrainte de clef primaire sur deux champs, il faut modifier toutes tables qui ont une contrainte de clef étrangère sur cette table). Perso, je préfère garder ma contrainte de clef étrangère sur les ID, et rajouter les contrainte d'unicité/non nullité nécessaires.

    • homogénéiser l'ordre des colonnes (par exemple, (id, *_id, reste des colonnes)) dans les scripts de création de la DB.

    sur la structure:

    • clefs étrangères
      la table parcours a trop de clefs étrangères à mon goût. Parfois, la meilleure alternative, c'est bien d'avoir plusieurs clefs étrangères. D'ailleurs, deux clefs étrangères, c'est complètement normal (pour modéliser les relations de cardinalité n,n, il n'y a pas le choix). Mais à partir de 3, perso, je regarde si j'ai pas d'autres options.

    • risque d'incohérence des données:
      Certaines tables de la structure actuelle sont reliées à d'autres tables par plusieurs chemins. C'est parfois ce qu'ont veut, mais la plupart du temps, on ne veut qu'une seule façon de relier deux tables. Par exemple, ici, eleve.etab_id fait le lien entre eleve et etablissement. Mais on peut aussi passer par eleve.enseignant_id, puis enseignant.etab_ens). Si c'est un cas normal qu'un enseignant suive des élèves d'un autre établissement que le sien, ce n'est pas forcément un problème. (Il semble aussi y avoir une duplication de eleve.etab_UAI, également un risque de incohérence)
      Cette remarque est valable pour parcours (eleve_id, etab_id, enseignant_id), ou on a même trois chemins pour rejoindre la table etablissement
      .

    • adéquation modèle/cardinalité
      Je signale ce risque d'incohérence sur cet exemple eleve/enseignant. Mais en fait, il y a potentiellement un problème plus fondamental sur cette relation eleve/enseignant. Par exemple, si le suivi peut avoir lieu sur plusieurs années, et si un enseignant(ou eleve) change d'établissement entre deux années, la relation eleve/enseignant n'est plus une relation de cardinalité 1,n, mais de cardinalité n,n. Or on ne peut utiliser les clefs étrangères que pour modéliser des relations 1,*. Dès que c'est du n,n, une table dédiée est nécessaire.

    • classe
      Faut-il une entité classe ? (user_info.classe, enseignant.class_ens, eleve.classe, parcours.classe). Sans plus d'infos, ça ressemble à une potentielle duplication de données.

    • association implicite
      Dans la table parcours, le fait qu'une partie des colonnes s'appellent "action_" suggèrent qu'il y a une entité implicite, l'entité "action" qui mérite p-e d'être modélisée en tant que telle. D'ailleurs, il y a une table actions, ce qui me fait penser que les champs parcours.action_* sont plutôt des attributs d'une relation entre parcours et actions.

    Mon expérience, c'est qu'on finit souvent pas regretter de ne pas avoir investi un peu plus de temps sur la modélisation de la DB au début d'un projet.
    C'est pour ça que je recommanderais de faire un modèle type entité-association en plus (voire avant) d'avoir le modèle technique. Ce n'est jamais trop tard pour le commencer.

    Ça permet de prendre du recul sur ce qu'on modélise, et fait souvent économiser de la complexité lors de l'implémentation. C'est bien aussi de garder la question des formes normales en tête.

    A noter que ce modèle entité-association ne peut pas être généré automatiquement. On ne peut pas inférer les cardinalités des relations à partir du seul modèle technique de la DB.

    PS: Ça se voit que j'aime bien modéliser les DB ou pas ? :o)