无聊介绍:
我知道 - DDD与技术无关。正如我所看到的 - DDD就是要与产品所有者一起创造无处不在的语言,并以如此简单和结构化的方式将其反映到代码中,以至于它不会被误解或丢失。
但是这里出现了一个悖论 - 为了摆脱领域模型中的应用技术方面,它至少从设计角度来看是技术性的。
上次我试图关注DDD - 它最终将域对象之外的整个逻辑变成了“魔术”服务和贫血领域模型。
我已经学会了一些新的忍者技巧,并想知道我这次是否可以处理歌利亚。
问题:
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
的东西,它通过构造函数接收必要的存储库,查询术语,执行一些额外的伏都教并返回布尔值(使相关逻辑远离对象本身并散布它知道在哪里)。 / p>
我认为做这样的事可能是可以接受的:
addProduct(product, productTypeValidityTermRepository){...}
但话又说回来 - 我无法自由地从多个规范中编写规范,这是他们的主要优势之一。
所以 - 问题是,在哪里这样做?商店如何知道条款?
答案 0 :(得分:2)
存在过度简化事物的风险:为什么不说明Product
是否是产品“知道”的新鲜事物? Store
(或任何其他类型的相关对象)不应该知道如何确定产品是否仍然新鲜;换句话说,freshSpecification
或productTypeValidityTerm
之类的事实甚至不应该为Store
所知,它应该只检查Product.IsFresh
(或者可能是其他一些对齐的名称)更好地利用现实世界,例如ShouldbeSoldBy
,ExpiresAfter
等。然后,产品可以通过注入存储库依赖性来了解如何实际检索protductTypeValidityTerm
。
在我看来,您正在外化行为,这应该是您的域聚合/实体固有的行为,最终导致(再次)成为贫血领域模型。
当然,在一个更复杂的情况下,新鲜度取决于环境(例如,预算商店中可接受的价格不值得在高级商店出售),您需要将整个行为外部化,这两者都来自产品并从商店,并创建一个不同的类型来模拟这种特殊的行为。
在评论后添加
我提到的简单场景沿着这些方向做了一些事情:制作Product聚合的FreshSpec
部分,它允许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);
}
}
}