Question

Dans la littérature sur la conception pilotée par domaine, il est souvent dit que les services de domaine devraient être apatrides.

Je pense que la raison en est que les appels de service devraient représenter des unités de travail uniques.Il ne devrait y avoir aucun état de service que plusieurs méthodes de service utiliseraient.

J'enfreins cette règle dans mon architecture de service afin de pouvoir injecter par le constructeur tous les référentiels pertinents requis dans le service.Exemple:

public class UserService : IUserService
{
    public IUnitOfWork UnitOfWork { get; set; }

    public IUserRepository UserRepository { get; set; }

    public ICustomerRepository CustomerRepository { get; set; }

    public UserService(IUnitOfWork unitOfWork, IUserRepository userRepository, ICustomerRepository customerRepository)
    {
        UnitOfWork = unitOfWork;
        UserRepository = userRepository;
        CustomerRepository = customerRepository;
    }

    public User RegisterNewUser(...)
    {
        // Perform relevant domain logic
    }

    // ...
}

Pour que j'utilise l'injection de constructeur sur le UserService, j'aurais besoin d'un état (propriétés) pour que les méthodes de service aient accès aux référentiels pertinents et autres.

Même si j'espère concevoir les méthodes de service individuelles comme des unités de travail isolées, je ne peux pas nécessairement empêcher que cela se produise.

Comment puis-je architecturer les services de domaine de manière à ce qu'ils soient apatrides ? Est-ce même nécessaire ?

MODIFIER:

Éric Evans dans Conception basée sur le domaine :Aborder la complexité au cœur du logiciel:

Lorsqu'un processus ou une transformation significative dans le domaine n'est pas une responsabilité naturelle d'un objet entité ou de valeur, ajoutez une opération au modèle en tant qu'interface autonome déclarée comme service.Définissez l’attribut interface en termes de langage du modèle et assurez-vous que le Le nom de l’opération fait partie du LANGAGE UBIQUITAIRE.Faire le SERVICE apatride.

Vaughn Vernon recommande également les services aux apatrides dans son livre Implémentation de la conception pilotée par domaine.

Était-ce utile?

La solution

Une façon de vous rapprocher de votre objectif consiste à injecter un conteneur IOC dans votre classe de service, puis à remplacer vos méthodes get de propriété pour résoudre une instance de la classe nécessaire.Votre nouvelle classe ressemblerait à ceci :

public class UserService : IUserService
{
  private IUnitOfWork UnitOfWork 
  { 
    get{return container.Resolve<IUnitOfWork>()}
  }
  private IUnityContainer container {get;set;}

  public UserService(IUnityContainer container )
  {
    this.container = container;
  }

  public User RegisterNewUser(User user)
  {
     //Domain logic
  }

}

Votre classe de service dépend désormais d'un conteneur IOC, ce qui n'est pas une bonne chose, mais si vous essayez de vous rapprocher d'un service sans état, cela le ferait.

Autres conseils

Il me semble que vous confondez avoir des propriétés et avoir un état.

UserService est un service.Il n'a qu'une lecture seule (veuillez supprimer les setters) les propriétés qui sont des services apatrides, tels que IUserRepository.Cela fait UserService lui-même un service apatride.

Oui, nous pourrions même ajouter un service de niveau supérieur, doté d'un IUserService comme l'un de ses composants.Ce service serait également apatride.

Pourquoi demandes-tu?

Le but (ou du moins un Le but) de l’apatridie est de permettre l’inversion du contrôle :nous abandonnons le contrôle sur quelles instances nous obtenons vers l'extérieur.Si quelqu'un d'autre contrôle les instances que nous obtenons, alors ces instances feraient mieux d'être apatrides !Que se passe-t-il si nous obtenons la même instance qu’une autre classe et que nous commençons tous les deux à modifier son état ?L'issue serait indéterminée.

De toute évidence, ce problème est évité si nos services n'ont aucune propriété - comme UserRepository, peut-être.Notez également que c'est tout aussi bien évité lorsqu'un service de niveau supérieur, tel que UserService, possède exclusivement les propriétés en lecture seule de ces services, car il n'y a rien à attribuer.Nous pouvons être assurés que le service injecté se comportera toujours correctement, car il n’y a aucun état dans sa hiérarchie dont il puisse dépendre.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top