web-dev-qa-db-fra.com

Conception axée sur le domaine: service de domaine, service d'application

Quelqu'un peut-il expliquer la différence entre un domaine et une application en fournissant des exemples? Et, si un service est un service de domaine, est-ce que je mettrais l'implémentation réelle de ce service dans l'assembly de domaine et, dans l'affirmative, pourrais-je également injecter des référentiels dans ce service de domaine? Quelques informations seraient vraiment utiles.

236
Chris

Il existe 3 types de services: services de domaine, services d'application, et services d'infrastructure.

  • Services de domaine: Encapsule une logique métier qui ne rentre pas naturellement dans un objet de domaine et qui est PAS opérations CRUD typiques - celles-ci appartiendraient à un référentiel .
  • Services d'application: Utilisé par les consommateurs externes pour communiquer avec votre système (pensez Services Web ). Si les consommateurs ont besoin d'accéder aux opérations CRUD, ils seraient exposés ici.
  • Services d'infrastructure: utilisé pour résumer les problèmes techniques (par exemple, MSMQ, fournisseur de messagerie, etc.).

Il est judicieux de conserver les services de domaine avec vos objets de domaine. Ils sont tous axés sur la logique de domaine. Et oui, vous pouvez injecter des référentiels dans vos services.

Les services d’application utiliseront généralement les référentiels de services de domaine et pour traiter les demandes externes.

J'espère que ça t'as aidé!

314
Vijay Patel

(Si vous ne voulez pas lire, il y a un résumé en bas :-)

J'ai moi aussi eu du mal à définir avec précision les services d'application. Bien que la réponse de Vijay ait été très utile pour ma réflexion il y a un mois, je suis parvenue à être en désaccord avec une partie de celle-ci.

Autres ressources

Il y a très peu d'informations sur les services d'application. Des sujets tels que les racines agrégées, les référentiels et les services de domaine font l'objet de nombreuses discussions, mais les services d'application ne sont mentionnés que brièvement ou sont totalement exclus.

L'article de MSDN Magazine Introduction à la conception dirigée par un domaine décrit les services d'application comme un moyen de transformer et/ou d'exposer votre modèle de domaine à des clients externes, par exemple. en tant que service WCF. C'est ainsi que Vijay décrit également les services d'application. De ce point de vue, les services applicatifs constituent une interface avec votre domaine .

Les articles de Jeffrey Palermo sur l'architecture d'oignon (partie n , deux et trois ) sont de bonne lecture. Il traite les services d'application comme des concepts de niveau application , tels que la session d'un utilisateur. Bien que cela corresponde mieux à ma compréhension des services d’application, cela ne correspond toujours pas à mes idées sur le sujet.

Mes pensées

Je suis venu à penser aux services d’application en tant que dépendances fournies par l’application . Dans ce cas, l'application peut être une application de bureau ou un service WCF.

Domaine

Temps pour un exemple. Vous commencez avec votre domaine. Toutes les entités et tous les services de domaine qui ne dépendent pas de ressources externes sont implémentés ici. Tous les concepts de domaine qui dépendent de ressources externes sont définis par une interface. Voici une solution possible (nom du projet en gras):

 Ma solution 
 - My.Product.Core (My.Product.dll) 
 - DomainServices 
 IExchangeRateService 
 Produit 
 ProductFactory 
 IProductRepository 

Les classes Product et ProductFactory ont été implémentées dans l'assembly principal. Le IProductRepository est quelque chose qui est probablement sauvegardé par une base de données. La mise en œuvre de ce point ne concerne pas le domaine et est donc définie par une interface.

Pour l'instant, nous allons nous concentrer sur le IExchangeRateService. La logique applicative de ce service est implémentée par un service Web externe. Cependant, son concept fait toujours partie du domaine et est représenté par cette interface.

Infrastructure

L'implémentation des dépendances externes fait partie de l'infrastructure de l'application:

 Ma solution 
 + My.Product.Core (My.Product.dll) 
 - Mon.Infrastructure.Produit (My.Product.Infrastructure.dll) 
 - DomainServices 
 XEExchangeRateService 
 SqlServerProductRepository 

XEExchangeRateService implémente le service de domaine IExchangeRateService en communiquant avec xe.com . Cette implémentation peut être utilisée par vos applications qui utilisent votre modèle de domaine, en incluant l’assemblage d’infrastructure.

Application

Notez que je n'ai pas encore mentionné les services d'application. Nous allons regarder ceux maintenant. Supposons que nous voulions fournir une implémentation IExchangeRateService qui utilise un cache pour les recherches rapides. Le contour de cette classe de décorateur pourrait ressembler à ceci.

public class CachingExchangeRateService : IExchangeRateService
{
    private IExchangeRateService service;
    private ICache cache;

