Как избежать анемичной доменной модели - реальный пример
Я пытаюсь понять Анемичные Доменные Модели и почему они предположительно являются анти-паттернами.
Вот пример из реального мира.
У меня есть класс 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
Исходя из вашего вопроса, вы нарушаете мои первые два правила моделирования предметной области:
- Поведение, смоделированное как (записанное). Действия лежат в основе доменной модели. Добавьте их в первую очередь.
- Модель предметной деятельности как классы, а не методы.
Я бы добавил активность "Запрос" к модели. При этом модель имеет поведение и может объединяться и работать как группа объектов без внешнего контроллера или сценария.