Сеттеры в доменной модели - PullRequest
       88

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

2 голосов
/ 15 сентября 2010

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

Пример:

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

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

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

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

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

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

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

Ответы [ 2 ]

3 голосов
/ 16 сентября 2010

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

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

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

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

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

1 голос
/ 15 сентября 2010

Возможно, вы захотите попробовать Автофиксирование .

Смешайте немного отражения любви и предметной области, что вполне поддается проверке:

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);

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

...