Как избежать анемичной доменной модели - реальный пример

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

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

У меня есть класс 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 ответа

Решение

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

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

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

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

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

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

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

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

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

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

Если ваша доменная модель содержит только роли и вещи, а не действия как поведение, то это анемично. Тем не менее, я говорю о поведении в отношении модели, а не объекта. Я говорю о разнице между ними в другом ответе... /questions/47547127/yavlyaetsya-li-anemic-domain-model-naborom-intellektualnyih-servisov-i-glupyih-obektov-bez-opredelennogo-povedeniya/47547137#47547137

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

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

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

EnquiryHandlerModel

Другие вопросы по тегам