Incompatibilité du modèle forum avec SQLAlchemy #25
Closed
opened 4 years ago by Lephenixnoir
·
5 comments
Loading…
Reference in new issue
There is no content yet.
Delete Branch '%!s(<nil>)'
Deleting a branch is permanent. It CANNOT be undone. Continue?
Le modèle actuel du forum comporte une classe de base,
Post
, qui représente les contenus datés avec un auteur.De cette classe héritent deux classes majeures,
Thread
etComment
. La première représente tous les fils de discussions, qui sont omniprésents sur le site : sujets, programmes, tutoriels, et d'autres. La seconde représente un commentaire normal.Cet héritage est polymorphe, ce qui permet de charger dynamique des
Post
et d'obtenir comme on le veut des fils de discussions et des commentaires mélangés.De
Thread
héritent encore plusieurs classes, qui sont comme attenduTopic
,Program
,Tutorial
et d'autres. Cela forme un deuxième niveau d'héritage polymorphe.Le problème est que SQLAlchemy ne supporte pas l'héritage polymorphe en cascade. Accessoirement, c'est assez compliqué et donc difficile à gérer. Voici, pour référence, ce qu'en dit la documentation :
Pour que ce modèle soit implémentable, il faut donc éliminer un de ces deux héritages polymorphes. Je vois plusieurs solutions.
Éliminer l'héritage
Post
→Thread
,Comment
C'est le plus naturel a priori, puisque cet héritage propage bien moins d'information que l'autre. Il faut alors inclure l'information de date et d'auteur autrement que par héritage, par exemple en reproduisant les attributs (duplication de la fonctionnalité) ou en définissant
Post
comme une sorte de mixin (à voir comment).Éliminer l'héritage
Thread
→Topic
,Program
,Tutorial
, etcIci, comme il est hors de question de répliquer la fonctionnalité des fils de discussion, la méthode qui me semble la plus naturelle pour éliminer l'héritage est simplement de mettre en relation chacune de sous-classes avec son fil sous-jacent. Cela se combine très élégamment avec notre volonté de lier le même fil à des topics et programmes jumeaux (même projet) et je pense donc que c'est la meilleure réponse pour l'instant.
Une troisième solution m'avait effleuré l'esprit, mais je l'ai oubliée en rédigeant... ça me reviendra sans doute si la discussion prend du temps.
@Darks Opinion désirée.
J'ajoute que la deuxième solution que je propose revient exactement à implémenter le mécanisme usuel de polymorphisme de SQLAlchemy, Joined Table Inheritance, mais à la main.
En fait on casse la boîte de l'héritage de SQLAlchemy pour aller voir au niveau en-dessous, celui avec les relations. Et c'est parfait pour nous car on planifie justement d'aller toucher à ce niveau pour implémenter la capacité pour un sujet et un programme de partager le même fil de discussion.
Avec les enjeux vraiment en tête, pour moi ça ne fait pas un pli. Compte tenu de la simplification du code et des modèles, je nous estime gagnants avec la seconde solution.
J'ai pas le recul nécessaire pour faire un choix. Je te fais confiance sur ce coup là, c'est toi qui a bossé sur le sujet plus que moi.
Enfin, c'est con que SQLAlchemy implémente pas un polymorphisme plus complet…
Ayant des problèmes à comprendre SQlAlchemy, je n'ai que compris que ce dernier n'implémentait pas une/des fonctionnalités utilisés dans l'architecture du modèle.
Sans rapport: C'est déjà un miracle que j'ai pigé ça, moi je pige que dalle à ce qui touche aux BDD, car j'ai pas assez bossé le sujet. À ce propos vous auriez-pas un tuto à me conseiller que je comprenne mieux de quoi on parle ici ?
Ce que l'on appelle « polymorphisme », c'est l'héritage. À savoir qu'un objet peut avoir plusieurs formes (être un
Topic
, unThread
et unPost
en même temps).SQLAlchemy ne sait pas gérer le polymorphisme de niveau 3 et plus : ton objet ne peut pas être une instance de 3 classes en même temps. Or, puisque
Post
→Thread
→Topic
, il nous faut casser l'héritage à un endroit.Il y en a deux possibles : entre
Post
etThread
ou entreThread
etTopic
. D'où la question de Lephe pour savoir à quel endroit casser.Bon, du coup je suis dessus. Voici les modifications que je vais faire :
Post
au lieu de faire hériter les fils de discussion. En effet la classePost
sert à dater et désigner un auteur. Or un sujet et un programme partageant le même fil de discussion ont quand meêm des dates de création différentes !text
de la classePost
, qui n'avait pas grand-chose à faire là.Avec ça on sera prêts à partir o/