Modèles par table de base de données?

11

J'utilise codeigniter, et je me suis retrouvé dans une situation similaire où j'ai répété les méthodes du modèle. Je crée un modèle par contrôleur. Mais est-ce que la création d'un modèle par table de base de données serait considérée comme une bonne pratique? De cette façon, les méthodes ne sont pas écrites deux fois.

Au lieu de modèle par contrôleur ou de plusieurs petits modèles partagés.

Exemple si j'ai une méthode modèle get_user ($ user_id) je pourrais l'écrire sur users_models.php ...

L'un des inconvénients que je vois à ce sujet est que je devrais peut-être appeler plusieurs modèles, plutôt que simplement controllername_models.php.

Le chargement de plusieurs modèles sur lesquels plusieurs méthodes peuvent ne pas être utilisées à partir d'un contrôleur peut-il affecter les performances et la vitesse? Quelle pourrait être la meilleure façon de résoudre ce problème?

Remarque: Il existe des questions similaires, mais elles ne couvrent pas le sol du modèle par table de base de données.

Howard Steff
la source

Réponses:

8

Je dis qu'un modèle par table ne fait que recréer votre base de données dans une structure de classe. Il est connu comme un modèle anémique et considéré comme un anti-modèle. En effet, les classes sont destinées à avoir à la fois des données et un comportement. Si vous limitez vos modèles à une seule table, où placez-vous le code (comportement) qui doit gérer les données et le comportement de plusieurs tables? Vos contrôleurs auraient alors besoin de modèles qui utilisent un ou plusieurs de ces modèles "de table" ... Donc, à part dans les applications les plus basiques, vous gagnez peu ou rien de cette approche.

Marjan Venema
la source
Juste un petit addendum - il est considéré comme un anti-modèle par Martin Fowler. Arrêt complet ici. Il a un aperçu de ce cas, mais cela ne signifie pas qu'il est mauvais - différemment de God Object, qui est presque toujours mauvais, une structure comme celle-ci est parfois incroyablement utile et facilement maitenable. Je ne considère pas cela comme un anti-modèle du tout.
T. Sar
1
Par exemple, le «modèle anémique» est conforme à SOLID - est-ce vraiment mauvais d'avoir un objet avec un seul but (stocker des données)? Bien que je respecte beaucoup de choses que M. Fowler dit, celle-ci était des conneries.
T. Sar
7

En général, vous devez créer vos modèles non pas par table ou par contrôleur, mais par objet métier. Parfois, il peut s'agir d'une relation 1: 1 avec la structure de vos tables ou avec vos contrôleurs, mais pas nécessaire.

Dans votre exemple, vous pouvez avoir une users_modelclasse qui est appelée à partir de plusieurs contrôleurs. C'est bien et parfois même souhaitable. Cependant, dans la plupart des cas, la users_modelclasse obtiendra ses données de plusieurs tables.
Par exemple, la last_login_datepropriété de la users_modelclasse peut ( ne doit pas ) être obtenue à partir d'une user_audittable distincte qui a une relation un-à-plusieurs avec la userstable principale .

Et je dirais que si vous avez une table SQL par objet métier, il est fort probable que la structure de votre base de données ne soit pas normalisée.

Dîme
la source
3

Je suis principalement d'accord avec la réponse de Dime selon laquelle vous souhaitez créer vos modèles par objet métier - les problèmes que l'entreprise tente de résoudre devraient guider la façon dont vous créez les classes de modèle. En pratique, j'ai trouvé que la création d'un modèle par table est un bon point de départ. Un schéma correctement conçu est susceptible d'imiter les processus métier que vous devez modéliser dans le code d'application - également appelé modèle de domaine.

L'utilisation d'une couche de mappage objet / relationnel est utile pour que votre modèle de domaine contienne les mêmes relations que le schéma de base de données sans avoir besoin d'appels répétitifs à une couche d'accès aux données. Découvrez Eloquent pour PHP comme exemple. Le schéma et le modèle de domaine doivent être conçus pour prendre en charge les processus métier.

Cela nous amène à la première partie de la réponse de Marjan Venema:

Je dis qu'un modèle par table ne fait que recréer votre base de données dans une structure de classe. Il est connu comme un modèle anémique et considéré comme un anti-modèle.

Un modèle de domaine anémique est un anti-modèle. Un «modèle par table», comme le suggère Venema, pourrait être considéré comme «recréant votre base de données», mais il est absolument incorrect de dire qu'il s'agit à lui seul d'un modèle de domaine anémique.

De Martin Fowler:

Le symptôme de base d'un modèle de domaine anémique est qu'à première vue il ressemble à la vraie chose. Il existe des objets, dont plusieurs portent le nom des noms dans l'espace du domaine, et ces objets sont liés aux relations et à la structure riches des vrais modèles de domaine. Le hic vient quand vous regardez le comportement, et vous vous rendez compte qu'il n'y a pratiquement aucun comportement sur ces objets, ce qui en fait un peu plus que des sacs de getters et de setters.

(c'est moi qui souligne)

Le facteur clé dans un modèle de domaine anémique est un manque de comportement ou de méthodes sur les classes de modèle de domaine.

En effet, les classes sont destinées à avoir à la fois des données et un comportement. Si vous limitez vos modèles à une seule table, où placez-vous le code (comportement) qui doit gérer les données et le comportement de plusieurs tables?

Encore une fois, vous pouvez et devez mettre le comportement dans vos modèles de domaine, même s'ils ne sont mappés qu'à une seule table. Un comportement qui affecte plusieurs tables affecte réellement plusieurs objets qui se mappent sur plusieurs tables. La conception pilotée par domaine est une approche précisément du même problème que Venema a mentionné: "où placez-vous le code (comportement) qui doit gérer les données et le comportement de plusieurs tables?"

Et la réponse est une racine agrégée . Martin Fowler déclare:

L'agrégat est un modèle de conception pilotée par domaine. Un agrégat DDD est un cluster d'objets de domaine qui peut être traité comme une seule unité. Un exemple peut être une commande et ses éléments de campagne, ce seront des objets séparés, mais il est utile de traiter la commande (avec ses éléments de campagne) comme un agrégat unique.

(c'est moi qui souligne)

Un «cluster d'objets de domaine» peut également être considéré comme un «modèle de domaine mappé à plusieurs tables». Le comportement qui affecte plusieurs tables doit être défini sur la racine agrégée - Une classe qui encapsule la «chose» qui affecte plusieurs tables ou objets:

Encore une fois, de Martin Fowler:

Un agrégat contiendra souvent plusieurs collections, ainsi que des champs simples.

Pour répondre à la question initiale du PO:

... la création d'un modèle par table de base de données serait-elle considérée comme une bonne pratique? De cette façon, les méthodes ne sont pas écrites deux fois.

Je dirais que c'est un bon point de départ, mais sachez que votre schéma et votre modèle d'objet ne doivent pas nécessairement correspondre à 100%. Le modèle objet devrait être davantage concerné par la mise en œuvre et l'application des règles métier. Le schéma devrait être davantage axé sur le stockage des données d'entreprise de manière modulaire et évolutive.

Un modèle par contrôleur ne serait pas une bonne pratique, bien qu'il y ait une variante du modèle appelé un modèle View qui ne forme dans la couche contrôleur. Un modèle d'affichage est une réorganisation du modèle de domaine pour s'adapter à un certain type d'affichage, que ce soit une page Web ou un formulaire dans une application graphique.

Greg Burghardt
la source