Tables de recherche: s'agit-il d'une fuite dans le modèle de domaine?


10

Vous construisez un système qui assure le suivi des entreprises. Ces entreprises ont des contacts. Ces contacts sont souvent des spécialistes qui ne répondent qu'à certains types de questions, telles que la facturation / paiement, les ventes, les commandes et le support client.

En utilisant la conception pilotée par domaine et une architecture oignon, j'ai modélisé cela avec les types suivants:

  • Compagnie
    • A des contacts
  • Contact
    • A des types de contact
  • ContactType (énumération)
  • CompanyRepository (interface)
  • EFCompanyRepository (défini dans un assembly externe, utilise EntityFramework, implémente CompanyRepository)

Notre équipe a une opinion partagée sur la façon de modéliser la base de données pour cette application.

Face A: Les DDD Lean:

  • Il appartient au domaine de définir quels types de contact sont valides pour un contact. L'ajout d'une table à la base de données pour valider que les ContactTypes inconnus ne sont pas enregistrés est le signe d'un domaine qui fuit. Cela étend la logique trop loin.
  • L'ajout d'une table statique à la base de données et au code correspondant est un gaspillage. Dans cette application, la base de données résout un problème: persister la chose et me la rendre. Écrire une table supplémentaire et le code CRUD correspondant est un gaspillage.
  • Changer la stratégie de persistance devrait être aussi simple que possible. Il est plus probable que ces règles commerciales changent. Si je décide que SQL Server coûte trop cher, je ne veux pas avoir à reconstruire toute la validation que j'ai mise dans mon schéma.

