Beaucoup de tutoriels sur DDD que j'ai étudiés couvrent principalement la théorie. Ils ont tous des exemples de code rudimentaires (Pluralsight et similaires).
Sur le Web, quelques personnes tentent également de créer des didacticiels couvrant DDD avec EF. Si vous commencez à les étudier brièvement - vous remarquez rapidement qu'ils diffèrent beaucoup les uns des autres. Certaines personnes recommandent de garder l'application minimale et d'éviter d'introduire des couches supplémentaires, par exemple un référentiel au-dessus d'EF , d'autres génèrent décidément des couches supplémentaires, souvent même en violant SRP en injectant DbContext
dans les racines d'agrégat.
Je m'excuse terriblement si je pose une question d'opinion, mais ...
En matière de pratique, Entity Framework est l'un des ORM les plus puissants et les plus utilisés. Malheureusement, vous ne trouverez pas de cours complet couvrant DDD.
Aspects importants:
Entity Framework sort UoW & Repository (
DbSet
) de la boîteavec EF vos modèles ont des propriétés de navigation
avec EF tous les modèles sont toujours disponibles off
DbContext
(ils sont représentés comme unDbSet
)
Pièges:
vous ne pouvez pas garantir que vos modèles enfants sont uniquement affectés via la racine agrégée - vos modèles ont des propriétés de navigation et il est possible de les modifier et d'appeler
dbContext.SaveChanges()
avec
DbContext
vous pouvez accéder à chacun de vos modèles, contournant ainsi la racine agrégéevous pouvez restreindre l'accès aux enfants de l'objet racine via la méthode
ModelBuilder
in en les marquant comme des champs - je ne pense toujours pas que ce soit la bonne façon de faire à propos de DDD et il est difficile d'évaluer le type d'aventures que cela pourrait conduire à l'avenir ( assez sceptique) )OnModelCreating
Conflits:
sans implémenter une autre couche de référentiel qui renvoie Aggregate, nous ne pouvons même pas résoudre en partie les pièges susmentionnés
en implémentant une couche supplémentaire de référentiel, nous ignorons les fonctionnalités intégrées d'EF (tout
DbSet
est déjà un dépôt) et compliquons trop l'application
Ma conclusion:
Veuillez excuser mon ignorance, mais sur la base des informations ci-dessus - c'est soit Entity Framework n'est pas adéquat pour la conception pilotée par domaine ou la conception pilotée par domaine est une approche imparfaite et obsolète .
Je soupçonne que chacune des approches a ses mérites, mais je suis complètement perdu maintenant et je n'ai pas la moindre idée de la façon de réconcilier EF avec DDD.
Si je me trompe - quelqu'un pourrait-il au moins détailler un simple ensemble d'instructions (ou même fournir des exemples de code décents) sur la façon de traiter DDD avec EF, s'il vous plaît?
la source
Réponses:
DDD et EF n'ont presque rien à voir l'un avec l'autre.
DDD est un concept de modélisation. Cela signifie penser au domaine, aux exigences commerciales et les modéliser. Surtout dans le contexte de l'orientation objet, cela signifie créer un design qui reflète les fonctions et capacités de l'entreprise.
EF est une technologie de persistance. Il concerne principalement les données et les enregistrements de bases de données.
Ces deux sont fortement divorcés. Une conception DDD peut utiliser EF sous une forme quelconque sous le capot, mais les deux ne doivent pas interagir d'une autre manière.
Certaines interprétations de la conception pilotée par domaine préconisent en fait la modélisation des données, et je pense que c'est de cela qu'il s'agit. Dans cette interprétation, les «entités» et les «objets de valeur» sont essentiellement des détenteurs de données sans fonction uniquement, et la conception se préoccupe des propriétés qu'elles détiennent et de la relation qu'elles ont entre elles. Dans ce contexte, DDD vs. EF peuvent apparaître.
Cette interprétation est cependant imparfaite, et je recommanderais fortement de l'ignorer complètement.
En conclusion : DDD et EF ne s'excluent pas mutuellement, ils ne sont en fait pas pertinents l'un pour l'autre, tant que vous effectuez une modélisation d'objet appropriée et non une modélisation de données. Les objets DDD ne doivent en aucun cas être des artefacts EF. Les entités DDD ne doivent pas être des "entités" EF par exemple. Dans une fonction pertinente pour l'entreprise, une conception DDD peut utiliser EF avec certains objets de données associés, mais ceux-ci doivent toujours être masqués sous une interface orientée comportementale pertinente pour l'entreprise.
la source
Traitez EF pour ce qu'il est, c'est-à-dire une bibliothèque d'accès aux données qui n'est que légèrement plus fortement typée que ADO.NET brut. Je ne recommanderais pas de modéliser votre domaine à l'aide de classes d'entités EF, tout comme je ne recommanderais pas de modéliser un domaine à l'aide de DataSet ou DataTable bruts.
Je comprends que EF est vendu comme un raccourci entre l'accès à la base de données et la modélisation de domaine, mais cette approche est intrinsèquement défectueuse car elle résout deux problèmes largement indépendants. Il y a eu d'autres tentatives dans .NET pour faire exécuter à une classe des choses complètement indépendantes (par exemple .NET Remoting) et elles n'ont pas bien fini.
Faites le DDD à l'aide des classes POCO et ne laissez pas le schéma de base de données piloter votre conception. Gardez EF à l'intérieur du référentiel / couche de persistance et ne laissez pas les entités EF s'échapper à l'extérieur.
la source
Non.
Les abstractions Entity Framework ont été construites avec ORM, pas DDD, à l'esprit. L'
DbSet
abstraction dans n'importe quelle version d'Entity Framework est loin d'être la simplicité d'un référentiel DDD - sans parler deDbContext
ce qui expose un million de choses plus qu'un UnitOfWork.Voici une liste non exhaustive des éléments du résumé d'EF Core 2.1
DbSet<TEntity>
dont nous n'avons pas besoin dans DDD:Attach(TEntity)
et tous ses frères et sœursFind(Object[])
Update(TEntity)
et tous ses frères et sœursIQueryable
En plus de traîner avec eux des dépendances inutiles, celles-ci obscurcissent l'intention d'un référentiel qui expose normalement un comportement de collecte très simple. De plus, les abstractions qui fuient sont une tentation constante pour les développeurs de trop se coupler à EF et une menace pour la séparation des préoccupations.
Bottom line: vous devez envelopper ces fatties dans de beaux concepts rationalisés et deviner quoi, cela signifie introduire des classes supplémentaires.
Un exemple relativement solide de ce que vous pouvez faire avec EF et DDD (bien que certains points de vue exprimés soient discutables): https://kalele.io/blog-posts/modeling-aggregates-with-ddd-and-entity-framework/
Je ne vois vraiment pas le lien entre les deux parties de cette phrase. Quelle que soit l'approche, il existe une chose dans DDD appelée Application Service et c'est là que vous manipulez l'unité de travail / référentiel (ou
DbContext
). Pas dans les racines agrégées.Bien qu'il puisse s'agir d'une approche valable s'il s'agissait d'un compromis éclairé, la récente tendance anti-référentiel «minimalisme Entity Framework» est délirante. Il blâme les modèles DDD pour la friction qui se produit avec Entity Framework alors que ce sont vraiment les créateurs EF qui n'ont rien fait pour rendre leur framework conforme aux meilleures pratiques. Pendant ce temps, ils sont étroitement liés à ce cadre même avec tous les problèmes de sécurité et de maintenabilité du code qui peuvent en découler.
la source
J'ai utilisé une approche où chaque agrégat obtient son propre DBContext, mappant exactement ce qui est nécessaire pour l'agrégat. Je pense que cela a également été décrit par Julie Lerman.
Cela a très bien fonctionné, mais pourrait ne pas suffire pour des modèles plus intéressants, où vous ne voulez pas lier vos concepts à vos entités.
la source
Je voudrais juste partager une solution possible pour examen:
éviter de référencer directement le projet EF dans Service Layer
créer une couche de référentiel supplémentaire (utilise le projet EF et renvoie la racine agrégée)
référencer le projet Repository Layer in Service Layer
Architecture :
UI
Couche de contrôleur
Couche de service
Couche de référentiel
Cadre d'entité
Projet principal (contient des modèles EF)
Les pièges que je vois avec cette approche:
si un référentiel renvoie la racine agrégée non pas comme arbre de modèle EF (par exemple, nous renvoyons un objet mappé) - nous perdons la capacité d'EF à suivre les modifications
si la racine agrégée est un modèle EF - toutes ses propriétés de navigation sont toujours disponibles , même si nous ne pouvons pas les traiter
DbContext
(nous ne référençons pas le projet EF dans la couche de service)la source