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

时间:2011-09-28 00:32:06

标签: 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;
}

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

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

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

    Repository.Add(entity);

    // Prepare return value
}

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

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

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

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

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

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

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

您可以提供哪些建议?

2 个答案:

答案 0 :(得分:4)

  

我读过DDD(埃文斯)以及尼尔森的“蓝皮书”而不是   明确我应该采取什么样的验证方法。

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

  

我还可以在防止他们的财产安置者中放置警卫   将实体置于无效状态的不可接受的价值   州。这意味着AutoMapper在尝试映射时会失败   无效的值。

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

答案 1 :(得分:1)

您有两种类型的验证:

  1. 对象一致性:是实体的责任。实体不应允许您将它们设置为无效状态,应强制执行依赖项,值应在范围内。你必须设计类的方法和属性以及不允许无效状态的构造函数。

  2. 业务角色验证:此类验证需要服务器处理,例如检查ID可用性,电子邮件唯一性等。在持久性之前,应在服务器中将这些类型的验证作为验证器或规范进行处理。