在“DDD”中,处理不同版本实体的最佳模式是什么,例如列表中的实体与完整对象的对比。我想避免在列表中显示实体时获取我不需要的属性的开销
您是否在列表中使用了单独的实体类型,或者只是部分填充完整的实体类型? 你会使用继承吗?
答案 0 :(得分:0)
我理解您在域中创建模型“视图”的冲动,但会建议不要使用它。就个人而言,我使用域内的整个实体,无论情况如何。实体是实体,任何更少或更多的实体都不会感到干净。但这并不意味着我不能使用对实体的引用来帮助我集中精力使用列表中的项目。
实体未在我的实现中跨越域边界。相反,我返回一种类型的DTO并具有可以从中抽象视图的应用程序服务。例如,这允许演示者从DTO生成正确的视图模型并将其提供给视图。我不知道您是在谈论域服务或应用程序服务中的操作,但您可以做的一些事情可以应用于(或两者)。
您可以做某些事情来减少在域图层中使用整个实体的性能损失。要注意的一件事是实现某种缓存搁置实现。请求实体时,请检查它是否已缓存。如果是,则返回缓存版本。如果不是,请将其拉出然后在返回之前将其缓存。更新实体后,将其从缓存中逐出并进行更新。我特意创建了我的具体存储库实现,以实现缓存感知。使用这样的方法考虑的另一件事是尽可能多地进行细粒度操作是有益的。虽然这一开始似乎不合逻辑,但如果实体通常从您的数据存储中“获取”,则很容易设置一些日志记录来测量缓存未命中的缓存命中数。
完整的循环,对你的问题...我处理的大多数列表都很小,所以我承担了整个加载实体的惩罚。假设大多数用例涉及用户钻入一个或多个项目,则由于缓存搁置实现而预先缓存它们。项目的数量是流动的,但我通常将此方法应用于列表中少于二十五个实体的任何内容。
对于较大的列表,我只使用ID。最有可能的是,这里的用例是某种搜索结果。例如,搜索结果通常是分页的,这不符合上述模式。相反,我使用较大的ID列表作为我感兴趣的实体的滑动范围窗口,然后传递给我所有存储库都有的GetRangeById()方法 - 写入以故意获取标识符列表并将其加载到一段时间,所以他们被缓存。从本质上讲,这将采用一个更大的轻量级列表,并且只在我感兴趣的区域中为零。
通过这样的方法,要实现的重要一点是它具有高度可扩展性。它可能不像使用小数据集的非缓存方法那样快,但是对于更大的数据集会表现更好。这里的操作有一个隐含的性能开销,但它的速度也比标准的“加载”模式慢。
答案 1 :(得分:0)
您可以使用CQRS模式分隔查询处理和命令处理。你甚至可以在一个数据库上完成它。在这种情况下,您可以将视图模型直接映射到数据库中的表(例如,通过NHibernate)。命令(写入)将通过真实域模型并将保留在DB中。查询(比如给我一个实体列表)会绕过域直接做数据库。查询域对象没有意义,因为您实际上不会在其中调用任何业务逻辑,只需检索一些数据。
您还可以通过为命令端和查询端提供单独的存储,将此解决方案扩展为功能齐全的CQRS。查询方将通过复制或发布/订阅消息传递进行同步。