我正在尝试学习领域驱动设计(DDD),我想我已经掌握了基本概念。但是有一些事情让我感到困惑。
在 DDD 中,持久性模型和域模型是不同的东西吗?我的意思是,我们在设计领域和类时只考虑领域问题;没关系。但是在那之后,当我们构建存储库或任何其他数据持久性系统时,我们是否应该创建模型的另一个表示以在持久层中使用?
我在想我们的域模型也用于持久性,这意味着我们的存储库从查询中返回我们的域对象。但是今天,我读了这篇文章,我有点困惑:
如果这是真的,那么将持久性对象与域对象分开会有什么好处?
我正在尝试学习领域驱动设计(DDD),我想我已经掌握了基本概念。但是有一些事情让我感到困惑。
在 DDD 中,持久性模型和域模型是不同的东西吗?我的意思是,我们在设计领域和类时只考虑领域问题;没关系。但是在那之后,当我们构建存储库或任何其他数据持久性系统时,我们是否应该创建模型的另一个表示以在持久层中使用?
我在想我们的域模型也用于持久性,这意味着我们的存储库从查询中返回我们的域对象。但是今天,我读了这篇文章,我有点困惑:
如果这是真的,那么将持久性对象与域对象分开会有什么好处?
可以这样想,领域模型应该不依赖任何东西,并且其中没有基础设施代码。域模型不应该是可序列化的,也不应该从某些 ORM 对象继承,甚至不应该共享它们。这些都是基础设施问题,应该与领域模型分开定义。
但是,如果您正在寻找纯 DDD 并且您的项目重视可扩展性和性能而不是初始开发速度。很多时候,将基础架构问题与您的“域模型”混合可以帮助您以可伸缩性为代价实现速度的巨大进步。关键是,您需要问自己,“纯 DDD 的好处是否值得在开发速度上付出代价?”。如果您的答案是肯定的,那么这就是您的问题的答案。
让我们从一个示例开始,您的应用程序以域模型开始,而数据库中的表恰好与您的域模型匹配。现在,您的应用程序突飞猛进,您在查询数据库时开始遇到性能问题。您已经应用了一些经过深思熟虑的索引,但是您的表增长得如此之快,以至于看起来您可能需要对数据库进行反规范化才能跟上。因此,在 dba 的帮助下,您提出了一种新的数据库设计,可以满足您的性能需求,但是现在这些表与以前的方式大不相同,现在您的域实体块分布在多个表中,而不是而不是每个实体都有一个表。
这只是一个示例,但它说明了为什么您的域模型应该与您的持久性模型分开。在此示例中,您不想拆分域模型的类以匹配您对持久性模型设计所做的更改,并从本质上更改域模型的含义。相反,您希望更改新的持久性模型和域模型之间的映射。
将这些设计分开有几个好处,例如可扩展性、性能和对紧急数据库更改的反应时间,但您应该权衡它们与初始开发的成本和速度。通常,从这种分离级别中获益最多的项目是大型企业应用程序。
评论员更新
在软件开发的世界里,有第 N 个可能的解决方案。正因为如此,灵活性与开发的初始速度之间存在间接的反比关系。作为一个简单的例子,我可以将逻辑硬编码到一个类中,或者我可以编写一个允许将动态逻辑规则传递给它的类。前一种选择将具有更高的开发速度,但代价是灵活性较低。后一种选择将具有更高程度的灵活性,但代价是开发速度较低。这在每种编码语言中都适用,因为总是有第 N 个可能的解决方案。
有许多工具可以帮助您提高初始开发速度和灵活性。例如,ORM 工具可以提高数据库访问代码的开发速度,同时还可以让您灵活地选择 ORM 支持的任何特定数据库实现。从您的角度来看,这是时间和灵活性的净收益减去工具的成本(其中一些是免费的),根据开发时间成本相对于业务需要。
但是,对于这种编码风格的对话,本质上就是领域驱动设计,你必须考虑编写你正在使用的工具所花费的时间。如果您要编写该 ORM 工具,甚至编写数据库访问逻辑以支持该工具为您提供的所有实现,那么与仅对您计划的特定实现进行硬编码相比,这将花费更长的时间关于使用。
总之,工具可以帮助您抵消自己的生产时间和灵活性价格,通常是将时间成本分配给购买工具的每个人。但是,任何代码,包括使用工具的代码,都将受到速度/灵活性关系的影响。通过这种方式,与将业务逻辑、数据库访问、服务访问和 UI 代码纠缠在一起的情况相比,领域驱动设计提供了更大的灵活性,但以生产时间为代价。领域驱动设计比小型应用程序更好地服务于企业级应用程序,因为企业级应用程序的初始开发时间与业务价值相关的成本往往更高,并且因为它们更复杂,它们也更容易发生变化,需要更大的灵活性。及时降低成本。
在 DDD 中,持久性模型和域模型是不同的东西吗?
在 DDD 中,您拥有域模型和存储库。而已。如果在存储库内部,您将直接持久化您的域模型,或者在持久化之前将其转换为持久性模型取决于您!这是一个设计问题,你的设计。这是您的存储库的实现细节,与域本身无关。
正如其他人指出的那样,每个选项都有其优点和缺点。看看这个答案,我详细介绍了其中的一些。
在 DDD 中,持久性模型和域模型是不同的东西吗?
是的,但这并不一定意味着一组不同的类来明确表示持久性模型。
如果使用关系数据库进行持久化,则诸如 NHibernate 之类的 ORM 可以通过映射到域类来处理表示持久性模型。在这种情况下,没有显式的持久性模型类。这种方法的成功取决于 ORM 的映射能力。例如,NHibernate 可以通过组件映射支持中间映射类。这允许在需要时使用显式持久性模型类。
如果使用文档数据库进行持久化,则通常对持久性模型的需求更少,因为域模型只需可序列化即可持久化。
因此,当存在无法通过 ORM 映射到域模型的复杂映射时,请使用显式持久性模型类。无论实现如何,域模型和持久性模型之间的区别仍然存在。