Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
841 views
in Technique[技术] by (71.8m points)

microservices - how to respect Post.CommentsAllowed if Post and Comment are separate aggregate roots?

In a classic example of 2 aggregate roots like:

class Post
{
  string AuthorId;
  string Title;
  string Content;
  boolean AllowComments;
  ...
}

class Comment
{
  string AuthorId;
  string Content;
  DateTime Date;
  ...
}

When creating new comment, how to ensure that comments are added only to the post that have Post.AllowComments = true?

Having on mind that when user starts writing comment Post.AllowComments could very well be true but in the meantime (while comment is being written) the Post author might change it to false. Or, even at the time of the submission => when we check Post.AreCommentsAllowed() it could return true but then when we do CommentRepository.Save(comment) it could be false.

Of course, one Post might have many Comments so it might not be practical to have single aggregate where Post have collection of Comments.

Is there any other solution to this?

PS. I could do db transaction within which i'd check it but i'm looking for a DDD purist solution.

question from:https://stackoverflow.com/questions/66051273/how-to-respect-post-commentsallowed-if-post-and-comment-are-separate-aggregate-r

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

i'm looking for a DDD purist solution.

Basic idea first: if our Comments logic needs information from our Post aggregate, then what we normally do is pass a copy of that information as an argument.

So our application code would, in this case, get a local copy of AllowComments, presumably by retrieving the handle to the Post aggregate root and invoking some query in its interface.

Within the comments aggregate, you would then be able to use that information as necessary (for instance, as an argument to some branching logic)


Race conditions are hard.

A microsecond difference in timing shouldn’t make a difference to core business behaviors. -- Udi Dahan

If data here must be consistent with data there, then the answer is that we have to lock both when we are making our change.

In an application where information is stored locally, that's pretty straight forward, at least on paper: you just need to acquire locks on both objects at the same time, so that the data doesn't change out from under you. There's a bit of care required to ensure that you get deadlocked (aka the dining philosophers problem).

In a distributed system, this can get really nasty.

The usual answers in "modern purist DDD" is that you either relax the consistency requirement (the lock that you are reading is allowed to change while you are working) and you mitigate the inconsistencies elsewhere (see Memories, Guesses, and Apologies by Pat Helland) OR you change your aggregate design so that all of the information is enclosed within the same aggregate (here, that would mean making the comment entities parts of the post aggregate).


Also: creation patterns are weird; you expect that the entity you are intending to create doesn't yet exist in the repository (but off the happy path maybe it does), so that business logic doesn't fit as smoothly into the usual "get the handle from the repository" pattern.

So the conditional logic needs to sneak somewhere else -- maybe into the Post aggregate? maybe you just leave it in the application code? ultimately, somebody is going to have to tell the application code if anything is being saved in the repository.

As far as I can tell, there isn't a broad consensus on how to handle conditional create logic in DDD, just lots of different compromises that might be "good enough" in their local context.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...