如果这些设计决策没有受到聚合边界的良好指导,请重新考虑模型。是领域的场景正在暗示着一个重要的新见解吗?这种改变通常会提高模型的表现力和灵活性,并解决事务和分配问题。
仓储
查询通用语言表达的聚合。
可遍历的关联的扩散只用于找到弄乱模型的东西。在成熟模型中,查询经常表达领域概念。然而查询可能会导致问题。
应用大多数数据库访问基础架构的纯粹技术复杂性迅速吞噬了客户端代码,导致开发人员陷入了领域层,使得模型无关紧要。
查询框架可能会封装大部分的技术复杂性,使开发人员能够以更自动化或声明的方式从数据库中提取所需的确切数据,但这只能解决一部分问题。
不受约束的查询可能会从对象中拉出特定的字段,违反封装,或从聚合内部实例化几个特定的对象,让聚合根变得充满变数并使这些对象无法执行领域模型的规则。领域逻辑移入查询和应用程序层代码,实体和值对象变成仅仅为数据容器。
因此:
对于需要全局访问的每种聚合类型,创建一个服务,它可以提供所有聚合根类型的对象的在一个内存集合中的错觉。通过一个大家都知道的全局接口设置访问。提供添加和删除对象的方法,这将封装实际数据往数据存储中的插入或删除。提供基于对领域专家有意义的标准来选择对象的方法。返回完全实例化的对象或属性值符合条件的对象集合,从而封装实际的存储和查询技术,或者返回给予以惰性的方式完全实例化的聚合的幻觉的代理。仅为实际需要直接访问的聚合根提供仓储。保持应用程序逻辑专注于模型,委托所有的对象存储和访问给仓储。
工厂
当创建一个完整的,内部一致的聚合或者一个大值对象变得复杂或者显示太多的内部结构时,工厂提供封装。一个对象的创建本身可以是一个主要的操作,但是复杂的组装操作不适合由创建的对象来承担。将这些职责结合起来可能会产生难以理解并且难看的设计。让客户端直接组装会混乱客户端的设计,破坏组装对象或集合的封装,并且过度地将客户端耦合到所创建对象的实现中【举个例子,这里的客户端可以理解成应用层或者UI层】。
因此:
将创建复杂对象和聚合实例的责任转移到单独的对象上,这个对象本身可能在域模型中没有职责,但仍然是领域设计的一部分。提供一个封装所有复杂程序集的接口,并且不要求客户端引用实例化对象的具体类。将创建一个完整的聚合作为一部分,强制实施它的不变性。创建一个复杂的值对象,可能是在将元素与构建器组合后。
作者:Zachary_Fan
出处:
如果你想及时得到个人自写文章的消息推送,欢迎扫描下面的二维码~。