Сеттеры в модели домена

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

Пример:

customer.StreetName = ...
customer.City = ...

Хотя правильным способом сделать это было бы иметь метод customer.ChangeAddress, который затем мог бы публиковать событие и т. Д., По крайней мере, с моего понимания, это все здравая теория, и я могу полностью понять, почему сеттеры в модели предметной области на самом деле нежелательны.

НО: Без сеттеров в вашей модели предметной области эти методы довольно сложно протестировать.

Как мне заставить экземпляр клиента запускать мои тесты, если я не могу создать его, не имея либо громоздкого конструктора, который принимает ВСЕ аргументы, либо не выполняет магию отражения? Я использую NHibernate в бэкэнде, поэтому NHibernate уже выполняет некоторую магию отражения, чтобы заполнить эти поля в первую очередь.

Но очень плохо иметь ctor с 10 аргументами .. (То же самое можно сказать и о фабричном методе).

Есть какие-нибудь советы по этому поводу?

привет даниил


person Tigraine    schedule 15.09.2010    source источник


Ответы (2)


В классическом (не-CQRS) DDD рекомендуется вынести все данные в объекты-значения, чтобы ваши сущности были сведены к их основной функции: поддержанию идентичности.

В вашем примере Customer должен ссылаться на Address ValueObject и иметь метод ChengeAddress, который должен быть таким же простым, как:

public void ChangeAddress(Address address)
{
   //Consistency rules are here
   _address = address;
}

Постарайтесь перенести как можно больше логики из своих сущностей в свои объекты-значения. Они по своей природе более тестируемы, поскольку полезный объект мал и неизменен. Вы используете конструктор для создания экземпляра VO в заданном состоянии и его выполнения (обычно путем вызова метода, который возвращает другой преобразованный экземпляр VO).

И последнее, но не менее важное: исходя из своего опыта, я могу сказать, что если для тестирования вашей модели предметной области требуется дополнительная инфраструктура (например, отражение или любой другой инструмент), вы делаете это неправильно (вводя ненужную связь).

person Szymon Pobiega    schedule 16.09.2010
comment
Итак, какова альтернатива для объектов с глубоким вложением значений? Как их заменить? Я получил ~ 18 листов Excel с иерархическими данными, где почти все неизменяемо. - person Arnis Lapsa; 16.09.2010
comment
Хороший момент по поводу неизменности :) Почему это отличается в системе CQRS? Из того, что я понял, я мог бы использовать Event Sourcing даже с нормальной моделью домена, просто записывая все команды, которые вызывают в модель предметной области. - person Tigraine; 17.09.2010

Вы можете попробовать AutoFixture.

Добавьте немного любви к размышлениям, и домен станет вполне поддающимся проверке:

namespace Unit{
  using System;
  using System.Linq.Expressions;
  public static class ObjectExtensions{
    public static T Set<T,TProp>(this T o,
      Expression<Func<T,TProp>> field,TProp value){

      var fn=((MemberExpression)field.Body).Member.Name;
      o.GetType().GetProperty(fn).SetValue(o,value,null);
      return o;
    }
  }
}

Использование:

myUberComplexObject.Set(x=>x.PropertyOfIt, newValueOfIt);

И Вы должны хотя бы попытаться разделить эти «большие» объекты на более мелкие. Попробуйте создать иерархию (просто убедитесь, что она соответствует повсеместному языку).

person Arnis Lapsa    schedule 15.09.2010
comment
Я действительно стараюсь делать свои объекты достаточно маленькими. И заводские методы в тестах сейчас очень помогают. Но у клиента по-прежнему должна быть масса информации, например: имя (имя, фамилия, заголовок ...), адрес (4 поля), день рождения ... и многое другое, относящееся к конкретному приложению ... Но спасибо за указание я в AutoFixture - person Tigraine; 15.09.2010
comment
Извлеките адрес как CustomerAddress. Будет на 3 поля меньше. :) - person Arnis Lapsa; 15.09.2010
comment
Если вам нужно передать данные, вам нужно передать данные - person andho; 28.10.2010