    public CachingExchangeRateService(IExchangeRateService service, ICache cache)
    {
        this.service = service;
        this.cache = cache;
    }

    // Implementation that utilizes the provided service and cache.
}

Notez le paramètre ICache? Ce concept ne fait pas partie de notre domaine, il ne s'agit donc pas d'un service de domaine. C'est un service d'application . C'est une dépendance de notre infrastructure qui peut être fournie par l'application. Introduisons une application qui démontre ceci:

 Ma solution 
 - My.Product.Core (My.Product.dll) 
 - DomainServices 
 IExchangeRateService 
 Produit 
 ProductFactory 
 IProductRepository 
 - Mon.Infrastructure.Produit (My.Product.Infrastructure.dll) 
 - ApplicationServices 
 ICache 
 - DomainServices 
 CachingExchangeRateService 
 XEExchangeRateService 
 SqlServerProductRepository 
 - My.Product.WcfService (My.Product.WcfService.dll) 
 - ApplicationServices 
 MemcachedCache 
 IMyWcfService.cs 
 + MyWcfService.svc 
 + Web.config 

Tout cela vient ensemble dans l'application comme ceci:

// Set up all the dependencies and register them in the IoC container.
var service = new XEExchangeRateService();
var cache = new MemcachedCache();
var cachingService = new CachingExchangeRateService(service, cache);

ServiceLocator.For<IExchangeRateService>().Use(cachingService);

Sommaire

Une application complète se compose de trois couches principales:

  • domaine
  • infrastructure
  • application

La couche de domaine contient les entités de domaine et les services de domaine autonomes. N'importe quel domaine concepts (cela inclut les services de domaine, mais également les référentiels) qui dépendent de ressources externes, sont définis par des interfaces.

La couche infrastructure contient la mise en œuvre des interfaces de la couche de domaine. Ces implémentations peuvent introduire de nouvelles dépendances non-domain qui doivent être fournies à l'application. Ce sont les services d'application et sont représentés par des interfaces.

La couche d'application contient l'implémentation des services d'application. La couche application peut également contenir des implémentations supplémentaires d'interfaces de domaine, si les implémentations fournies par la couche infrastructure ne sont pas suffisantes.

Bien que cette perspective puisse ne pas correspondre à la définition générale des services DDD, elle sépare le domaine de l'application et vous permet de partager le domaine (et l'infrastructure) Assembly entre plusieurs applications.

106

La meilleure ressource qui m'a aidé à comprendre la différence entre un service d'application et un service de domaine était l'implémentation de Java de l'exemple de fret d'Eric Evans, trouvé ici . Si vous téléchargez Pour cela, vous pouvez consulter les composants internes de RoutingService (un service de domaine) et de BookingService, CargoInspectionService (qui sont des services d’application).

Mon moment 'aha' a été déclenché par deux choses:

  • En lisant la description des Services dans le lien ci-dessus, plus précisément cette phrase:

Les services de domaine sont exprimés en termes de langue omniprésente et de types de domaine, c'est-à-dire que les arguments de méthode et les valeurs de retour sont des classes de domaine appropriées.

Ce que je trouve très utile pour séparer les pommes des oranges, c’est penser en termes de flux de travail d’application. Toute la logique concernant le flux de travail de l'application finit généralement par être factorisée dans la couche application des services d'application, alors que les concepts du domaine qui ne semblent pas correspondre à des objets de modèle finissent par former un ou plusieurs services de domaine.

35
Ghola

D'après le livre rouge (Implementing Domain Driven Design, de Vaughn Vernon), voici comment je comprends les concepts:

objets de domaine (entités et objets de valeur) encapsulent le comportement requis par le (sous) domaine, le rendant ainsi naturel, expressif et compréhensible.

Services de domaine encapsule de tels comportements qui ne rentrent pas dans un objet de domaine single. Par exemple, une bibliothèque de livres prêtant un Book à un Client (avec les modifications correspondantes de Inventory) pourrait le faire à partir d'un service de domaine.

