I’m struggling designing this system where an address is the most central piece of information. Now in this case, an address is not just a few lines of strings. We’re storing municipalities (code, name), district (post code, name), streets (code, name), house number on a street in a specific district belonging to a municipal. It's a very normalized scheme.
So we have the entities Municipal, District, Street and HouseNumber each with relations to each other, defining a complete address for a person (or something else).
Now I have been trying to figure out if it would make any sense having an aggregate root named Address? An Address entity (aggregate root) would then have references to HouseNumber, Street, District and Municipal. Then a person would be associated to an Address.
Strictly speaking this aggregate root is not necessary, but if I don’t have it, I would have to traverse many objects to obtain the full address. Does it make any sense to create an aggregate root based on that argument?
A person will never reference anything but the aggregate root in this case, however the UI might display only Municipalities (when browsing addresses, etc.). Is this a violation of the aggregate root idea?
I would really like your advice and take on this problem. Any help will be much appreciated!
A little update from another discussion about my problem:
There is some invariants needed to be managed in the aggregate. For example; I
can't have a house number on a street thats in one district/municipality, where
the postal box is in another different district/municipality. So when assigning
a post box to an address/person, I need to make sure that they are in the same
district.
Also there are some consistency boundaries (if I understood this concept the
right way). If I have an address, this must have a house number in a district on
a street (in that district). A street can span multiple districts so it's
important to ensure that the house number on that street is in the correct
district.
Update about designing the aggregate:
A house number is actually the entry point for an address. A house number is associated with a street and a district. So a person is associated to a house number. What I also want to define is if a person has "postal responsibility" for that house number. Introducing the aggregate root Address, makes the person associate with that instead of the house number. In the database, the aggregate Address will contain a 1-1 association to a house number, and the Address has a 1-* to a Person. Where should I store the value indicating that the person has postal responsibility or not? Should I do this in the Address aggregate? Or where would
you put it? And the same goes for my entities - where should I indicate if the person has a postal responsibility?
To distinguish if address is value object or entity, ask Yourself a question - if person address changes and 2nd person had same address - will both change? If they both changes - address gets promoted to entity (cause address identity is important and not value).
To distinguish if address is entity or an aggregate root, ask Yourself a question - does address make any sense on it's own or it's always tied to person, is modified through it, deleted together with it? If it's not tied with person but exists on it's own (in model You are modeling and not reality), then address is an aggregate root.
Strictly speaking this aggregate root is not necessary, but if I don’t have it, I would have to traverse many objects to obtain the full address. Does it make any sense to create an aggregate root based on that argument?
No it does not. Technical issues shouldn't mess with Your domain. Entity can work as a 'sub-aggregate', address can hold together municipality, city, etc. and still be just an entity (cause it makes no sense w/o person).
A person will never reference anything but the aggregate root in this case, however the UI might display only Municipalities (when browsing addresses, etc.). Is this a violation of the aggregate root idea?
Presentation shouldn't mess with Your domain too. As far as i see - it's perfectly fine if You are showing only list of entities and hiding aggregates they belong to.
Two persons can be associated to the same address, and if one of them move the other doesn't move automatically.
Question is - how You want to model that moving process?
I see 2 ways:
When person #1 moves, address is modified but address of person #2 is not the same address and hence - is not affected. In this case - address is just an entity.
When person #1 moves, moving process switches address to another one. In this case - address is an aggregate root.
Addresses exists on their own and if a person move to an address, he gets associated with it.
This one means that You want to stick with 2nd way (when address is an aggregate root). It's fine and there is nothing wrong, but You should re-check if address can be demoted to entity cause that would make Your domain model less complex.
And keep in mind - there isn't "The model", there are only "A model"s. You can't model reality to mimic it perfectly, You can only model some part of it to solve specific problems.
This is why it's so hard to answer ddd related questions.
No one knows Your problems You are trying to solve.
If I understand it correctly (http://msdn.microsoft.com/en-us/magazine/dd419654.aspx - the part about aggregates), then whether an address can exist without a person (or other addressee) is irrelevant; the question is whether the address-constituents can exist or be accessed without the address. If they can, Address shouldn't be an aggregate root.
It is relevant. If address can't exist without a person (which is not a case here) - it's inevitably demoted as an entity (cause it makes no sense without person) or value object (if address itself has no identity). Otherwise - You are just introducing unnecessary aggregate root.
It's fine if aggregate root contains references to other aggregate roots (but not entities of other aggregate roots). Therefore - address constituents can be aggregate roots too (Municipality that is referenced in PostOffice) and that wouldn't change if address itself is entity or an aggregate root.
Aggregate, in my opinion, should be created if
there is a containment
relationship with its associated
objects
the objects of an
Aggregate are stored in a database,
and only the root should be
obtainable through queries. The
other objects should be obtained
through traversal associations.
and you have invariant rules that u need to enforce uniformly across the contained objects
your scenario doesn't seem to satisfy either of those 2. so my opinion is no
Also read this post and provided answers: DDD: Aggregate Roots
Whether Address should be a separate entity should not be driven by technical concerns.
The way you talk about an address tells me it is a separate entity made up of the constituent parts you mentioned.
The fact that the Address persists even when it isn't tied to a Person or another class, also is a clue that it should be its own entity.
Furthermore: Address can be used not just be a Person, but by other things (classes) as well. Do you really want to burden each class that can have an address to have to deal with how to form it from its consituent parts?
The fact alone that you are talking about an Address as a specific concept is enough to make it a separate class. Even in the case where an address would only exist as long as it is tied to another class, it would make sense to create a separate class, possibly a nested class in that case, just to separate the logic dealing with the address from the logic dealing with the rest of the person's attributes.
Update
If I understand it correctly (http://msdn.microsoft.com/en-us/magazine/dd419654.aspx - the part about aggregates), then whether an address can exist without a person (or other addressee) is irrelevant; the question is whether the address-constituents can exist or be accessed without the address. If they can, Address shouldn't be an aggregate root.
On the one hand an Address should be an aggregate of its constituent parts. But, the constituent parts of an address seem to be independent of address and can exist without it. After all, a municipality or street can exist without a "door" being present in either. So, I would say that this disqualifies Address as an aggregate root in DDD terms.
Update
As Tommy mentioned (see comments): A better question would be "Will the system ever manipulate a street/municipality directly, or will it always be the whole address?"
I would consider that selecting a municipality from a list in order to construct an address isn't "direct manipulation" when it is always done in the context of constructing an address. Similarly, I would not consider maintaining that list of municipalities "direct manipulation" if it is only maintained for use by an address.
Update
As Arnis points out, whether Address can exist independently of Person (or another entity) is relevant in as much as that dictates whether Address is an entity in its own right. As I understand it now, only entities can be aggregate roots.
Related
I really want to give some thought to this situation, I want to map addresses and properties. The address table is filled based on the information retrieved from google maps and inserted on the table. Repetition is present on the table, if a two different people register two properties on the same address (neighbors) (no property number is inserted) the address table will have two identical address with two different ids. I have two design ideas and both will work fine, no doubt about it but both seem weird somehow.
My first design, I will have each property table have and address_id.
Why it is weird for me, "it seems that the address table owns a property (the foreign key in the "main entity") when it is the opposite the property owns an address.
My second design, the address table will have two column to find the correct "property".
The property type and property id.
which design should I use. There's some other better option?
I simplified things a little, but the idea is 100% here.
The first design is, for most generic requirements, the standard implementation. A property has an attribute of an address
I' struggling with this question : how to tel if a concept is an aggregate root or just an entity (that is part of an AR) ? :
They both got Ids
They both are composed by entities or value object
Maybe if I need to reference an entity in an other AR then I need to make it an AR : if somewhere on the app I need to link something to a particular order line, then order line will become an AR.
Or it's just in terms of lifecycle, but if it is, I don't see the point of having an entity inside an AR : it's just value object.
Or maybe it's because an entity can change of AR then I'll promote it as AR.
Take a look at Udi Dahan blog post and comments below.
From a technical perspective, AR is a transactional boundary. In other words, a group of entities which should stay consistent all the time. Going extreme with this definition, AR doesn't even have to have an Id.
From a business perspective, it is a primary concept in your domain that is part of Ubiquitous language, whereas entities don't have to be.
For example for car selling companies, Car is an AR but engine, wheel, tires and so on are just entities. But if you extend your car selling company's software with a car manufacture capabilities, then: engine, tires, etc: would probably be AR on their own in that part of the software. So if you have a piece of software that sells cars and makes them, you would sometimes have different AR depending on a context. Some objects will be AR in one place and an entity in the other. DDD names this concept as a "bounded context" or a "domain".
I think your confusion comes with the lack of upfront design and not having those "bounded context" properly defined.
Entities can be retrieved only from within AR, and can't be referenced from another ARs. So when you delete AR, garbage collector should also collect all entites/valuesobject in it.
I make an AR everything that I need to retrieve by one(by id). You said that both (entities and AR) got ids. If entities got global ids, that would mean that you would want to retrieve them by id, so they should be ARs too.
Example of entity can be a reply to a post. You want to retrieve one post (AR), but you don't retrieve replies by id, you get replies from post AR. But if you would like to rate a reply, delete it, edit or something, then it will probably become an AR, because you will want to retrieve it without first retrieving post (and other replies with it, which would be an overhead).
Try to create small ARs (without big entity tree inside). When you want to reference AR from another AR, then do it by VO id, in example FooAggregateId(1). Don't make reference to AR object, otherwise you would have to load a lot of ARs all at once, or use lazy loading.
I recurrently run into an scenario similar to this:
A container business class that models a hierarchy.
A business class that participates in this hierarchy and is aggregated by the aforementioned class.
Let me give you an example.
A Map has Countries. Now the Map should know where each Country is, since its main responsability besides containing all countries is to know the locations and proximity of each. From this point of view, a functionality such as isNeighbour(Country A, Country B) seems like a correct addition to Map. However, each Country should also offer a method to know if a country is nearby. Say spain.isNeighbour(italy). This is indeed useful. Now, if I don't want to duplicate functionality and responsability, what approach should I take?
The current example I am working on is something for my university, each course requires other courses and also blocks the next level ones. The major is the one that contains all courses and dictates which course precedes which. Say I want to add a dependency of a course over another, e.g to take Calculus 2 you need Calculus 1... Should I go calculus.addRequired(calculus2) and then pass it to the major object, or maybe computerScience.addRequired(calculus1, calculus2)...
I don't want to have both alternatives because to me it seems it can lead to error, but at the same time I want each course to be able to answer what are its requirements. I don't really know how to distribute responsabilities correctly.
First thing is, that there is no problem calling each other.
You can have
boolean Map.isNeighbour(Country A, Country B) { return A.isNeighbour(B); }
or
boolean Country.isNeighbour(Country other) { return map.isNeighbour(this, other); }
Second seems to need reference to global map. First makes Map look like simple facade.
Second thing is that you say it is persisted. There also might be good idea to create a service, that will query DB with related parameters. This can be either Map or some repository service. This will also allow you to query with only identities of entities (eg. countryId) instead of full objects.
I believe neither of the solutions is better or worse. Only point of difference is where other developers expect the methods to be located. But when I think about it, this would mean Map will have all responsibilities of Country, thus breaking SRP, especially if it is not call-through to the country method.
I would put the isNeighbour() method into Country.
Country would contain a map of neighbours. And then the container can call this method on the country instance in question.
This way the logic is maintained by the countries, and the container simply delegates to answer the question to them.
In case of courses it is possible that Course-1 is required for Course-2 in Major-1, but not in Major-2. In this case I would introduce another class, e.g. CourseInMajor that would contain the required courses for a given course in a given Major.
I have a position, and some entities that use position as it's identifier (geography, biome, and so on). If I want to get acess to them, I would need to retrieve each one by it's position, which would cause repeated code. On the other hand, I could create a class that is a container, like a "location". But, in this case, to retrieve geography (for example), I would need to break demeter's law.
Repository.getLocation().getGeography().getHighestPeak();
Is there any other approach to this, or a common pattern that I'm missing? Keep in mind that this type of objects (that relate to position in the way I described) are very likely to grow large in number after a few months.
I'm not sure it's a good idea to have a Position as an ID
The Position of an entity is likely to change, which leads to an unstable identifier.
You won't be able to have multiple instances of a given entity with the same position.
On the other hand, I could create a class that is a container, like a
"location". But, in this case, to retrieve geography (for example), I
would need to break demeter's law.
Repository.getLocation().getGeography().getHighestPeak();
You're basically saying that a Location has an entity, which is a bit awkward. It seems much more natural to say that an entity has a position. How about
GeographyRepository.getGeographyByPosition(new Position(...)).getHighestPeak();
?
context:
I have an entity Book. A book can have one or more Descriptions. Descriptions are value objects.
problem:
A description can be more specific than another description. Eg if a description contains the content of the book and how the cover looks it is more specific than a description that only discusses how the cover looks. I don't know how to model this and how to have the repository save it. It is not the responsibility of the book nor of the book description to know these relationships. Some other object can handle this and then ask the repository to save the relationships. But BookRepository.addMoreSpecificDescription(Description, MoreSpecificDescription) seems difficult for the repository to save.
How is such a thing handled in DDD?
The other two answers are one direction (+1 btw). I am coming in after your edit to the original question, so here are my two cents...
I define a Value Object as an object with two or more properties that can (and is) shared amongst other entities. They can be shared only within a single Aggregate Root, that's fine too. Just the fact that they can (and are) shared.
To use your example, you define a "Description" as a Value Object. That tells me that "Description" with multiple properties can be shared amongst several Books. In the real-world, that does not make sense as we all know each book has unique descriptions written by the master of who authored or published the book. Hehe. So, I would argue that Descriptions aren't really Value Objects, but themselves are additional Entity objects within your Book Aggregate Root Entity boundery (you can have multiple entities within a single aggregate root's entity). Even books that are re-released, a newer revision, etc have slightly different descriptions describing that slight change.
I believe that answers your question - make the descriptions entity objects and protect them behind your main Book Entity Aggregate Root (e.g. Book.GetDescriptions()...). The rest of this answer addresses how I handle Value Objects in Repositories, for others reading this post...
For storing Value Objects in a repository, and retrieving them, we start to encroach onto the same territory I wrestled with myself when I went switched from a "Database-first" modeling approach to a DDD approach. I myself wreslted with this one, on how to store a Value Object in the DB, and retrieve it without an Identity. Until I stepped back and realized what i was doing...
In Domain Driven Design, you are modeling the Value Objects in your domain - not your data store. That is the key phrase. It means you are not designing the Value Objects to be stored as independant objects in the data store, you can store them however you like!
Let's take the common DDD example of Value Objects, that being an Address(). DDD presents that an Mailing Address is the perfect Value Object example, as the definition of a Value Object is an object of who's properties sum up to create the uniqueness of the object. If a property changes, it will be a different Value Object. And the same Value Object 9teh sum of its properties) can be shared amongst other Entities.
A Mailing Address is a location, a long/lat of a specific location on the planet. Multiple people can live at the address, and when someone moves, the new people to occupy the same Mailing Address now use the same Value Object.
So, I have a Person() object with a MailingAddress() object that has the address information in it. It is protected behind my Person() aggregate root with get/update/create methods/services.
Now, how do we store that and share it amongst the people in the same household? Ah, there lies DDD - you aren't modeling your data store straight from your DDD (even though, that would be nice). With that said, you simple create a single Table that presents your Person object, and it has the columns for your mailing address within it. It is the job of your Repository to re-hydrate that information back into your Person() and MailingAddress() object from the data store, and to split it up during the Create/Update operations.
Yep, you'd have duplicate data now in your data store. Three Person() entities with the same mailing address all now have three seperate copies of that Value Object data - and that is ok! Value Objects are meant to be copied and destoyed quite easily. "Copy" is the optimum word there in the DDD playbook.
So to sum up, Domain Drive Design is about modeling your Domain to represent your actual business use of the objects. You model a Person() entity and a MailingAddress Value Object seperately, as they are represented differently in your application. You persist them a copied-data, that being additional columns in the same table as your Person table.
All of the above is strict-DDD. But, DDD is meant to be just "suggestions", not rules to live by. That's why you are free to do what myself and many others have done, kind of a loose-DDD style. If you don't like the copied data, your only option is that being you can create a seperate table for MailingAddress() and stick an Identity column on it, and update your MailingAddress() object to have now have that identity on it - knowing you only use that identity to link it to other Person() objects that share it (I personally like a 3rd many-to-many relationship table, to keep the speed of the queries up). You would mask that Idenity (i.e. internal modifier) from being exposed outside of your Aggregate Root/Domain, so other layers (such as the Application or UI) do not know of the Identity column of the MailingAddress, if possible. Also, I would create a dedicated Repository just for MailingAddress, and use your PersonService layer to combine them into the correct object, Person.MailingAddress().
Sorry for the rant... :)
First, I think that reviews should be entities.
Second, why are you trying to model relationships between reviews? I don't see a natural relationship between them. "More specific than" is too vague to be useful as a relationship.
If you're having difficulty modeling the situation, that suggests that maybe there is no relationship.
I agree with Jason. I don't know what your rationale is for making reviews value objects.
I would expect a BookReview to have BookReviewContentItems so that you could have a method on the BookReview to call to decide if it is specific enough, where the method decides based on querying its collection of content items.