I'm currently designing a web application using DDD methodology. While distinguishing the Entities from value objects, I came across one such model element which I'm unable to decide to place under Entity /VO category.
Every Order will be associated with 1 and only 1 Comment History object which manages the List of Comments. Now when the order is edited, a user may add a comment. This gets appended to the comment history.
Comment History object as such doesn't mean anything when it comes to persistance. I'm planning to use nHibernate "component" so effectively only the list of comments gets written down to ORDER_COMMENTS table.
Order is an Entity.
Should Comment History (Various user's comments appended to the Order) be an Entity or VO?
CommentHistory is an entity.
Because You append comments to it instead of replacing whole history every time it changes.
That means - it's modifiable.
If it's modifiable, it must have an identity, a known "peg" on which You "hang" state changes.
If it has an identity which is independent from state, it's an entity:
Entity:
An object that is not defined by its attributes, but rather by a thread of continuity and its identity.
In contrast - value objects are identified by their state. If they are identified by state, then, if state changes, it's a different object already. Ability for objects to change their own identity would be too much freedom which eventually would lead into chaos. That leads to conclusion that value objects should be immutable (their state is defined only once, per construction).
Here's another example:
Assume Citizen is like comment. Citizens are "appended" to Country. If country was a value object, every time new citizen born, whole country would be needed to be reconstructed.
From my point of view I see the comment history as the value object, I mean, a comment history is just a collection of comments at a given time. despite the fact that you can reconstruct or not the comment history every time you add an comment to it, it does not have an identity and lifecicle of its own.
I mean if you have to comment histories with the same comments do we have two different comment histories? I do not think so, we have the same comment history, we do not care about the identity we care about the attributes, i.e. the comments inside the comment history to be the same.
So that for me the comment history is a V.O.
Thanks
Pablo
Comment is a value type for all the reasons described above.
CommentHistory is a property of the Order and does not require a separate object. It is simply a collection of Comment values. The Order maintains the collection internally and controls access through an AddComment method.
Related
I have recently dived into DDD and this question started bothering me. For example, take a look at the scenario mentioned in the following article:
Let's say that a user made a mistake while adding an EstimationLogEntry to the Task aggregate, and now wants to correct that mistake. What would be the correct way of doing this? Value objects by nature don't have identifiers, they are identified by their structure. If this was a Web application, we would have to send the whole EstimationLogEntry value object as a request parameter, along with the new values, just so we could replace the old value object with the new one. Should EstimationLogEntry be an entity?
It really depends. If it's a sequence of estimations, which you append every time, you can quite possibly envision an operation which updates the value only of the VO. This would use VO semantics (the VO is called to clone itself in-mem with the updated value on the specific property), and the command can just be the estimation (along with a Task id).
If you have an array of VO's which all semantically apply to Task (instead of just the "latest" or something)... it's a different matter. In that case, you'd probably have to send all of them in the request, and you'd have to include all properties too, but I'd say that the need to change just one, probably implies a need to reference them, which in turn implies a need to have an Entity instead of a VO.
DDD emphasizes the Ubiquitous language and many modelling questions like this ones will derive their answer straight from that language.
First things first, if there's an aggregate that contains a value object, there's a good chance that the value object isn't directly created by the user. That is, the factory that creates the value object lives on the aggregates API. The value object(s) might even be derived directly from the aggregates state instead of from any direct method call. In this case, do you want to just discard the aggregate and create a new one? That might make sense depending on your UL.
In some cases, like if you have immutable value objects (based on your UL), you could simply add a new entry into the log entry that "reverses" the old entry. An example of this would be bank accounts and transactions. If bank accounts are aggregate roots and transactions are the value objects. If a transaction is erroneously entered, you can simply write a reversing transaction to void it.
It is definitely possible that you want to update the value object but that must make sense in your UL and it's implementation must also be framed around your UL. For example, if you have a scheduling application and an aggregate root is a person's schedule while the value objects are meetings. If a user erroneously enters a meeting, what your aggregate root should do would be to invalidate the old meeting (flip a flag, mark its state cancelled e.t.c) and create a new one. These actions fit the UL for your scheduling app. The same thing as what you are calling "updating the entry" above.
I am trying to get to grips with the ideas behind DDD and apply them to a pet project we have, and I am having some questions that I hope that someone here would be able to answer.
The project is a document management system. The particular problem we have regards two notions that our system handles: That of a Document and that of a DocumentStatus.
A Document has a number of properties (such as title, author, etc). Users can change any of the Document's properties through out its life time.
A Document may be, at any time, be at a particular state such as NEW, UNDER_REVISION, REVISED, APPROVED etc. For each state we need to know who made that change to that state.
We need to be able to query the system based on a document status. An example query would be "Get me all documents that are in the REVISED state".
"Get me all documents whose status has been changed by user X"
The only time that a Document and a DocumentStatus need to be changed in the same transaction is when the Document is created (create the document and at the same time assign it a status of NEW).
For all other times, the UI allows the update of either but not both (i.e. you may change a document's property such as the author, but not its state.) Or you can update its state (from NEW to UNDER_REVISION) but not its properties.
I think we are safe to consider that a Document is an Entity and an Aggregate Root.
We are buffled about what DocumentStatus is. One option is to make it a Value Object part of the Document's aggregate.
The other option is to make it an Entity and be the root of its own aggregate.
We would also liked to mention that we considered CQRS as described in various DDD documents, but we think it is too much of a hassle, especially given the fact that we need to perform queries on the DocumentStatus.
Any pointers or ideas would be welcomed.
Domain
You say you need to be able to see past status changes, so the status history becomes a domain concept. A simple solution would then be the following:
Define a StatusHistory within the Document entity.
The StatusHistory is a list of StatusUpdate value objects.
The first element in the StatusHistory always reflects the current state - make sure you add the initial state as StatusUpdate value object when creating Document entities.
Depending on how much additional logic you need for the status history, consider creating a dedicated value object (or even entity) for the history itself.
Persistence
You don't really say how your persistence layer looks like, but I think creating queries against the first element of the StatusHistory list should be possible with every persistence mechanism. With a map-reduce data store, for example, create a view that is indexed by Document.StatusHistory[0] and use that view to realize the queries you need.
If you were only to record the current status, then that could well be a value object.
Since you're composing more qualifying - if not identifying - data into it, for which you also intend to query, then that sounds to me as if no DocumentStatus is like another, so a value object doesn't make much sense, does it?
It is identified by
the document
the author
the time it occurred
Furthermore, it makes even more sense in the context of the previous DocumentStatus (if you consider more states than just NEW and UNDER_REVISION).
To me, this clearly rules out modeling DocumentStatus as a value object.
In terms of the state as a property of DocumentStatus, and following the notion of everything is an object (currently reading David West's Object Thinking), then that could of course be modeled as a value object.
Follows How to model an entity's current status in DDD.
I'm trying to improve my design using some DDD concepts. Currently I have 4 simple EF entites as shown in the following image:
There are multiple TaskTemplates each of them storing multiple TasksItemTemplates. The TaskItemTemplates contains various information (description, images, default processing times).
Users can create new concrete Tasks based on a TaskTemplate. In the current implementation, this will also create a TaskItem for every TaskItemTemplate, but in the future it might be possible to select one some relevant TasksItemTemplates.
I wonder how to model this requirement in DDD. The reference from TaskItem to TaskTemplateItem is not allowed, because TaskTemplateItem is not an aggregate root. But without this reference it is not possible to get the properties of the TaskTemplateItem.
Of course I could just drop the reference and copy all properties from TaskTemplateItem to TaskItem, but actually I like the possibility to update TaskItems by updating the TaskTemplateItems.
Update: Expected behaviour on Task(Item)Template updates
It should be possible to edit TaskTemplate and TaskItemTemplate and e.g. fix Typos in Name or Description. I expect these changes to be reflected in the Task/TaskItem.
On the other hand, if the DefaultProcessingTime is modified, this should not change the persisted DueDate of a TaskItem.
In my current Implemenation it is not possible to add/remove TaskItemTemplates to a persisted TaskTemplate, but this would be a nice improvement. How would I implement something likes this? Add another entity TaskTemplateVersion between TaskTemplate and TaskItemTemplate?
Update2: TaskItemTemplateId as ValueObject
After reading Vaughn's slides again, I think with a simple modification, my model is correct according to DDD:
Unfortunately I do not really understand, why this Design is better (is it better?). Okay, there won't be unnecessary db queries for TaskItemTemplates. But on the other side I almost ever need a TaskItemTemplate when working with a TaskItem and therefore everything gets more complicated. I cannot any longer do something like
public string Description
{
get { return this.taskItemTemplate.Description; }
}
Based on the properties that you list beneath TaskItem and TaskItemTemplate I'd say that they should be value objects instead of entities. So if there isn't a reason (based on the information in your question there isn't) to make them entities, change them to immutable value objects.
With that solution, you just create a TaskItem from a TaskItemTemplate by copying its data.
Regarding the update scenario that you describe, it see the following solution:
TaskItems are created from a specific version of the TaskItemTemplate. Record that version with a TaskItem.
The TaskTemplate is responsible for updating its items and keep track of their version.
If a template changes, notify all Tasks that are derived from the template if immediate action is required. If you just want to be able to "pull in" the template changes at a later time (instead of acting when the template changes), you just compare the versions.
To make informed decisions, it is very important that you fully understand the pros and cons of immutability. Only then you will see a benefit in modelling things as value objects. One source on the topic that I find very valuable is Eric Lippert's series on immutability.
Also, the book Implementing DDD by Vaughn Vernon explains the concepts of value objects and entities very well.
I am working on an application where users can follow each other, in a similar fashion to Twitter.
After reading up on DDD, I understand that my users are Entity Objects - I refer to them using their unique ID.
When one user 'follows' another (i.e. forms a Connection), the relationship is stored in a many-to-many table. Its fields include FollowerID, TargetID, and Status. There can be only two records for each Follower/Target combination (one Active, the other Inactive), so I can safely identify objects based on their attributes.
So, I think my Connection objects are Value Objects, not Entity Objects, but I'm not sure. Can you help me with this decision?
You are correct that entities are unique and carry the notion of having an identity (i.e. only one unique user can exist). A Connection is dependent on other User entities. It represents some aspect between two users. That aspect is whether there is an active or inactive connection. Without containing the data of which users are connecting, a connection has no identity. It may even have it's own primary key in the database, but from a domain perspective, it has no identity of it's own.
Therefore, I would say that Connection is a value object.
To support my conclusion, Microsoft.Net Architecting Applications for the Enterprise, page 187, says:
A value object class represents an entity in the domain that mostly
contains data and lives for the data it contains. A value object is
fully identified by a combination of values it contains. An entity
object, on the other hand, has its own life and rich behavior
regardless of the data it contains. Entity objects are usually objects
with a longer lifetime. A value object represents an aspect of an
entity and can live only in relation to an entity.
And also on page 189:
One further comment is needed to explain the difference between
entities and value objects. You don’t need a repository or a data
mapper for a value object. You need a repository only for an entity.
The repository (or the mapper) for a given entity will certainly take
care of all value objects that depend on a given entity.
Some time ago, I saw a cartoon about scientist that had invented cloning. Every time he cloned himself, he destroyed previous version. Then person that was watching demonstration decided to interrupt and sabotaged destruction part so there were two scientists. Cartoon ended with some interesting existential questioning.
Values vs entities is not about having or not having id fields in one or another form. Point is - how we are looking at those objects through our domain perspective. If they are value objects, then only their value matters - 1st, 3rd and 53rd scientist are the same. If we care about identity, if we think that cloning 3rd scientist will never be like 1st one, then our object is an entity.
There is two things in my project Advertiser and BonusPrograms.
Business rules are -:
Advertisers will select bonus program from list of bonus programs.
Only one bonus program can be assigned at a time, previous bonus program will be discarded for that Advertiser.
BonusPrograms are not created by Advertiser, only assigned to them.
BonusPrograms are not created per advertiser, it is for all advertisers
Any new bonusprogram can be introduced at any time in project
My question are -:
1) I have created Bonus program as a separate agg root against Advertiser root aggregate because , advertiser does not create it, it only assigns it. Do I am correct ?
OR
2) Do i make BonusPrograms as valueobject under Advertiser Aggregate because only one bonusprogram is assigned to Advertiser, When a new one is assigned previous one is removed?
I'd go with option 3) which is that BonusProgram is an Entity, but not an Aggregate Root. It's hard to say w/o knowing more of your domain, but from what you described here, Advertising (or Marketing, or soemthing similar) is the aggregate, and Advertisers and Bonus Programs are entities under that aggregate. Not sure what the root would be for the aggregate from what you've said, but it doesn't sound like either Advertisers or Bonus Programs to me.
Firstly, let me say I agree with Paul, and you should accept his answer at some point. I'd have made this a comment but I can express my thoughts this way better.
You are asking two questions here, and there are two common sticky concepts in each.
The first question is the notion of where BonusProgram goes with respect to Advertiser if Advertiser is an aggregate root. This is definitely an interesting question, and depends on your domain and use cases. It doesn't depend on whether BP is a value object or entity though, as aggregates will typically contain both. The point of the aggregate is to simplify object traversal for external (to the aggregate root) objects. You accomplish that by picking one root entity that an external object can have a reference to, and only one (for a use case). This means that a client object can have a reference to Advertiser, but not BonusProgram. Advertiser will hold and necessary references to BP in order to satisfy the clinet object's request.
The second question is whether BP is a value object or an entity. Again the answer depends on your domain. The question to always ask yourself is whether you care about the objects identity or not. If you don't care, it is a value object; if you do care it is an entity. The classic case of a value object is Money - while you certainly care about it, you don't typically care about which dollar is which (one dollar is as wonderful as another)! In this case though, BonusProgram smells more like an entity, and you likely are interesting in knowing things like which BP was in effect last month and what were it's results compared to this month's BP.
Again, Paul is saying the same things and you should accept his answer.
HTH,
Berryl