c# - 如何管理域模型或数据访问模型或数据传输模型

标签 c# domain-driven-design

在DDD中,有许多模型:


域模型,用于繁忙或应用程序层。
数据访问模型,用于数据访问或数据存储库层。
表示层中使用的数据传输模型(DTO)。


由于它们,缺点产生了:


它们违反了DRY原理,因为它们之间存在许多重复字段并且无法避免。
他们需要很多烦躁的映射才能在不同层之间进行转换。


我们如何减少烦躁的模型?

最佳答案

最终,这是关于选择战斗的方法。域驱动解决方案中的主要考虑因素之一是,它专注于域的隔离和封装。这意味着,从这个前提出发,您将不​​想在每个项目中都将其用作一种方法。您需要具有要减少的内在复杂性,并且可以通过对业务需求和应用程序需求进行独立建模来实现。这意味着您不是在创建单个系统,而是在创建一个或多个正在使用完善子系统(您的域)的系统(您的一个或多个应用程序)。

就我个人而言,我没有在您的任何项目中描述的三种类型的数据承载类。相反,我只有我的域模型和基于每个不同UI要求的视图模型表示形式。我发现,需要单独的一组持久性类是多余的。有多种方法可以消除对持久性类的需求,例如具有代码优先EF的POCO,对象数据库/ NoSQL以及读取模型和写入模型的分离。在大多数情况下,我个人选择最后两者的组合。

我发现域和应用程序/ UI之间的转换层是必需的,因为域所代表的“真相”是绝对可靠的。但是,为了获得到域的可用接口,应用程序有时会对域有其他要求或不同要求。这意味着该转换层不仅涉及字段映射,还涉及不同概念的封装和使用场景的隔离。

由于该域绝对不知道如何使用它,因此这意味着需要翻译,并且不应尝试将其从系统中删除。我看到有人直接在UI中使用他们的域类作为实际模型,(在我看来)这比创建转换层更令人发指。您只是从翻译的角度来看它,但请记住,它也与孤立有关。在翻译中可以有效地拦截新概念的引入,现有概念的更改以及域内的其他更改,以防止对UI产生影响,反之亦然。

这听起来很琐碎,但在企业环境中,并非只有一个利用域的应用程序,而是多个应用程序,这并不罕见。考虑您的域正在提供桌面应用程序,Web应用程序和REST API的可能性。这些中的每一个都有自己的特定应用程序需求,这些需求与您的业务需求是分开的。他们也可能希望以不同的方式表示域。这意味着它们每个人都可能具有诸如不同的验证要求,对您的域的不同视图以及独特的应用程序功能之类的东西。无论如何,该域仍然幸福地遗忘了这一切。在域上方的某个地方,您将不得不为每个翻译不同的语言。

如果您发现自己的模型看起来与您的域完全一样,并且其中大多数是一对一的映射,则可能需要退后一步,寻找可能发生的其他问题。我发现大量的单一字段的双向映射是一种代码味道。并非总是,但通常,这是贫血领域模型的早期迹象。我个人尽力在域模型上强制执行架构要求,例如要求属性为只读(强制通过现有数据的构造函数设置属性,并通过类上的方法更改属性)等。编写架构单元测试很简单,它将反映您的域类以检查它们是否违反此类规则。但是,关键是,如果您发现翻译是您的痛点,请确保您的域模型不只是充当数据容器。贫血域模型是DDD实现中一个非常常见的陷阱,而贫血域模型实际上对DDD方法几乎没有好处,因为您将权力和责任从应该执行的地方移开了。

业务需求应反映域的需求,这与域的使用模式不同。理想情况下,您应该告诉域您要如何更改其状态,并且域应应用域逻辑来允许或禁止这些更改。如果您发现自己拉下了一部分域的完整域模型表示,将整个事物转换为模型或DTO,修改了该模型或DTO,将其转换回域表示,然后将整个事物发送回去,您可能有更大的问题。

关于c# - 如何管理域模型或数据访问模型或数据传输模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41393088/

相关文章:

java - 不要模拟值对象 : too generic rule without explanation

javascript - 使用 Ajax 的 URL Action 参数

c# - 如何从 app.config 获取此配置值?

c# - 我无法在 ODBC(RDO) 中找到数据源以使用 VS2015 添加到 Crystal 报告 Mysql 中

c# - 使用Gmail API发送电子邮件,在正文中编码希腊字符

php - 域模型 MVC 中的 native 数据库查询

c# - 如何解释 WP7 中滚动查看器偏移量的变化?

domain-driven-design - 除了 "real"对象之外,DDD 存储库还可以使用摘要对象吗

architecture - 如何在 DDD 中设计多阶段任务

c# - 域驱动设计布局问题