75 votes

Éviter le modèle de domaine anémique - un exemple réel

J'essaie de comprendre Anémique Modèles de Domaine et pourquoi ils sont censés être un anti-modèle.

Voici un exemple réel.

J'ai une classe d'Employés, qui a une tonne de propriétés: nom, prénom, sexe, nom d'utilisateur, etc

public class Employee
{
    public string Name { get; set; }
    public string Gender { get; set; }
    public string Username { get; set; }
    // Etc.. mostly getters and setters
}

Ensuite, nous avons un système qui consiste à faire tourner les appels téléphoniques entrants et des enquêtes de site web (connu sous le nom 'conduit') uniformément parmi le personnel de vente. Ce système est assez complexe, car elle implique un aller-robining demandes de renseignements, de la vérification de vacances, des préférences des employés etc. Donc ce système est actuellement séparés dans un service: EmployeeLeadRotationService.

public class EmployeeLeadRotationService : IEmployeeLeadRotationService
{
     private IEmployeeRepository _employeeRepository;
     // ...plus lots of other injected repositories and services

     public void SelectEmployee(ILead lead)
     {
         // Etc. lots of complex logic
     }
}

Puis sur le dos de notre site web, formulaire de demande, nous avons un code comme ceci:

public void SubmitForm()
{
    var lead = CreateLeadFromFormInput();

    var selectedEmployee = Kernel.Get<IEmployeeLeadRotationService>()
                                 .SelectEmployee(lead);

    Response.Write(employee.Name + " will handle your enquiry. Thanks.");
}

Je n'ai pas vraiment rencontrer de nombreux problèmes avec cette approche, mais apparemment c'est quelque chose que je devrais courir en hurlant de, car il est un Anémique Modèle de Domaine.

Mais pour moi, il n'est pas clair où la logique dans la tête de rotation de service devrait aller. Faut-il aller dans la direction? Faut-il aller à l'employé?

Pour ce qui est de l'injection de référentiels, etc. que la rotation de service exige - comment pourraient-ils être injecté dans de l'employé, étant donné que la plupart du temps lorsque vous traitez avec un employé nous n'avons pas besoin de ces référentiels?

55voto

radman Points 3430

Dans ce cas, cela ne constitue pas une Anémie Modèle de Domaine. Une Anémie Modèle de Domaine est précisément à propos de la validation et de transformer les objets. Donc, un exemple de ceci serait si une fonction externe réellement changé l'état des Employés ou mis à jour leurs coordonnées.

ce qui se passe dans ce cas est que vous prenez tous les employés et de faire une sélection de l'un d'eux en fonction de leurs informations. C'est bien d'avoir un objet distinct qui examine les autres et prend les décisions relatives à ce qu'il trouve. Il n'est PAS normal d'avoir un objet qui est utilisé pour la transition d'un objet à partir d'un état à l'autre.

Un exemple d'une Anémie Modèle de Domaine dans votre cas serait d'avoir une méthode externe

updateHours(Employee emp) // updates the working hours for the employee

qui prend un objet Employé et les mises à jour de ses heures travaillées pendant la semaine, en s'assurant que les drapeaux sont levés si les heures de dépasser une certaine limite. Le problème avec cela est que si vous n'avez Employé les objets, puis vous n'avez aucune connaissance de la façon de modifier leurs heures dans les contraintes. Dans ce cas, la façon de traiter avec elle serait de déplacer la updateHours méthode dans la classe d'Employés. Qui est l'essence même de la faiblesse de Domaine Modèle anti modèle.

30voto

mdma Points 33973

Je pense que votre conception est bien ici. Comme vous le savez, la faiblesse de modèle du domaine de l'anti-modèle est une réaction contre la tendance à éviter tout comportement codées dans des objets du domaine. Mais à l'inverse il ne signifie pas que tous les comportements se rapportant à un objet de domaine doit être encapsulé par cet objet.

En règle générale, un comportement qui est intrinsicly liés à l'objet du domaine et est entièrement défini en termes de qu'un domaine instance d'objet peuvent être inclus dans le domaine de l'objet. Sinon, pour garder des responsabilités claires, il est préférable de le mettre en externe dans un collaborateur/service comme vous l'avez fait.

14voto

ima Points 4782

Tout est dans votre tête - considérez le service de rotation comme faisant partie du modèle de domaine et le problème disparaîtra.

La rotation doit conserver des informations sur de nombreux employés. Elle n'appartient donc pas au responsable, ni à un seul objet employé. Cela mérite de mériter d'être un objet de domaine en soi.

Renommer "RotationService" en quelque chose comme "Organisation.UserSupportDepartment" le rend évident.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X