I have similar scenario in Domain Driven Design Question on Services and Repositories and http://pastie.org/795679 which the azamsharp faces.
Since registration is value object, and user can have list of value objects, how can i save this registrations in user table because there is 1 to M relationship between User and Registration. Do i have to create seperate table for registration.
DDD or no DDD, it you have a 1-M relationship, the cleanest solution is a separate Registration table, with an FK back to the User.
Just because Registrations are Value objects, doesn't mean that you have to save them in the User table. It's a common misconception with DDD newbies. Maybe this answer can help.
Related
I am developing an online job portal using DDD patterns.
There are many "objects" that i have figured out like Users, Jobs, Roles, Expertise, ExperienceRange, Country, State, City, Address, Subscriptions, etc
My question is how do i figure out which of these is an entity or a value object or an aggregate? Please advice me if you have ever faced the same dilemma.
I have made the following decision:
Entities - User, Job, SubscriptionPackage
ValueObjects - Role, Expertise, ExperienceRange, City, State, Country
I know that we should not think about persistence while doing DDD modelling but a doubt has surfaced that whichever value objects i am storing in database should have an id or not?
if they have an id do they not violate the fundamental principal of ValueObjects and if we do not save them with ids then how to reference them in foreign key fields?
Please help me answer these queries.
If you can suggest which of the above mentioned objects are entities, which are value objects and which are aggregates that would be great.
Thanking in advance
When thinking of DDD, leave the DB mapping to a later stage. I know I'm repeating what you said, but just because it's true. A value object might have a DB id for other reasons (normalisation, reporting , etc).
First come up with your object model and then figure out how to map it. In some (rare) cases you might need to change slightly your object model if there's something that is too expensive to map properly (I cannot think of an example, but I don't want to be extremist).
So once more, forget about the DB - think about objects. For what reason does an entity have an id? I would say so then later it can be retrieved and modified, while keeping the same id.
And if it is a VO is because the identity is implicit in the values of the object. Does it make sense for a User to have an id? What about an Address? Or a City?... It depends.
To give the example of a city value object, if you need to map that as FK to 'cities' table, then your City object will probably have an id, but the id is not exposed. It's a detail of the implementation. While the user id would be exposed. For example a city might be linked to a province/state and that to a country.
But in another application, where users can add cities and information about them, the city might be an Entity or even an Aggregate. It really depends on your requirements.
Having said that, the list of Entities and VOs you provided looks ok in a general way, but I don't know your requirements.
To answer the first question: you can read Entities, Value Objects, Aggregates and Roots as there are some rules about what is a VO, Entity or Aggregate. The difficulty comes from how to apply them, and experience is the solution to that.
As a summary:
Entities
Many objects are not fundamentally defined by their attributes, but rather by a thread of continuity and identity.
Value Objects
Many objects have no conceptual identity. These objects describe characteristics of a thing.
Aggregates
Aggregates draw a boundary around one or more Entities. An Aggregate enforces invariants for all its Entities for any operation it supports.
In my system, an User can be member of a Team.
I got a domain model called Team which contains id, name, member_count and is_channel. So when I fetch teams in the repository I retrieve the Team domain model.
How would I model the relation between a User and a Team? Because when talking about the relation I don’t care about the member_count and is_channel from the Team model. I even have extra data in the relation which is a role_type.
Should I create a domain model for the relation called TeamScope or something? That contains id, user_id, team_id, role_type?
See my comments on your question regarding your use of terms (model, class, association). I'm assuming you are misusing them when I wrote my answer.
How would I model the relation between a User and a Team? Because when talking about the relation I don’t care about the member_count and is_channel from the Team model (sic). I even have extra data in the relation which is a role_type.
You could use an association class in your domain model to represent this.
Membership can capture the role_type, which really is linked to the association as you have figured out.
member_count is represented with a / at the start, indicating that you'll derive its value from the multiplicity (it's a count of the number of members associated with the team).
You tagged node.js in your question, so I'm going to point to how to implement association classes in Java (not exactly your case, but in Node.js it should be easy to apply).
You should almost definitely model a TeamMember object which contains both a link to the User, a link to the Team, and the role the user plays on that team.
Teams have a list of TeamMembers, Users have a list of TeamMembers. Teams have a MemberCount (not sure if this is static, or dynamic from the count of TeamMembers), and I have no idea what is_channel means...
Scenario: Cascading 1:1 Relationship as shown below.
I merely want to have an inverse relationship amongst a few entities, based on the userID field.
Questions:
1) How does the relationships know which field to link to?
All I did was indicate target and give the relationship a distinct name.
If the relationship is independent on the supplied userID, then I assume such field is superfluous; correct?
2) You'll notice that I need two (2) relationships: userID & userID2.
Essentially I merely want to link all common userId values across files. Is this the correct setup?
Core Data isn't a relational database, therefore you don't need a specific field to create a relationship between objects.
Typically you use relationships to model what would be a property on an object.
If you want UserConfigurations, UserCredentials, etc. to be related to a User then you should create a relationship between User and each of the user specific objects.
Then you can access a users configuration somewhat like this:
user.configurations
If you have set up inverse relationships, which Core Data recommends, you can also access the User from the UserConfigurations object. That allows you to access other parts of the object graph easily, e.g. you could access a users events from a users configuration:
configuration.user.events
This way you don't need relationships between the different objects that are related to a user.
Your data model should look similar to this:
I have two Entities Publisher and SocialAccount , both are independent and having relationship of Many to Many. Both are root Aggregates , now i cannot get social account through Publisher and I want to convert M To M relationship to 1 To M. So I Introduced another entity Registration , will have {PubID, SocID, CreateDate}. Now there is 1 To M relationship between Publisher and Registration and 1 to 1 between Registration and SocialAccount. so publisher will have
List <Registrations> _Registrations {get;set;}
But when I create aggregate boundaries, Publisher is my root and according to aggregate principle, only root aggregate will hold reference to another root aggregate. But here Registration hold reference.
So do i am violating aggregate principle , because registration is connected Social Account entity.
Your use of aggregate concept appears to be incorrect. Objects within an aggregate can in fact hold references to other aggregates. The rule is an external object cannot hold a reference to something within an aggregate.
On the Registration object, you seem to have created it to avoid some aggregate to aggregate relationships. That is not why you create an object. If there is in fact a Registration in your domain, create it and model it. If it is not in your domain, don't add it just to traverse some path.
Having added Registration, you say it cannot hold a reference to Social Account because it is part of Publisher. That is not the rule, but more important how did Registration suddenly become part of the Publisher aggregate anyway? By virtue only of Publisher having a Registration collection?
An aggregate is a group of objects that are treated as one unit for maintaining state and invariants. Existence of a relationship by itself does not confer membership in an aggregate.
But look at the other side now. Registration is 1 to 1 with Social Account. And if we remove a Social Account does it ever make sense to still have a Registration with a Publisher? If not then Registration probably is in fact part of the SocialAccount aggregate instead. That is why we create aggregates - to ensure objects and their relationships are always valid after a state change. If the change of state of removing a SocialAccount includes removing all Registrations associated with that account, we would want to include it in the aggregate to enforce that rule.
Now you have indeed violated the "aggregate rule" - you have an external relationship from Publisher to an object, Registration, that is an internal part of the SocialAccount aggregate.
These concepts are more than just rules, they have reasons. You need to review what aggregate really means, understand what the rules actually say and what they really mean, why they exist in the first place. Then reevaluate your relationships and aggregate definitions accordingly.
First we need an abstraction for encapsulating references within the model.
An AGGREGATE is a cluster of associated objects that we treat as a unit for the purpose of data changes.
Each AGGREGATE has a root and a boundary. The boundary defines what is inside the AGGREGATE. The root is a single, specific ENTITY contained in the AGGREGATE. The root is the only member of the AGGREGATE that outside objects are allowed to hold references to, although objects within the boundary may hold references to each other. ENTITIES other than the root have local identity, but that identity needs to be distinguishable only within the AGGREGATE, because no outside object can ever see it out of the context of the root ENTITY.
what you think about it Ssyphus?
I'm working a pretty standard e-commerce web site where there are Products and Categories. Each product has an associated category, which is a simple name-value pair object used to categorise a product (e.g. item 1234 may have a category "ballon").
I modelled the product as a root aggregate, which owns and knows how to modify it's category, which is an entity.
However, I ran into a problem where a user needs to be able to search a category. How am I supposed to implement this in DDD? I'm new to DDD but I believe that only root aggregates should be given it's own repository. So that leaves me with 2 options:
Add "SearchCategory" method to the ProductRepository
Implement the search logic as service (i.e. CategoryFinderService)
I personally think option 2 is more logical but it feels weird to have a service that touches database. Somehow I feel that only repository should be allowed to interact with database.
Can someone please tell me what's the best way to implement this?
IMHO, in your Domain Model, Category should not be child of the Product Aggregation. The Product has a Category, but it does not know how to create or edit a Category.
Take this another example. Imagine the ShoppingCart class, it's an aggregate root and contains a list of Items. The ShoppingCart is responsible for adding/editing/removing the Items, in this case you won't need a Repository for the Item class.
Not sure by the way, I'm new to this just like you.
Placing something You don't know where to put into artificial services usually leads to anemic domain model.
I would go with first option. But need for entities without context of root is a sign that You might lack another root.
Don't try to implement everything with your domain model. The domain model is powerful for changing the state of the system, but unnecessary complex for querying. So separate the two. It's called Command Query Responsibility Segregation, or CQRS. And no, it has nothing to do with Event Sourcing, even though they do work nicely together.
I implement scenarios such as this so that I have a domain logic side with the domain objects and repositories (if needed), which do the state changing when something happens, i.e. new order is placed or order is shipped. But when I just need to show something in the UI, for instance the list of the products filtered by the category, it is a simple query and does not involve the domain objects at all. It simply returns Data Transfer Objects (DTO) that do not contain any domain logic at all.