Services d'application gérer le flux des cas d'utilisation, y compris les problèmes supplémentaires nécessaires au-dessus de du domaine. Il expose souvent ces méthodes via son API, pour la consommation par des clients externes. Pour reprendre notre exemple précédent, notre service d’application peut exposer une méthode LendBookToClient(Guid bookGuid, Guid clientGuid) qui:

  • Récupère le Client.
  • Confirme ses autorisations. ( Notez que nous avons gardé notre modèle de domaine exempt de problèmes de sécurité/de gestion des utilisateurs. Une telle pollution pourrait entraîner de nombreux problèmes. Au lieu de cela, nous remplissons cette exigence technique ici, dans notre service d'application.)
  • Récupère le Book.
  • Appelle le service de domaine (en passant le Client et le Book) pour gérer la logique du domaine réel du prêt du livre au client. Par exemple, j'imagine que la confirmation de la disponibilité du livre fait définitivement partie de la logique du domaine.

Un service d'application doit généralement avoir un flux très simple. Les flux de services d'application complexes indiquent souvent que la logique du domaine s'est écoulée hors du domaine.

Comme vous pouvez l'espérer, le modèle de domaine reste très propre de cette façon, et il est facile à comprendre et à discuter avec les experts du domaine, car il ne contient que le sien, préoccupations commerciales réelles. Le flux d'application, en revanche, est aussi beaucoup plus facile à gérer, car il est soulagé des problèmes de domaine et devient concis, et direct.

27
Timo

service de domaine est l'extension du domaine. Cela ne devrait être vu que dans le contexte du domaine. Ce n'est pas une action de l'utilisateur, comme par exemple , fermer un compte ou quelque chose du genre. Le service de domaine s'adapte là où il n'y a pas d'état. Sinon, ce serait un objet de domaine. Le service de domaine fait quelque chose qui n'a de sens que lorsqu'il est fait avec d'autres collaborateurs (objets de domaine ou autres services). Et cela donner un sens relève de la responsabilité d'une autre couche.

service d'application est la couche qui initialise et supervise l'interaction entre les objets et les services du domaine. Le flux est généralement le suivant: récupérez un ou plusieurs objets de domaine dans le référentiel, exécutez une action et mettez-la (ou les) à l'arrière (ou non). Il peut en faire plus - par exemple, il peut vérifier si un objet de domaine existe ou non et émettre des exceptions en conséquence. Cela permet donc à l'utilisateur d'interagir avec l'application (et c'est probablement de là que provient son nom) - en manipulant des objets et des services de domaine. Les services d’application doivent généralement représenter tous les cas d’utilisation possibles . La meilleure chose à faire avant de penser au domaine est probablement de créer des interfaces de service d’application, ce qui vous donnera une bien meilleure idée de ce que vous essayez réellement de faire. Avoir de telles connaissances vous permet de vous concentrer sur le domaine.

Les référentiels peuvent généralement être injectés dans des services de domaine, mais ce scénario est plutôt rare. Cependant, c'est la couche d'application qui le fait la plupart du temps.

24
kboom

Services de domaine: Les méthodes qui ne tiennent pas vraiment sur une seule entité ou qui nécessitent un accès au référentiel sont contenues dans les services de domaine. La couche de service de domaine peut également contenir sa propre logique de domaine et fait autant partie du modèle de domaine que les entités et les objets de valeur.

Services d'application: Le service d'application est une couche mince située au-dessus du modèle de domaine et coordonnant l'activité de l'application. Il ne contient pas de logique métier et ne détient pas l'état des entités; Cependant, il peut stocker l'état d'une transaction de workflow d'entreprise. Vous utilisez un service d'application pour fournir une API dans le modèle de domaine à l'aide du modèle de messagerie Demande-Réponse.

Millett, C (2010). Modèles de conception professionnels ASP.NET. Wiley Publishing. 92.

8
GorkemHalulu

Services de domaine : service qui exprime un logique applicative qui ne fait partie d'aucune racine agrégée.

  • Vous avez 2 agrégat:

    • Product qui contient le nom et le prix.
    • Purchase qui contient la date d'achat, la liste des produits commandés avec la quantité et le prix du produit à ce moment, ainsi que le mode de paiement.
  • Checkout ne fait pas partie de l'un ou l'autre de ces deux modèles et fait partie du concept de votre entreprise.

  • Checkout peut être créé en tant que service de domaine qui récupère tous les produits et calcule le prix total, paie le total en appelant un autre service de domaine PaymentService avec une partie d'implémentation d'Infrastructure et le convertit en Purchase.

Services d'application : service qui "orchestre" ou exerce des méthodes de domaine. Cela peut être aussi simple que juste votre contrôleur.

C'est l'endroit où vous faites habituellement:

public String createProduct(...some attributes) {
  if (productRepo.getByName(name) != null) {
    throw new Exception();
  }

  productId = productRepository.nextIdentity();

  product = new Product(productId, ...some attributes);

  productRepository.save(product);

  return productId.value();
  // or Product itself
  // or just void if you dont care about result
}

public void renameProduct(productId, newName) {
  product = productRepo.getById(productId);

  product.rename(newName);

  productRepo.save(product);
}

Vous pouvez faire des validations ici, comme vérifier si un Product est unique. À moins qu'un Product étant unique soit un invariant, il doit faire partie du service de domaine et peut être appelé UniqueProductChecker car il ne peut faire partie de la classe Product et il interagit avec plusieurs agrégats.

Voici un exemple complet de projet DDD: https://github.com/VaughnVernon/IDDD_Samples

Vous pouvez trouver de nombreux exemples de service d’application et quelques services de domaine.

2
doesnotmatter