Как избежать анемичной доменной модели - реальный пример - PullRequest
75 голосов
/ 18 мая 2010

Я пытаюсь понять модели анемичных доменов и почему они предположительно являются анти-паттернами.

Вот пример из реального мира.

У меня есть класс Employee, который имеет массу свойств - имя, пол, имя пользователя и т. Д.

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

Далее у нас есть система, которая включает в себя чередование входящих телефонных звонков и запросов веб-сайтов (называемых «лидерами») среди торгового персонала. Эта система довольно сложна, поскольку включает в себя круговые запросы, проверку праздников, предпочтений сотрудников и т. Д. Таким образом, эта система в настоящее время отделена от службы: 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
     }
}

Тогда на обратной стороне нашей формы запроса на сайте у нас есть такой код:

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

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

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

На самом деле я не сталкиваюсь со многими проблемами с этим подходом, но, предположительно, я должен кричать об этом, потому что это Модель анемичной области .

Но для меня неясно, куда должна идти логика в службе чередования лидов. Должен ли он идти впереди? Должен ли он пойти на сотрудника?

Как насчет всех внедренных репозиториев и т. Д., Которые требуются службе ротации - как они будут внедрены в сотрудника, учитывая, что в большинстве случаев при работе с сотрудником нам не нужны эти репозитории?

Ответы [ 4 ]

54 голосов
/ 18 мая 2010

В этом случае это не анемичная модель предметной области. Модель анемичной области предназначена для проверки и преобразования объектов . Так что примером этого может быть, если внешняя функция действительно изменила состояние сотрудников или обновила их данные.

В данном случае происходит то, что вы забираете всех сотрудников и выбираете одного из них на основе их информации. Хорошо иметь отдельный объект, который исследует других и принимает решения относительно того, что он находит. НЕЛЬЗЯ иметь объект, который используется для перехода объекта из одного состояния в другое.

Примером модели анемичной области в вашем случае может быть использование внешнего метода

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

, который принимает объект Employee и обновляет часы, отработанные за неделю, следя за тем, чтобы флаги поднимались, если часы превышают определенный предел. Проблема в том, что если у вас есть только объекты Employee, то вы не знаете, как изменить их часы в соответствии с правильными ограничениями. В этом случае способ справиться с этим - переместить метод updateHours в класс Employee. В этом суть анти-паттерна Анемичной Модели Домена.

29 голосов
/ 18 мая 2010

Я думаю, что ваш дизайн в порядке здесь. Как вы знаете, анти-шаблон анемичной доменной модели является негативной реакцией против тенденции избегать любого поведения, закодированного в доменных объектах. Но, наоборот, это не означает, что все поведение, относящееся к объекту домена, должно быть инкапсулировано этим объектом.

Как правило, поведение, которое неразрывно связано с объектом домена и полностью определяется с точки зрения того, что один экземпляр объекта домена может быть включен в объект домена. В противном случае, чтобы сохранить четкую ответственность, лучше поместить ее внешне в соавтора / службу, как вы это сделали.

14 голосов
/ 18 мая 2010

Это все в вашей голове - рассмотрите службу ротации как часть модели предметной области, и проблема исчезнет.

Ротация должна хранить информацию о многих сотрудниках, поэтому она не принадлежит ни руководству, ни любомуодин сотрудник объекта.Он заслуживает того, чтобы быть доменным объектом сам по себе.

Простое переименование «RotationService» в нечто вроде «Organization.UserSupportDepartment» делает это очевидным.

0 голосов
/ 03 августа 2015

Если ваша модель предметной области содержит только роли и вещи, а не действия как поведение, то она анемична. Тем не менее, я говорю о поведении в отношении модели , а не объекта . Я говорю о разнице между ними в другом ответе ... https://stackoverflow.com/a/31780937/116442

Исходя из вашего вопроса, вы нарушаете мои первые два правила моделирования предметной области: -

  1. Поведение, смоделированное как (записанное) Действия являются основой модели предметной области. Сначала добавьте их.
  2. Модель деятельности домена как классы, а не методы.

Я бы добавил в модель действие "Запрос". Благодаря этому модель имеет поведение и может комбинироваться и работать как группа объектов без внешнего контроллера или сценария.

EnquiryHandlerModel

...