Предотвращение анемичной модели предметной области - реальный пример

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

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

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

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

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

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

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

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

75
задан cbp 18 May 2010 в 05:49
поделиться

3 ответа

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

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

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

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

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

55
ответ дан 24 November 2019 в 11:42
поделиться

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

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

30
ответ дан 24 November 2019 в 11:42
поделиться

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

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

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

14
ответ дан 24 November 2019 в 11:42
поделиться