在许多领先的DDD项目中,特别是MVC样式,我看到UI使用镜像域实体的显示对象,而不是直接使用这些域对象。这种风格显然是为了解决和分离问题,我个人更喜欢这种风格。
但我不确定的是,这是否是DDD的严格原则,还是这不仅仅是开发人员对它的不同解释。
您是否可以直接在用户界面中使用域对象,并且仍然遵循该行为中的DDD方法?
或者总是使用显示对象是DDD的最佳做法吗?
注意:虽然我提到了MVC,但我真的很感兴趣是否必须在DDD项目中的几乎所有DDD兼容的UI模式中使用显示对象。
答案 0 :(得分:8)
如果你正在做一个MVC模式,你需要查看对象; DDD只是你的模特。这并不意味着你必须总是使用MVC;例如,可以构建DDD作为模拟器,您所看到的就是发出的日志消息。但是在MVC中你真的应该有单独的视图对象。
现在,问问自己为什么会这样?答案是视图可以更改,即使业务模型不。 DDD模型应该以业务的术语表达对业务至关重要的内容。
答案 1 :(得分:8)
在我开始关注Greg Young和Udi Dahan(通过Martin Fowler)的工作之前,我并没有真正开始理解为什么或如何将领域模型与演示问题解耦。
他们一直在教导一种称为Command and Query Responsibility Segregation(CQRS)的原则。
我对CQRS的解释是,有两组责任可以将领域模型拉向不同的方向,从而形成一个两者平庸的模型。这两个职责是命令(即,将导致写入数据库的行为)和查询(即,从数据库读取以便获取用于UI消费的数据)。一个示例是向实体添加getter和setter以支持UI中的数据绑定。如果您的模型具有getter和setter,那么它可能在建模需要在事务上发生的状态更改或封装业务逻辑方面做得很差。它也无法对状态变化的业务环境进行建模(参见事件采购)。
在DDD术语中,您可能会说域模型和表示模型通常位于单独的有界上下文中。
CQRS规定的解决方案是为命令创建一个模型,为查询创建另一个模型。如果当前模型具有更改状态的方法(即模型中的行为),以及将状态公开给UI以进行数据绑定的getter,则可以将这两个职责重构为命令和查询的单独模型。查询模型不会映射到您的域实体,而是直接映射到数据库。如果您的数据库未捕获域模型的派生状态,请查看名为Eager Read Derivation的模式。
如果你的系统只是CRUD并且没有任何行为,那么试试一个可以自动构建数据库模式的脚手架系统,比如ASP.NET动态数据
答案 2 :(得分:7)
DDD是一种在设计从域建模开始的软件时的思考方式。正如webpage所说:
域驱动设计不是一个 技术或方法。它是一个 思维方式和一套 旨在加速的优先事项 必须处理的软件项目 复杂的域名。
这种设计模式自然产生的一件事是分层架构。正如在DDD Pattern Summaries
中所说的那样将复杂程序划分为 层。在每个内部开发设计 LAYER是有凝聚力的 仅取决于下面的图层。 遵循标准架构模式 提供松耦合 以上层。集中所有代码 与域模型相关的一个 图层并将其与用户隔离 界面,应用程序和 基础设施代码域名 对象,没有责任 展示自己,存储 自己,管理应用程序 任务等都可以集中在 表达域模型。这个 允许模型发展为富裕 足够清晰,足以捕获 必要的商业知识和投入 它起作用。
是否需要显示对象来执行此操作?这只是实现这一点的一种方式,但可能甚至不是提供松散耦合的最佳方法。至于一个例子:也许视图层只是一个webbrowser和xlt文件来可视化业务层提取的xml文件?如果有人有更合适的例子,请添加它们。我的观点是DDD强调分层架构,但并不局限于一种可能的解决方案。
答案 3 :(得分:3)
在MVC设计中,您通常会有一个来自Repository的映射 - >域模型,然后来自域模型 - >查看模型。视图模型通常包含域对象。
答案 4 :(得分:1)
答案很简单:
如果您可以在视图中使用域对象,则它们可能不是面向域的。
答案 5 :(得分:0)
域对象实际上是业务逻辑层中的内部逻辑。它们不应直接暴露给您的客户(UI层)。相反,将域模型的使用封装到应用程序服务中。应用程序服务可以利用轻量级DTO和/或命令对象在客户端和域模型之间传递数据和意图。