DDD, обрабатывая зависимости

Скучное введение:

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

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

В прошлый раз я пытался следовать за DDD - он закончился с целой логикой за пределами объектов области на 'волшебные' службы все вокруг и анемичная модель предметной области.

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


Проблема:

class store : aggregateRoot { 
  products;
  addProduct(product){
    if (new FreshSpecification.IsSatisfiedBy(product))
      products.add(product);
  }
}

class product : entity {
  productType;
  date producedOn;
}

class productTypeValidityTerm : aggregateRoot {
  productType;
  days;
}

FreshSpecification как предполагается, указывает, не пахнет ли продукт. Чтобы сделать это - это должно проверить тип продукта, найти им дни, сколько времени продукт нов, и сравните его с producedOn. Вид простое.

Но здесь прибывает проблема - productTypeValidityTerm и productType как предполагается, управляются клиентом. Он должен смочь свободно добавить/изменить их. Поскольку я не могу пересечь от продукта до productTypeValidityTerm непосредственно, я должен так или иначе запросить их productType.

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

Я думал, что могло бы быть приемлемо сделать что-то вроде этого:

addProduct(product, productTypeValidityTermRepository){...}

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

Таким образом - вопрос, где сделать это? Как хранилище может знать об условиях?

7
задан 9 revs 9 February 2010 в 15:40
поделиться

1 ответ

С риском чрезмерного упрощения: почему бы не сделать тот факт, что Продукт свежий, чем-то «знает» продукт? Магазин (или любой другой связанный объект) не должен знать, как определить, свежий ли продукт; другими словами, тот факт, что что-то вроде freshSpecification или productTypeValidityTerm вообще существует, не должен быть известен Store , он должен просто проверить Product.IsFresh (или, возможно, какое-то другое имя, которое лучше соответствует реальному миру, например ShouldbeSoldBy , ExpiresAfter и т. Д.). Тогда продукт сможет узнать, как на самом деле получить protductTypeValidityTerm путем внедрения зависимости репозитория.

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

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

Добавлено после комментария

Нечто подобное для простого сценария, о котором я упоминал: сделать FreshSpec частью агрегата Product, что позволяет ProductRepository (здесь вводится конструктор ), чтобы (лениво) загрузить его при необходимости.

public class Product {
  public ProductType ProductType { get; set; }
  public DateTime ProducedOn { get; set; }
  private FreshSpecification FreshSpecification { get; set; }
  public Product(IProductRepository productRepository) { }

  public bool IsFresh() {
    return FreshSpecification
      .IsSatisfiedBy(ProductType, ProducedOn);
  }
}

Магазин не знает об этих внутренних компонентах: все, что его волнует, - это свежий продукт или нет:

public class Store {
  private List<Product> Products = new List<Product>();
  public void AddProduct(Product product) {
    if (product.IsFresh()) {
      Products.Add(product);
    }
  }
}
2
ответ дан 7 December 2019 в 18:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: