域/持久性模型隔离通常会很尴尬吗?
我深入研究了域驱动设计(DDD)的概念,发现一些原则很奇怪,尤其是在域和持久性模型的隔离方面。这是我的基本理解: 应用程序层(提供功能集)上的服务从其执行功能所需的存储库中请求域对象。 该存储库的具体实现从为其实现的存储中获取数据 该服务告诉封装业务逻辑的域对象执行某些修改其状态的任务。 该服务告诉存储库保留修改后的域对象。 存储库需要将域对象映射回存储中的相应表示形式。 现在,鉴于以上假设,以下内容似乎很尴尬: 广告2: 域模型似乎加载了整个域对象(包括所有字段和引用),即使请求它的功能不需要它们。如果引用了其他域对象,则甚至可能根本无法完全加载,除非您同时加载这些域对象以及它们依次引用的所有对象,依此类推。想到了延迟加载,但是这意味着您开始查询域对象,这首先应该是存储库的责任。 鉴于此问题,加载域对象的“正确”方式似乎具有针对每种用例的专用加载功能。这些专用功能将仅加载其设计用例所需的数据。尴尬在这里发挥了作用:首先,我必须为存储库的每个实现维护大量的加载函数,并且域对象最终将null以其字段中携带的不完整状态结束。从技术上讲,后者应该不是问题,因为如果未加载值,则无论如何要求它的功能都不应要求该值。仍然很尴尬和潜在的危害。 广告3 .: 如果没有存储库的任何概念,领域对象将如何验证唯一性对构造的约束?例如,如果我想创建一个User具有唯一社会保险号(已给出)的新保险,则只有在数据库中定义了唯一性约束的情况下,最早的冲突将在要求存储库保存对象时发生。否则,User在创建新的社会保障之前,我可以寻找具有给定社会保障的a并报告错误(如果存在)。但是,约束检查将存在于服务中,而不存在于它们所属的域对象中。我刚刚意识到,域对象被很好地允许使用(注入)存储库进行验证。 广告5: 与让域对象直接修改底层数据相比,我认为将域对象映射到存储后端是一项工作量很大的过程。当然,将具体的存储实现与域代码脱钩是必不可少的前提。但是,确实付出了这么高的代价吗? 您显然可以选择使用ORM工具为您执行映射。这些通常需要您根据ORM的限制来设计域模型,或者甚至引入从域到基础结构层的依赖关系(例如,通过在域对象中使用ORM批注)。我也读过ORM引入了大量的计算开销。 对于NoSQL数据库(几乎不存在任何类似于ORM的概念),您如何跟踪域模型中的哪些属性发生了变化save()? 编辑:另外,为了使存储库访问域对象的状态(即每个字段的值),域对象需要显示其内部状态,这会破坏封装。 一般来说: 交易逻辑将流向何方?这当然是持久性特定的。一些存储基础架构甚至可能根本不支持事务(例如内存中的模拟存储库)。 对于修改多个对象的批量操作,我是否必须分别加载,修改和存储每个对象才能通过对象的封装验证逻辑?这与直接对数据库执行单个查询相反。 我希望对此主题进行一些澄清。我的假设正确吗?如果没有,解决这些问题的正确方法是什么?