Интересный поток появился, когда я набрал этот вопрос только сейчас. Я не думаю, что он отвечает на мой вопрос.
Я много работал с .NET MVC3, где желательно иметь анемичную модель. Просмотр моделей и моделей редактирования лучше всего использовать в качестве немых контейнеров данных, которые вы можете просто передать с контроллера на представление. Любые потоки приложений должны поступать от контроллеров, а представления обрабатывают пользовательский интерфейс. В MVC мы не хотим никакого поведения в модели.
Однако мы не хотим, чтобы в контроллерах не было никакой бизнес-логики. Для более крупных приложений лучше всего сохранить код домена отдельно от моделей, представлений и контроллеров и независимо от них (и, в общем, HTTP в этом случае). Таким образом, существует отдельный проект, который прежде всего предоставляет модель домена (с объектами и объектами ценности, составленными в агрегаты в соответствии с DDD).
Я сделал несколько попыток отойти от анемичной модели к более богатому в доменном коде, и я собираюсь отказаться. Мне кажется, что классы объектов, которые содержат данные и поведение, нарушают SRP.
Возьмем, к примеру, один очень распространенный сценарий в Интернете, составляющий электронные письма. Принимая во внимание какое-то событие, ответственность за создание объекта EmailMessage лежит на домене с учетом электронной почты, электронной почты и пользовательских значений. Шаблон существует как объект со свойствами, а пользовательские значения предоставляются в качестве ввода пользователем. Позвольте также сказать ради аргумента, что адрес EmailMessage FROM может быть предоставлен внешней службой (IConfigurationManager.DefaultFromMailAddress). Учитывая эти требования, кажется, что модель с богатым доменом может дать EmailTemplate ответственность за составление EmailMessage:
public class EmailTemplate
{
public EmailMessage ComposeMessageTo(EmailAddress to,
IDictionary<string, string> customValues, IConfigurationManager config)
{
var emailMessage = new EmailMessage(); // internal constructor
// extension method
emailMessage.Body = this.BodyFormat.ApplyCustomValues(customValues);
emailMessage.From = this.From ?? config.DefaultFromMailAddress;
// bla bla bla
return emailMessage;
}
}
Это была одна из моих попыток в богатой доменной модели. Однако, добавив этот метод, ответственность за EmailTemplate заключалась в том, чтобы содержать свойства данных сущности и составлять сообщения. Это было около 15 строк в длину и, казалось, отвлекало класс от того, что на самом деле означает быть EmailTemplate, и это значит, что IMO просто хранит данные (формат темы, формат тела, вложения и необязательный из/ответ на адреса).
Я закончил рефакторинг этого метода специальным классом, который несет ответственность за составление EmailMessage с учетом предыдущих аргументов, и я гораздо счастливее с ним. Фактически, я начинаю предпочитать анемичные домены, потому что это помогает мне разделять обязанности, делая классы и модульные тесты короче, более краткими и более целенаправленными. Похоже, что создание объектов и других объектов данных "лишенных поведения" может быть хорошим для разделения ответственности. Или я здесь не здесь?