在域驱动设计中,存储库模式是否维护对对象的引用
In Domain Driven Design, does the Repository pattern maintain a reference to the objects?
我知道存储库模式抽象了域对象的持久性,允许开发人员从持久存储中读取/写入/删除对象,而无需知道对象是如何存储的(SQL,NoSQL,平面文件等)。我非常喜欢存储库模式,并发现它在许多情况下都运行良好,例如,从持久性逻辑中抽象业务逻辑,允许在适当的情况下延迟加载对象等。
但是,我不清楚的是存储库对象是否维护对所有对象的引用?例如:
Repository repository;
std::shared_ptr<Person> pPerson = repository.retrievePersonById("bob");
p->updateDetails("Bob", "the Builder");
repository.savePerson(p);
- 在上面的假设C++示例中,
repository
是否应该维护对返回的Person
实例的引用?是的 - 感谢纪尧姆31 的内存类比。 - 如果问题 1 的答案是"是",
repository
何时以及如何删除该Person
实例?据推测,这是引用计数达到零时。 - 如果 Q1 的答案是否定的,那么当另一个区域想要访问同一对象,但由于
repository
不再存储对它的内部引用,它会从数据库中冻结一个新副本,并且当您真正应该引用同一实例时,您实际上有两个Person
实例时,您如何处理这种情况?鉴于 Q1 的答案是"是",那么存储库始终维护一个引用,因此应始终返回相同的对象。
我实际上正在编写一个PHP应用程序,尽管上面的例子是C++的。
对于存储库来说,更合适的比喻可能是它是内存中对象集合的错觉。从任何 OO 语言中获取基本集合类型。如果从该集合中获取元素并修改该元素,则通常不必在之后将其保存回集合,因为它从未停止在集合中。
存储库也是如此 - 它提供对象,可以将对象添加到自身,但不公开任何用于将修改保存到底层存储的功能。事实上,这一切都是为了隐藏底层存储的存在。它也不会公开任何方法来"更新"实体的状态,因为它服务的实体在内存中,您可以自由修改它,它永远不会不同步。
如果存储库不干涉事务管理和提交工作单元,那也会更好。您应该将其委托给客户端(请参阅领域驱动设计第 156 页)。
为了回答您的问题,在业务事务中,您不应该假设存储库返回的对象的新鲜度。它们只是反映了某些实体在某个时间点的状态,您所要做的就是按原样使用它们。在更全局的层面上,一些外部机制(通常是ORM工具)将为您提供管理如何将您的小业务交易与其他交易隔离的能力,通常以工作单元实现的形式。刷新对数据库的更改和处理潜在的过时实体问题不是每个存储库的查询决策,而是一个更全局的业务事务级别的决策,只有在您决定用例已完成并且想要提交它时才应该发生。
相关文章:
- 在提升multi_index容器中,是否定义了"default index"?
- 在C++STL中是否有Polyval(Matlab函数)等价物?
- 检查输入是否不是整数或数字
- 是否可以初始化不可复制类型的成员变量(或基类)
- 在C++中,是否可以基于给定的标识符创建基类的新实例,反之亦然
- 是否可以通过C++扩展强制多个python进程共享同一内存
- 此代码是否违反一个定义规则
- 是否需要删除包含对象的"pair"?
- 是否可以从int转换为enum类类型
- 无论条件是否为true,if总是在c++中执行
- 如何找到大小'x'数组是否完全填充,在C++?
- 检查值是否在集合p1和p2中,但不在p3中
- 是否可以在编译时初始化数组,以便在运行时不会花费时间?
- 检查 std::shared_ptr<> 的当前底层类型是否为 T
- 是否很好地使用状态模式来维护当前选定的对象?
- libc++是否维护内部状态
- 在域驱动设计中,存储库模式是否维护对对象的引用
- 是否有任何序列容器也维护主键?(c++)
- std::map::erase(it++)是否维护一个指向映射中下一个元素的有效迭代器
- 是否可以跨静态断言维护状态