【问题标题】:DDD - storing Domain Objects in document oriented storages, PostgreSQL, MongoDBDDD - 在面向文档的存储、PostgreSQL、MongoDB 中存储域对象
【发布时间】:2016-12-11 05:17:02
【问题描述】:
关于 DDD 的另一个问题。考虑持久化我的聚合(我不想使用事件溯源),我在互联网上搜索,发现 Vaughn Vernon 的 article 非常有趣。简而言之 - 作者赞扬了使用面向文档的存储,特别是 PostgreSQL 来存储具有整个结构的域对象的概念。
我的问题是 - 由于我是 DDD 概念的新手 - 在 DDD 开发中使用这种方法是否常见?我的意思是使用面向文档的存储将聚合存储为序列化的完整文档?
我认为以嵌套方式持久化聚合更接近 DDD 的想法,而不是使用 ORM 加载和映射。对于域对象的嵌套结构,文档格式似乎更加自然和灵活。
除了上面提到的文章,我没能找到更多关于这个概念的 cmets。
下一个问题是 - 在 PHP 环境中 - 有没有人试图将它与 Doctrine2 联系起来?它似乎可以自动序列化 POPO,并且可以通过某种方式使用 ValueObjects。
提前致谢!
【问题讨论】:
标签:
php
mongodb
postgresql
doctrine-orm
domain-driven-design
【解决方案1】:
我的问题是 - 由于我是 DDD 概念的新手 - 在 DDD 开发中使用这种方法是否常见?
是的 - 是的。
要记住的一件事:DDD 旨在帮助正确地对业务进行建模。如果 change 对域来说是一个有价值的属性(如果这个项目代表了您的业务的竞争优势,则可能是这种情况),那么您需要考虑聚合序列化,即轻松迁移到改进的模型。换句话说,如何将旧模型的表示映射到新模型?
如果您采用这种方法,那么您可能还想查看cqrs;数据块对于写用例来说是令人满意的,但只写领域模型并没有提供太多的商业价值。您可能会更轻松地开发最终一致的读取模型,而不是尝试从文档存储中按需构建复杂的预测。
您看到类似方法的另一个地方是使用事件源聚合的解决方案;写入是通过附加到历史记录来实现的,任何给定更改所涉及的实际状态通常存储在 blob 中。
【解决方案2】:
您可能从书中了解到,聚合持久性是通过使用存储库模式完成的。其目的是对领域模型隐藏持久性技术和实现细节。
根据定义,存储库只能存储和检索整个聚合。这就是为什么 Vernon 提到类文档存储是一个很好的候选者。在使用 RDBMS 进行聚合持久性时,您通常最终会使用 ORM 和复杂的映射。走这条路时,您会得到复杂的架构和非最佳查询、繁琐的更新逻辑等等。
这确实是 CQRS 在 DDD 社区中特别受欢迎的原因,因为传统的“收集式”存储库缺乏任何查询许多聚合和检索一些“报告式”数据的能力。蓝皮书提出了一些相当复杂的方法来做到这一点。 CQRS 消除了这个问题,但需要相当多的额外工作才能使两个模型保持同步。
还有另一种处理方法。通常,域模型不需要对聚合运行查询。域模型的“客户端”负责向域模型发送适当的“命令”或请求,以由某种应用程序服务处理。六边形架构中的这个“客户端”部分或“适配器”部分可以在不使用任何存储库的情况下在域持久性数据库上运行查询。它也是一种 CQRS,但使用一个数据库。