Face B: Les traditionalistes [ce n'est probablement pas un nom juste. Les DBCentristes?]:

  • C'est une mauvaise idée d'avoir des données dans la base de données qui n'ont aucun sens sans lire le code. Les rapports et autres consommateurs doivent répéter eux-mêmes la liste des valeurs.
  • Ce n'est pas beaucoup de code pour charger vos dictionnaires de type db à la demande. Ne t'en fais pas.
  • Si la source de ceci est du code et non des données, je devrai déployer des bits au lieu d'un simple script SQL lorsqu'il changera.

Aucun côté n'a raison ou tort, mais l'un d'eux est probablement plus efficace à long terme, en comptant le temps de développement pour le développement initial, les bogues, etc. De quel côté s'agit-il - ou y a-t-il un meilleur compromis? Que font les autres équipes qui écrivent ce style de code?


Je préfère avoir des tables de recherche dans la base de données et avoir du code (modèles T4 dans .NET) qui génère les énumérations pour moi en fonction des tables de recherche dans mon code d'application.
programmeur

@JasonHolland Le modèle T4 effectue-t-il réellement une requête? Sinon, je ne sais pas comment cela génère plus qu'une énumération vide avec le nom attendu.
attiré


Pour une table avec des valeurs statiques, combien de code CRUD devez-vous écrire? Écris-le et fais.
JeffO

2
L'argument CRUD-ist traditionnel sur «eh bien, cela n'aura pas de sens pour les rapports» est un non-starter. Dès que vous introduisez une autre responsabilité que le système a (à savoir, le reporting), vous avez trouvé une exigence commerciale qui doit être gérée de manière appropriée. La base de données est là pour stocker et charger l'état propre et protégé des applications; le fait de pouvoir en rendre compte crée un couplage entre votre application et les personnes qui ont besoin des rapports. Si DDD concerne quelque chose, il s'agit de séparer ces contextes.
Matt

Réponses:


4

En adoptant l'architecture DDD et oignon, vous avez décidé que la base de données est la deuxième à votre modèle de domaine. Cela signifie qu'il n'y aura personne d'autre effectuant des opérations sur la base de données autre que le modèle. Si les traditionalistes n'aiment pas cela, ils auraient dû s'opposer à l'utilisation de DDD en premier lieu.

La première chose est claire: vous avez besoin de la "table de correspondance" dans le modèle. Votre modèle doit différencier les différents types de contacts. Cela signifie qu'il conserve une liste fortement typée de tous les types. Il faut également mapper ces types forts vers des valeurs sérialisées dans la base de données. Ce mappage peut être à l'intérieur du module de base de données. Mais la liste de tous les types possibles sera toujours dans le modèle. Et si le modèle doit être une source unique de vérité, il ne doit pas se trouver dans la base de données. Ou du moins, lorsque la liste change dans le modèle, elle doit changer dans la base de données. Et pas de mais!


2

Les objets de domaine cessent d'être des objets de domaine lorsqu'ils franchissent une limite de processus . Même si la base de données n'est qu'un magasin de persistance, à un moment donné dans le futur, les exigences de l'entreprise vont entraîner une modification du modèle domaim qui n'est pas cohérente avec l'historique persistant, et vous aurez de toute façon besoin d'une couche anti-corruption ....

Cela dit, je pense que vos DBCentristes manquent le bateau. Les modélisateurs de domaine disent qu'ils ont besoin d'un magasin de persistance. Les "rapports et autres consommateurs" ont besoin de quelque chose qu'ils puissent interroger - quelque chose avec des index décents, comme cela a été noté dans les commentaires.

Qui a introduit la contrainte selon laquelle toutes ces différentes préoccupations devaient être prises en charge par une seule base de données? Que se passe-t-il si vous repoussez cela.

Mot-clé de recherche: CQRS.


1

J'ai trouvé préférable de stocker des énumérations comme représentation de chaîne dans la base de données et de ne pas inclure de table de recherche.

De toute évidence, l'inconvénient est qu'il utilise plus d'espace disque et n'est pas normalisé.

Le côté positif est que le champ conserve sa signification dans la base de données, vous ne vous retrouvez pas avec des nombres magiques correspondant à la valeur int de l'énumération par exemple et vous n'avez pas à gérer la gestion des versions d'une table de recherche lorsque l'énumération change.

Je ne suis pas sûr que je qualifierais cela de différence DDD vs Trad. C'est plus un code de base de données centralisé vs est le meilleur à mon avis


se demandant si les bases de données elles-mêmes ont une telle fonctionnalité enum ces jours-ci
herzmeister

Je suppose que cela dépend de la base de données, vous pouvez faire toutes sortes de trucs fous CLR avec MSSQL. Mais je suis fermement du côté 'DB bad, code good' quand il s'agit de telles choses
Ewan

@herzmeister <3 PostgreSQL postgresql.org/docs/9.4/static/datatype-enum.html , Ewan La base de données est du code une fois que vous avez adopté les procédures stockées. (PLv8 est merveilleux).
Sirisian

@Sirisian tu sais que ça mélange quelque chose? J'ai une question similaire. "est-ce que ça évolue?"
Ewan

Voulez-vous dire que cela fait un produit croisé pour transformer l'énumération en une chaîne? Probablement pas. Je ne sais pas comment cela est implémenté, mais c'est plus rapide que d'utiliser une table séparée. Il évolue. J'ai trouvé cela aussi: stackoverflow.com/questions/2318123/… semble toujours être une évaluation valide 5 ans plus tard. (J'ai tendance à écrire des programmes hautement couplés à PostgreSQL, donc j'utilise toutes les fonctionnalités, mais tout le monde ne peut pas le faire).
Sirisian

0
  • Tant que vous utilisez une base de données relationnelle, vous devez conserver les tables normalisées dans une mesure raisonnable. La normalisation permet d'éviter les anomalies d'insertion et de mise à jour.
  • La relation une application <-> une base de données n'est plus courante, plusieurs applications peuvent utiliser plusieurs bases de données et une seule base de données peut être utilisée par plusieurs applications, il est donc bon que la base de données applique l'intégrité référentielle autant que possible.
  • Le SGBDR est votre ami.
  • Vous pouvez utiliser un stockage de valeurs-clés à la place et tout faire dans le code.
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.