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实现,以便依赖关系解耦.
你能提供什么建议?
I’ve read the “blue book” of DDD (Evans) as well as Nilsson and am not
clear what approach to validation I should take.
蓝皮书从不同的角度解决问题.我认为没有使用术语’验证’,因为它是一个危险的overgeneralization.更好的方法是考虑对象不变量,而不是验证.对象(不仅在DDD中)应该自己强制执行内部不变量.它不是UI或服务或合同或映射器或“验证框架”或对象外部的任何其他内容.不变量在内部强制执行.您可能会发现这些答案有用:1,2,3,4.
I could also put guards in the property setters that prevent
unacceptable values from ever putting the entity into an invalid
state. This would mean that AutoMapper would fail when trying to map
an invalid value.
您可能根本不应该关心AutoMapper失败或完全使用AutoMapper.域对象应封装并强制执行其内部不变量,并在尝试破坏它时抛出异常.它非常简单,您不应该因为某些基础结构问题而损害域对象的简单性和表现力. DDD的目标不是满足AutoMapper或任何其他框架的要求.如果框架不能与您的域对象一起使用,请不要使用它.