使用IoC在SOA应用程序中使用DDD进行验证

Son*_*ate 5 validation domain-driven-design

在我的服务外观层,我有一个服务类,其方法/操作接受DTO(数据契约)对象.AutoMapper用于将此DTO映射到我的域对象的实例以应用任何更改.请求将传递到我的域服务,该服务执行实际工作.这是方法的样子:

public EntityContract AddEntity(EntityContract requestContract)
{
    var entity = Mapper.Map<EntityContract, Entity>(requestContract);

    var updatedEntity = Service.AddEntity(entity);

    var responseContract = Mapper.Map<Entity, EntityContract>(updatedEntity);

    return responseContract;
}
Run Code Online (Sandbox Code Playgroud)

使用构造函数注入和Unity作为IoC容器来设置Service和Mapper属性.

在执行操作时,域服务对实体进行更改,然后使用存储库来保存更改,如:

public Entity AddEntity(Entity entity)
{
    // Make changes to entity

    Repository.Add(entity);

    // Prepare return value
}
Run Code Online (Sandbox Code Playgroud)

还使用构造函数注入设置存储库.

问题是,一旦数据被持久化,数据立即可供其他客户端使用,因此我必须确保不会保留无效数据.我已经阅读了DDD(埃文斯)和尼尔森的"蓝皮书",我不清楚我应该采取什么样的验证方法.

如果我的目标是阻止实体进入无效状态,我应该在服务方法中验证entityContract以确保在将请求传递给我的域服务之前满足所有规则吗?我不愿意这样做,因为我似乎打破了在服务外观中定义这些规则的封装.

我们使用薄外观层委托给域服务的原因是我们在API中暴露了粗粒度的接口,但是通过细粒度域服务的组合支持重用.请记住,多个Facade服务可能正在调用相同的域服务方法,也许将这些规则委托给域服务会更好,因此我们知道每个用法都经过验证.或者我应该在两个地方验证?

我还可以在属性设置器中放置防护装置,防止不可接受的值将实体置于无效状态.这意味着AutoMapper在尝试映射无效值时会失败.但是,当没有映射值时,它没有帮助.

我仍然无法理解这些规则是实体行为的一部分,并且确定对象是否有效应该封装在实体中.这是错的吗?

首先,我需要确定执行这些验证检查的时间和地点.然后我需要弄清楚如何用DI实现,以便依赖关系解耦.

你能提供什么建议?

Dmi*_*try 4

我读过 DDD (Evans) 和 Nilsson 的“蓝皮书”,但不清楚我应该采取什么方法进行验证。

蓝皮书从不同的角度解决了这个问题。我认为不使用“验证”一词是因为它是一种危险的过度概括。更好的方法是考虑对象不变量,而不是验证。对象(不仅在 DDD 中)应该自行强制执行其内部不变量。它不是 UI、服务、合约、映射器、“验证框架”或对象外部的任何其他内容。不变量在内部强制执行。您可能发现这些答案很有帮助:1、2、3、4

我还可以在属性设置器中放置防护装置,以防止不可接受的值将实体置于无效状态。这意味着 AutoMapper 在尝试映射无效值时会失败。

您可能根本不应该关心 AutoMapper 失败或使用 AutoMapper。域对象应该封装并强制执行其内部不变量,并在尝试破坏它时抛出异常。它非常简单,您不应该因为一些基础设施问题而损害域对象的简单性和表现力。DDD 的目标不是满足 AutoMapper 或任何其他框架的要求。如果该框架不适用于您的域对象,请不要使用它。