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