2016-09-29 104 views
1

我们的团队有一个基本上是MIS的项目。 我们正在使用的架构是CQRS与DDD(域驱动设计)。 我们拥有持久层中的持久化对象,领域层中的域对象,数据传输对象以承载来自用户的输入信息,以及查看对象以在特定页面上显示数据。域对象是否可以与持久对象相同?

我认为这种设计是巨大的。但在项目实施过程中,我们发现了一些阻碍我们的问题。最令人厌恶的是我们必须编写许多转换器来在两个不同的层之间转换对象,如PO到DO,DO到PO,DTO到DO。这些转换器中有太多的get和set语句。我们之所以没有使用像BeanUtils这样的东西,是因为当两个对象中的字段具有不同的类型或名称时,它效果不佳。显然这些代码违反了开放原则。每当特定页面发生变化或者我们想要更改数据库中的字段时,这将是一场噩梦。

我不知道是不是真的不一定分开DO和宝,我们可以只简化架构和设计,使他们同样的事情,因为在大多数情况下,他们只包含差别不大相同的字段。 我们如何简化设计以避免我们面临的问题并提高我们的生产力并确保软件的可扩展性和稳定性?

+0

也许你有贫血的域模型。 https://en.wikipedia.org/wiki/Anemic_domain_model无论如何,你不应该做你正在计划的事情,因为它会导致贫血域模型。 ;-)据我所知... – inf3rno

+0

从域对象中分离持久化对象是IMO最近的一个趋势,这是由于ORM做了一个或多或少的离开域实体原始工作的不好的事实。关于测绘,还检查了http://blog.ploeh.dk/2012/02/09/IsLayeringWorththeMapping/ – guillaume31

+0

域对象模型的业务限制。持久化对象模拟数据应该如何存储在数据库中。目的非常不同。只是在简单的情况下,CRUD应用程序可以是相同的。 – MikeSW

回答

2

如果你看看DDD的战术模式,你会发现任何关于“域对象”。如果您聚合了根,那么您有聚合,它由实体和其中一个实体组成。每个有界上下文可能只有一个实体,这将是您的聚合根。

你坚持你的聚合作为一个整体。基本仓库以“集合样式”运行,只允许您将新集合放入存储库并通过其标识从存储库检索一个集合。

CQRS将一个对象分成两部分。一个对象是您的聚合优化写作。通常,在“写入端”你的命令处理程序中使用集合式存储库就足够了。然而,在“阅读方面”,你有更扁平的阅读模型,代表你想以一种为阅读而优化的方式展示给用户的内容。

如果你说你使用CQRS但只有一个模式,一个数据库,这不会有很大的意义。如果你有命令处理程序,这并不意味着你使用CQRS。

此澄清后,大家可以看一下总的持久性。 从来没有人说过你不能坚持聚合。从某种意义上说,如果您拥有合适的存储空间,这实际上是首选方法。通常情况下,ORM不是一个合适的存储,因为它会在你发现目标世界和关系数据库世界之间的阻抗不匹配的地方产生摩擦。文档数据库更适合于此。 PostgreSQL JSONB功能也是一个不错的选择。

流将被:

  • DTO(命令)从客户端发送
  • 工作单位开始
  • 命令处理程序检索从仓库聚集
  • 命令处理程序调用对聚合方法来执行必要的逻辑运算
  • 骨料可能发射可工作
  • 01的在同一单元内触发的事件处理程序的一些域事件工作
  • 单位提交更改

正如你看到的,对于任何持久性“转换”这里没有真正到位。如果你有一个合适的存储空间,那就很好。

当你阅读,但是,你有来自客户端的请求。然后,这个请求会转到某个查询提供程序,数据提供程序或任何您称之为的内容。有的把所有这些查询到他们的资料库,但是这仅适用,如果你使用CQRS或至少有一个持久性模型,而不是两个都

查询是幂等,它们不改变系统的状态,因为你没有后果一样,除了你的持久层,如果读不优化,可以加载可以运行多次。但是,读取方面不需要大量的抽象。同时,您不应将聚合发回给查询您的域的客户端。您需要拥有一个代表客户视图模型以满足特定需求的DTO,而不是更少。此DTO需要尽可能快地在客户端进行优化,无需计算和转换。这基本上是CQRS建议在读取方面做的 - 准备您的数据以快速交付这些DTO。