DDD - 每个实体一个存储库还是一个用于所有内容的存储库?

发布于 2025-01-07 10:31:52 字数 652 浏览 1 评论 0原文

首先,可能没有正确的答案,但我确信有人比我了解更多并且能够提供帮助。

我有 3 个实体:用户、博客、帖子。

系统可以有任意数量的用户。

用户可以拥有任意数量的博客,但每个博客只能有一个用户。

博客可以包含与用户要发布的帖子一样多的帖子,并且所有帖子都来自拥有该博客的同一用户(即,如果 John 拥有博客 Food,则只有 John 可以在此博客中发布帖子)。当然,每个帖子都有一个家长博客。

然后我有用户个人资料页面,我想在其中显示所有用户详细信息、他的所有博客的名称以及最后 5 个帖子。

然后我有一个博客页面,显示博客的详细信息、所有者(用户)的姓名和所有帖子的标题。

然后我有一个帖子页面,显示帖子详细信息、博客名称和所有者姓名。

正如你所看到的,我在它们之间都有关系,但它们都不能作为聚合体。

在代码中定义实体并不难,我真正遇到的问题是定义存储库。我需要多少? 3 - 每个实体一个? 1 - 一切?我如何进行查找?

例如,获取用户页面中最后 5 篇帖子。用户没有对帖子的引用,而是持有一个博客容器,其中每个博客又持有帖子容器。我的存储库中是否应该有一个接受 UserID 并返回帖子列表的方法?或者也许它应该是一项服务?另外,我通常不会加载所有数据,而是进行延迟加载。通过检索现有的用户实体,我不会加载其博客,除非需要它们(首次访问时)。

First of all there is probably no correct answer, but I'm sure there are people who knows more than me and will be able to assist.

I have 3 entities: User, Blog, Post.

The system can have any number of users.

User can have any number of blogs, but each blog have only one user.

Blog can have as many posts as the user will post, and all posts will be from the same user that owns the blog (i.e. if John owns blog Food, only John can post in this blog). And of course each post have one parent blog.

Then I have the user profile page, where I want to display all the user details, names of all his blogs, and last 5 posts.

I have then a blog page that displays details of the blog, the name of the owner (User) and titles of all posts.

Then I have post page that displays the post details, blog name and owner name.

As you see I have relations between all of them, but none of them can act as aggregate.

Its not that hard to define the entities in code, what I do have issues with is defining the repositories. How much do I need? 3 - one per each entity? 1 - for everything? How do I perform look-up?

For example to get the 5 last posts in the user page. User does not have reference to Posts, instead in holds a container of Blogs where each Blog in turn holds container of Posts. Should I have a method in my repository that accepts the UserID and returns a list of Posts? Or maybe it should be a Service? Also I don't usually perform loading of all the data but instead I have lazy loading. By retrieving an existing User entity, I would not load its blogs unless they are needed (when first time accessed).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

绝對不後悔。 2025-01-14 10:31:52

我会创建:

  • 用于处理帖子和评论的 PostRepository
  • BlogRepository 主要用于搜索
  • UserRepository

如果您不打算支持评论,我会删除帖子存储库并处理 BlogRepository 中的帖子

我通常对存储库进行建模使用后并避免聚合嵌套(超过两层)。

例如获取用户页面中最后 5 篇帖子。用户没有对帖子的引用,而是持有一个博客容器,其中每个博客又持有帖子容器。

恕我直言,用户不应该拥有博客容器。您有可以获取它的存储库。

我的存储库中是否应该有一个方法来接受 UserID 并返回帖子列表?

是的。

或者也许它应该是一个服务?

服务用于从使用域模型的代码中删除业务逻辑。在获得这种逻辑之前不要创建它们。

此外,我通常不会加载所有数据,而是进行延迟加载。通过检索现有的 User 实体,除非需要(第一次访问时),否则我不会加载其博客。

可以通过不具有将所有域模型链接在一起的属性来避免延迟加载。尝试仅具有子聚合的属性。

I would create:

  • a PostRepository used to handle posts and comments
  • BlogRepository used mostly for searching
  • UserRepository

If you are not going to support comments I would remove the post repository and handle posts in the BlogRepository

I usually model the repositories after their usage and to avoid nesting of aggregates (more than two levels).

For example to get the 5 last posts in the user page. User does not have reference to Posts, instead in holds a container of Blogs where each Blog in turn holds container of Posts.

