2

如果您需要在页面上生成只读数据列表,并且该数据自然会来自多个(可能是 5 个或更多)不同的存储库,您会怎么做?

我们正在使用 DDD,并且一直在强制通过存储库访问我们的数据库,但是出现了一个似乎不适合 DDD 的场景,我们正在尝试确定要使用的最佳模式。

例如,假设您有一个基于社区的网站,其中包含视频、论坛、博客等。您有一个包含评论列表的论坛页面。这很粗糙,但我希望它是有道理的。

<table>
<tr><td>User Name (with possible link)</td><td>User's community score.</td><td>User Avatar</td><td>User's E-mail</td><td>User's blog</td><td>User's videos</td></tr>
</table>
<table>
<tr><td>This is a comment.</td></tr>
</table>

所以每条评论都包含几个不同的部分:用户名、社区分数、头像、电子邮件、用户的博客和用户的视频页面。传统上,这些信息都来自不同的存储库。

问题在于效率。存储库可以最大化,但只能围绕为其创建的聚合。当您需要访问位于多个存储库中的数据时,使用存储库的读取访问效率会降低。

我的解决方案是使用相关信息创建一个 UserInformation DTO,并在 UserForumsRepository 中放置一个带有签名的方法

ILIst<UserInformation> GetUserForumsUserInformationByForumPostID(int forumPostID).

我的一位同事建议以这种方式使用 DTO 会破坏我们一直在使用的设计模式,并建议更好的方法是获取论坛评论 id 列表,然后将这些 id 传递到各个存储库以返回结果。

我自己的观点是,存储库的主要目的是封装对 CRUD 的 CUD 部分很重要的业务逻辑,但只读列表应该以最有意义的方式生成。如果合适的话,我认为从存储库中完全删除只读列表方法甚至是有意义的(例如,在跨多个不同类型页面使用的公共小部件中)。

你如何处理这种情况?

4

2 回答 2

1

我讨厌回答我自己的问题,但我没有任何评论,而且我似乎从通常的嫌疑人那里找到了答案:福勒。

在我们的设计中,与大多数简单的 DDD 相同,我们的应用程序直接连接到我们的存储库以获取和更新数据。但是,在更复杂的场景中,具体存储库和应用程序层之间还有一个额外的服务层。不是将对象从域模型传递给客户端,而是传递 DTO。

根据 Fower (PoEAA 401),您“......通常不能从域模型中传输对象,......因为这些对象通常连接在一个复杂的网络中,即使不是不可能,也很难序列化。” Fowler 继续说道:“相反,您必须从域对象中传输简化形式的数据。”

所以实际上,尤其是在分布式系统中,将 DTO 传递给客户端是常态。服务层如何从域层组装这些 DTO 应该是客户端不感兴趣的。

我必须承认,福勒的这番话让我有些苦恼。我非常喜欢在 ASP.Net MVC 中使用域模型的便利。它在创建主从 UI 设计模式视图时特别方便。当强类型视图与客户相关联时,只需一行代码即可包含 CustomerOrders.ascx 部分视图(类型为 IList)并将 customer.Orders 传递给部分视图。也许继续这样做是可以的,只要域对象没有行为,但这是一个未来的问题。

于 2010-03-23T17:24:42.850 回答
1

答案#2

这里需要的是具体存储库和客户端之间的额外服务层。有时,客户端需要的与存储库层提供的不同,尤其是在存储库可能是分布式的情况下。服务层允许您定义粗粒度的方法并向客户端隐藏细粒度的细节。通过服务层,您可以将轻量级 DTO 传递给客户端,而不是完整的业务对象。

为了将业务对象映射到 DTO 或反之,Automapper 工具变得非常流行。

于 2010-03-24T13:48:52.703 回答