The blue book is definitely worth a read if you want to get the best out of the DDD approach. DDD patterns are not trivial and learning the essence of each of them will help you ponder when to use which pattern, how to divide your application in layers, how to define your Aggregates, and so on.
The group of 2 entities you're mentioning isn't a Bounded Context - it's probably an Aggregate. Each Aggregate has an Aggregate Root, an Entity that serves as a single entry point to the Aggregate for all other objects. So no direct relation between an Entity and another Entity in another Aggregate that is not the Aggregate Root.
Repositories are needed to get hold of Entities that are not easily obtained by traversal of other objects. Repositories usually contain Aggregate Roots, but there can be Repositories of regular Entities as well.
In your example, Conversation seems to be the Aggregate Root. Maybe Conversations are the starting point of your application, or maybe you want to query them with detailed criteria so they are not satisfyingly accessible through simple traversal of other objects. In such a case you can create a Repository for them that will give the client code the illusion of a set of in-memory Conversations to query from, add to or delete from directly.
Messages on the other hand are easily obtained by traversal of a Conversation, and you might not want to get them according to detailed criteria, just all of a Conversation's Messages at once, so they might not need a Repository.
ConversationRepository will play a role in persisting Messages, but not such a direct role as you mention. So, no AddMessage() on ConversationRepository (that method rather belongs in Conversation itself) but instead, each time the Repository will persist a Conversation, it's a good idea to persist its Messages at the same time, either transparently if you use an ORM framework such as (N)Hibernate, using ad hoc SQL if you choose so, etc.
Could Vote, in this case be considered an "aggregate" and be deserving
of its own repository and aggregate status?
I think this might be the right answer. An aggregate should be a transactional consistency boundary. Is there a consistency requirement between votes on a match? The presents of a Vote collection on a Match aggregate would suggest that there is. However, it seems like one vote has nothing to do with the next.
Instead, I would store each vote individually. This way you can use the aggregate functionality of MongoDB to get the count, though I'm not sure whether it is still slow. If it is, then you can aggregate using the Map/Reduce functionality.
More generally, this may not be a best fit for DDD. If the domain doesn't consist of complex behavior there is hardly a reason to try to adapt the DDD tactical patterns (entity, agreggate) to this domain.
Best Answer
Depending on the collaborative degree of your application, you might find yourself in trouble if 2 or more users try to increment the same
Choice
concurrently. That will happen whether it's a VO or an Entity in the same Aggregate as thePoll
.To me the natural consistency boundary implied by the domain action of voting includes the user. So I would suggest a full fledged
PollChoice
Aggregate Root with a link to the User, or if there are multiple choices per poll, aPollResponse
AR containing all choices (which can then be VO's) made by a particular user to a specific poll.Edit : something along these lines