Java 我应该从应用程序服务或实体获取其他聚合值吗?

Java 我应该从应用程序服务或实体获取其他聚合值吗?,java,domain-driven-design,Java,Domain Driven Design,我有库存、目录和销售信息 我有一个不变量: 创建目录时,我们的销售量不能超过库存量 或者我应该将服务传递到目录中 class CatalogApplicationService { void createCatalog(ProductId productId, int numToSell) { Catalog c = new Catalog(productService, numToSell) catalogRepository.save(c) }

我有库存、目录和销售信息

我有一个不变量:

创建目录时,我们的销售量不能超过库存量

或者我应该将服务传递到目录中

class CatalogApplicationService {
    void createCatalog(ProductId productId, int numToSell) {
        Catalog c = new Catalog(productService, numToSell)
        catalogRepository.save(c)
    }
}

class Catalog {
    Catalog(ProductService productService, int numberToSell) {
        ProductValue pv = productService.byId(productId)
        if (pv.numAvailable < numberToSell) throw new IllegalArgumentException();
        setSku(pv.sku);
        setAmount(numberToSell);
    }
}

验证业务逻辑通常在服务层完成。模型应该只包含数据,而不是逻辑。因此,建议您采用第一种解决方案。

您不应在聚合目录中插入服务,而应将数据传递给它们,以使它们尽可能干净,没有不必要的依赖关系


此外,您应该在整个代码中使用通用语言UL。例如,抛出一般的IllegalArgumentException似乎不是来自UL。

将pv传递给目录构造函数而不是ProductService怎么样?Catalog c=新CatalogproductService.byIdproductId,numToSell;是的,这是我的第一个选择,哦,是的,但我的意思是将验证放在目录构造函数中。通过将pv传递给实体的创建者,我担心我正在向ApplicationService泄漏逻辑though@Fajarmf好的关切。我不会考虑将产品细节作为业务逻辑来检索,但更多的是支持工作流逻辑。如果确定收集数据的过滤规则非常复杂,那么可能会有所不同,但这里的问题只是传递一个PoductId。然而,我最担心的是你用Catalog这个词来描述一个订单。此外,由于Catalog AR依赖于外部数据,因此它只能以最终一致的方式保护规则。在createCatalog执行时,库存可能会更改。实际上,仅包含数据贫血症模型的模型是一种反模式:是的,我希望避免贫血症域模型。但有一点担心,当调用实体的contstructor@H我同意,但是如果一个人使用ORMs,他们通常会这样做,我认为这会产生更干净的代码,不是吗?嗯,你可以在ORM实体和应用程序之间创建一个层。依我所知,如果你使用ORM实体作为你的应用实体,你的程序是数据驱动的,而不是域驱动的,而且,根据我的经验,它更难维护。让ApplicationService收集数据的一个问题是,它感觉像某种域逻辑,我们应该把它放在实体中,对吗,域逻辑应该在实体中。但我对将DomainService传递给实体也有保留,我想知道这样做是否好。你的意思是,ApplicationService,从其他服务收集数据不是域逻辑?是的,它不是域逻辑。
class CatalogApplicationService {
    void createCatalog(ProductId productId, int numToSell) {
        Catalog c = new Catalog(productService, numToSell)
        catalogRepository.save(c)
    }
}

class Catalog {
    Catalog(ProductService productService, int numberToSell) {
        ProductValue pv = productService.byId(productId)
        if (pv.numAvailable < numberToSell) throw new IllegalArgumentException();
        setSku(pv.sku);
        setAmount(numberToSell);
    }
}