imho the user should not have a container to the Blog. You have the repository to fetch it.

Should I have a method in my repository that accepts the UserID and returns a list of Posts?

yes.

Or maybe it should be a Service?

Service is used to remove business logic from the code that uses the domain models. Don't create them until you get that kind of logic.

Also I don't usually perform loading of all the data but instead I have lazy loading. By retrieving an existing User entity, I would not load its blogs unless they are needed (when first time accessed).

Lazy loading can be avoided by not having properties that link all domain models together. Try to only have properties to child aggregates.

淡淡绿茶香 2025-01-14 10:31:52

在决定是否拥有存储库之前,我会先考虑您的实体的重要性。

从测试驱动开发的角度来看,我将为每个实体都有一个存储库。这样我就可以拥有 IUserRepository、IBlogPostRepository 等的假实现。这种方法促进了单元测试,并允许我用存储库的一种实现替换另一种实现。

然后,我会将我的存储库分组为我认为合适的服务。实现此目的的一种方法是以适合您的要求的方式编写用例和分组。

例如,我可以说用户可以执行以下操作:

  1. 查看帖子
  2. 提交帖子
  3. 编辑帖子

我现在可以创建一个 IUserService 来查看、提交和编辑帖子。该服务将聚合(分组)我的存储库。

最后,我将能够执行以下操作。

var blogPost = new BlogPost();
ServiceFactory.Resolve<IUserService>(c => c.SubmitPost(blogPost));

现在,这是这样做的一种方法。

或者,您可能有一个 IBlogPostService ,它会公开非常相似的行为,或者您可以只使用存储库而不实现聚合服务。

我想要指出的一点是,你不应该纠结于小细节。通常有多种方法可以实现类似的行为,而你学习的唯一方法就是通过练习。

让你的存储库可重用,但要问你自己是否过度设计了某些东西,即我是否会单独使用这个存储库?一旦你有很少的存储库,请将它们包装在聚合服务中,

如果你的服务有超过 3 个(阈值完全取决于你)存储库。 ,然后考虑将此服务重构为两个单独的服务,

我希望这会有所帮助。

I would look at significance of your entity, prior to deciding whether I'll have a repository or not.

Looking from test-driven development side, I would have a repository for each entity. This way I can have a fake implementation of IUserRepository, IBlogPostRepository etc. This approach promotes unit testing and allows me to substitute one implementation of repository with another.

I would then group my repositories into services as I feel suited. One way of doing this, is to write use cases and group in a way that suits your requirements.

For example, I can say that a User can do the following:

  1. View post
  2. Submit post
  3. Edit post

I can now make a IUserService for viewing, submitting and editing posts. This service will aggregate (group) my repositories.

At the end, I'll be able to do the following.

var blogPost = new BlogPost();
ServiceFactory.Resolve<IUserService>(c => c.SubmitPost(blogPost));

Now, this is one way of doing this.

Alternatively, you might have a IBlogPostService which would expose very similar behaviour, or you could just use the repositories and not implement an aggregate service.

Point that I"m trying to make, is that you should not hang up on small details. There are normally multiple ways of achieving similar behaviour, and the only way you will learn is by practising.

Make your repositories re-usable, but ask yourself whether you are over-engineering something, i.e. am I ever going to use this repository on its own? Once you have few repositories, wrap them in aggregate service.

If you service has more then 3 (threshold is entirely up to you) repositories, then consider refactoring this service into two separate services.

I hope this helps.

蓝色星空 2025-01-14 10:31:52

用户通常是典型的聚合根。用户聚合可能包含用户偏好、用户统计数据,甚至可能包含博客。

我还认为 Post 是聚合根的一个很好的候选者,它周围有很多东西:评论、标签、类别...然后您可以为您的页面使用 PostRepository.LoadByBlog() 或 PostRepository.LoadByUser() 。

现在这只是从你所描述的情况推断出的一种可能性。每个域名都是独一无二的,您可能拥有我们不知道的改变游戏规则的信息。

User is often a typical aggregate root. The User aggregate may contain user preferences, user statistics, even Blogs maybe.

I also see Post as a good candidate for an aggregate root with a lot of things gravitating around it : Comments, Tags, Categories... You could then use PostRepository.LoadByBlog() or PostRepository.LoadByUser() for your pages.

Now this is only one possibility inferred from what you described. Every domain is unique and you might have game changing information we're not aware of.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文