J'étudie DDD ces jours-ci, et j'ai des questions concernant la gestion des référentiels avec DDD.
En fait, j'ai rencontré deux possibilités:
Premier
La première façon de gérer les services que j'ai lus est d'injecter un référentiel et un modèle de domaine dans un service d'application.
De cette façon, dans l'une des méthodes de service d'application, nous appelons une méthode de service de domaine (vérification des règles métier) et si la condition est bonne, le référentiel est appelé sur une méthode spéciale pour persister / récupérer l'entité de la base de données.
Une façon simple de procéder pourrait être:
class ApplicationService{
constructor(domainService, repository){
this.domainService = domainService
this.repository = repository
}
postAction(data){
if(this.domainService.validateRules(data)){
this.repository.persist(new Entity(data.name, data.surname))
}
// ...
}
}
Deuxième
La deuxième possibilité consiste à injecter le référentiel à l'intérieur de domainService à la place et à n'utiliser le référentiel que via le service de domaine:
class ApplicationService{
constructor(domainService){
this.domainService = domainService
}
postAction(data){
if(this.domainService.persist(data)){
console.log('all is good')
}
// ...
}
}
class DomainService{
constructor(repository){
this.repository = repository
}
persist(data){
if(this.validateRules(data)){
this.repository.save(new Entity(data.name))
}
}
validateRules(data){
// returns a rule matching
}
}
À partir de maintenant, je ne suis pas en mesure de distinguer lequel est le meilleur (s'il y en a un) ou ce qu'ils impliquent tous les deux dans leur contexte.
Pouvez-vous me donner un exemple où l'un pourrait être meilleur que l'autre et pourquoi?
la source
Réponses:
La réponse courte est - vous pouvez utiliser des référentiels à partir d'un service d'application ou d'un service de domaine - mais il est important de considérer pourquoi et comment vous le faites.
Objectif d'un service de domaine
Les services de domaine doivent encapsuler les concepts / la logique du domaine - en tant que tel, la méthode du service de domaine:
n'appartient pas à un service de domaine, car il
persist
ne fait pas partie du langage omniprésent et l'opération de persistance ne fait pas partie de la logique métier du domaine.En règle générale, les services de domaine sont utiles lorsque vous avez des règles / logique métier qui nécessitent de coordonner ou de travailler avec plusieurs agrégats. Si la logique n'implique qu'un seul agrégat, elle doit se trouver dans une méthode sur les entités de cet agrégat.
Référentiels dans Application Services
Donc, dans ce sens, dans votre exemple, je préfère votre première option - mais même là, il y a place à amélioration, car votre service de domaine accepte les données brutes de l'API - pourquoi le service de domaine devrait-il connaître la structure de
data
?. De plus, les données ne semblent être liées qu'à un seul agrégat, il y a donc une valeur limitée à utiliser un service de domaine pour cela - en général, je mettrais la validation dans le constructeur de l'entité. par exempleet lever une exception si elle n'est pas valide. En fonction de votre infrastructure d'application, il peut être simple d'avoir un mécanisme cohérent pour intercepter l'exception et la mapper à la réponse appropriée pour le type d'api - par exemple pour une api REST, renvoyer un code d'état 400.
Référentiels dans les services de domaine
Nonobstant ce qui précède, il est parfois utile d'injecter et d'utiliser un référentiel dans un service de domaine, mais uniquement si vos référentiels sont implémentés de telle sorte qu'ils acceptent et renvoient uniquement des racines d'agrégat, et également lorsque vous abstrayez une logique impliquant plusieurs agrégats. par exemple
l'implémentation du service de domaine ressemblerait à:
Conclusion
La clé ici est que le service de domaine encapsule un processus qui fait partie du langage omniprésent. Pour remplir son rôle, il doit utiliser des référentiels - et c'est parfaitement bien de le faire.
Mais l'ajout d'un service de domaine qui enveloppe un référentiel avec une méthode appelée
persist
ajoute peu de valeur.Sur cette base, si votre service d'application exprime un cas d'utilisation qui appelle à ne travailler qu'avec un seul agrégat, il n'y a aucun problème à utiliser le référentiel directement à partir du service d'application.
la source
Il y a un problème avec la réponse acceptée:
Le modèle de domaine n'est pas autorisé à dépendre du référentiel et le service de domaine fait partie du modèle de domaine -> le service de domaine ne doit pas dépendre du référentiel.
À la place, vous devez assembler toutes vos entités nécessaires à l'exécution de la logique métier déjà dans le service d'application, puis fournir simplement à vos modèles des objets instanciés.
D'après votre exemple, cela pourrait ressembler à ceci:
Donc, règle générale: le modèle de domaine ne dépend pas des couches externes
Application vs service de domaine De cet article :
Les services de domaine sont très granulaires alors que les services d'application sont une façade destinée à fournir une API.
Les services de domaine contiennent une logique de domaine qui ne peut naturellement pas être placée dans une entité ou un objet de valeur, tandis que les services d'application orchestrent l'exécution de la logique de domaine et n'implémentent eux-mêmes aucune logique de domaine.
Les méthodes de service de domaine peuvent avoir d'autres éléments de domaine comme opérandes et valeurs de retour tandis que les services d'application fonctionnent sur des opérandes triviaux tels que des valeurs d'identité et des structures de données primitives.
Les services d'application déclarent les dépendances des services d'infrastructure requis pour exécuter la logique du domaine.
la source
Aucun de vos modèles n'est bon à moins que vos services et objets n'encapsulent un ensemble cohérent de responsabilités.
Dites d'abord ce qu'est votre objet de domaine et parlez de ce qu'il peut faire dans le langage de domaine. S'il peut être valide ou invalide, pourquoi ne pas l'avoir comme propriété de l'objet de domaine lui-même?
Si, par exemple, la validité des objets n'a de sens qu'en termes d'un autre objet, alors vous avez peut-être une responsabilité «règle de validation X pour les objets de domaine» qui peut être encapsulée dans un ensemble de services.
La validation d'un objet nécessite-t-elle de le stocker dans vos règles métier? Probablement pas. La responsabilité du «stockage des objets» va normalement dans un objet de référentiel séparé.
Vous avez maintenant une opération que vous souhaitez effectuer qui couvre un éventail de responsabilités, créez un objet, validez-le et, s'il est valide, stockez-le.
Cette opération est-elle intrinsèque à l'objet domaine? Faites-en ensuite partie intégrante
ExamQuestion.Answer(string answer)
Cela correspond-il à une autre partie de votre domaine? met ça ici
Basket.Purchase(Order order)
Préférez-vous faire des services ADM REST? Alors ok.
la source