I was learning about DDD recently and didn't quite understand the concepts. I have some questions about a sample blog application.
Let's assume that there are four domain objects in the blog system: User, Blog, Post and Comment. One User can have only one Blog, a Blog has multiple Post entities and a Post has many Comment entities.
My design is that Blog is the aggregate root:
class Blog {
private User;
private List<Post> posts;
}
class Post {
private List<Comment> comments;
}
class BlogRepository {
public void saveBlog(Blog blog);
public void findBlogById(long id);
public void getAllBlogs();
}
Am I right to design the aggregate root and repository like this?
I have some requirements to get all the Comment entities added by an user for all Blog entities, and also the User is allowed to modify her/his own Comment.
My question is how can I implement these requirements?
While the model you present reflects the domain, it isn't an optimal DDD implementation. With DDD, in addition to considering relationships between entities, you must also consider transactional consistency boundaries. As a result, it would be better to design a Blog, Post and User as separate aggregates which reference each other by ID only. Moreover, there is no reason that the Blog entity needs to have a collections of posts. You will never need to load the entire blog and behaviors never span multiple posts. Instead, provide a paginated repository method to load a subset of posts for a blog. A Comment however can be a value object and so the comments collection should be loaded together with the Post aggregate. The easiest way to get all comments for a user is to create a repository query method which returns a read-model to prevent conflating queries with behavior in your entities. For more on designing aggregates take a look at Effective Aggregate Design.
Related
I have been reading Eric Evan's book on DDD and on page 139 he states:
"if you needed to add elements inside a preexisting AGGREGATE, you might create a FACTORY METHOD on the root of the AGGREGATE"
I would assume that could be implemented something like this where the method NewLineItem is used to create and add a new line item to the order.
class Order
{
public IEnumerable<LineItem> LineItems { get; }
public void NewLineItem(Product product, int quantity);
}
Another way I could think of doing this is to move the factory method into the collection itself. Something like this below. I could then add a new item by calling LineItems.New(...).
class Order
{
public LineItems LineItems { get; }
public class LineItems : IEnumerable<LineItem>
{
public void New(Product product, int quantity);
}
}
What are the pros/cons to each approach? Are there any gotchas with moving the factory method into a collection? We are currently trying to figure out the best way to implement a large domain model. We are concerned that some of these root aggregate models will get bloated with numerous factory methods and deletion methods such as RemoveLineItem(LineItem). Our thinking is that moving these factory methods to their collections helps organize the design and keeps the root aggregate less cluttered with methods. Any advice?
Thanks
One advantage of having the factory method on the AR directly is that it makes the AR aware of the changes and allows it to enforce it's invariants. Not only that, but because the method is aware of the internal state of the AR you may be able to reduce the number of arguments passed to the factory method (most useful when creating other related ARs).
E.g. registration = course.register(registrant) vs registration = new Registration(registrant, courseId)
Also, LineItem becomes an implementation detail so the client doesn't need to be aware of that class.
The fact that you are asking this question and are actually worried of having too many methods on your ARs is perhaps an indicator that you may be clustering together objects that do not belong together.
Do not lose sight of the AR main purpose: it's a transactionnal boundary allowing to protect invariants. If there's no invariant to protect then clustering may be unecessary or even undesirable.
I would strongly advise you to read Effective Aggregate Design by Vauhgn Vernon.
There is always that "law" of Demeter business :)
The aggregate root (AR) is going to be responsible for the integrity and invariants. It may be possible that you will have an invariant along the lines of "maximum order total of $50 and no more than 6 line items at any time". The collection will not have access to any of this information (well, perhaps the count). So the idea is that the AR handles these interactions.
If you are concerned with bloat or find yourself with ARs that are unwieldy it may indicate a problem with your design. Vaughn Vernon covers these scenarios quite nicely in his book. You really do want highly cohesive ARs and it can be tricky to identify them correctly. A couple of iterations may be required to get the most comfortable design.
So I would try and stick with Eric's advice and handle the interactions on the AR itself as far as is practically possible.
I think I've read 16,154 questions, blog posts, tweets, etc about DDD and best practices. Apologies for yet another question of that type. Let's say I have three tables in my database, User, Department, and UserDepartment. All very simple. I need to build a hierarchy showing what departments a user has access to. The issue is that I also need to show the parent departments of those that they have access to.
Is it best to have a GetDepartments() method on my user class? Right now I have a user service with GetDepartments(string userName), but I don't feel like that is the optimal solution. If user.GetDepartments() is preferred then how do I get access the repository to get the parent departments for those that the user has access to?
Don't think it matters, but I'm using the Entity Framework.
public class User
{
[Key]
public int UserId { get; private set; }
[Display(Name = "User Name")]
public string UserName { get; private set; }
[Display(Name = "Email")]
public string Email { get; private set; }
[Display(Name = "UserDepartments")]
public virtual ICollection<UserDepartment> UserDepartments { get; private set; }
public List<Department> GetDepartments()
{
// Should this be here? and if so, what's the preferred method for accessing the repository?
}
}
DDD is more about the behavior, which also mean it is TDA (tell, don't ask) oriented.
Normally you structure your aggregates in a way that you tell them what to do, not ask for information.
Even more, if some extra information is required by the aggregate in order to perform its behavior, it is typically not their job to figure out where to get this information from.
Now, when you are saying that your User aggregate has GetDepartments method, it raises a bell. Does the aggregate need this information in order to perform any kind of behavior? I don't think so, it is just you wanting some data to display.
So what I see here is that you are trying to structure your aggregates against your data tables, not against the behavior.
This is actually #2 error when applying DDD (#1 is not thinking about bounded contexts).
Again, aggregates represent business logic and behavior of your system. Which means that you don't have to read from aggregates. Your read side can be done much easier - just make a damn query to the DB.
But once you need to ask your system to do something - now you do it through aggregates: AppService would load one from the repository and call its behavior method.
That's why normally you don't have properties in your aggregates, just methods that represent behavior.
Also, you don't want your aggregates to be mapped to the data tables anyhow, it is not their job, but the job of repositories. Actually, you don't want your domain to have dependencies on anything, especially infrastructure.
So if you want to go for DDD direction then consider the following:
Structure your aggregates to encapsulate behaviors, not represent data tables
Don't make your domain dependant on infrastructure, etc.
Make repositories to be responsible to load/save aggregates. Aggregates themselves should know nothing about persistence, data structure, etc.
You don't have to read data through aggregates.
Think of #4 as your system has two sides: the "read" side when you just read the data and show them in the UI, and the "command" side when you perform actions.
The first one (read) is very simple: stupid queries to read the data in a way you want it. It doesn't affect anything because it is just reading, no side effects here.
The second one is when you make changes and that is going through your domain.
Again, remember the first rule of DDD: if you don't have business logic and behavior to model then don't do DDD.
I'm building a new application and am new to Domain Driven Design. I've been reading through the documentation and I've managed to model most of the domain model but I would like some advice about two queries:
I have two domain objects channel and program. I've modelled these both as entities as both can be accessed independantly. A channel can have a list of programs so I have put this as an attribute of channel. My query is how should I populate the program list. Is it OK for the getChannerById method in ChannelService to first get the channel information and then call the ProgramService to get the list of programs for the channels e.g:
Channel {
String channelId
List <Program> programList
}
Program {
String programId {
}
ChannelService {
Channel getChannelById(String channelId)
}
ProgramService {
Program getProgramById(String programId)
List <Program> getProgramsByChannelById(String channelId)
}
I have a product domain object but some of its attributes (e.g. specification and compatability) involve quite time consuming operations. These attributes are not required all the time so is it OK to put these as part of the domain object and have seperate service methods that populate these attributes when required e.g.
Product {
String productId
Specification specification
List <Product> compatibleProducts
}
ProductService {
Product getProduct(String productId);
void getProductSpecifications(Product product);
void getCompatibleProducts(Product product);
}
Any advice would be very much appreciated.
When designing entities in DDD you shouldn't create associations from one entity to another such that the association is used for display or query purposes alone. While it is true that a channel has a set of programs, is the association between channel and the set of its programs required for the channel entity? More importantly, if you're only considering the query aspect then you may not need be forcing DDD upon your code. Instead, when designing entities consider the behavior that these entities need to implement. If your entities have no behavior but are only used as data containers then you don't need DDD. To answer your question, I would use read model classes that satisfy requirements of each query. For example, for your product model, if one query requires the specification attribute and another doesn't, create distinct read-model classes for those queries. These classes are not entities, they are simple read-only value objects, they don't have any behavior and their job is to represent data. In regards to implementing the query you have several options. Calling both the ChannelService and the ProgramService is one option. However, if the data is all stored together in a single database, why not just create a repository that returns all required data with one call? Take a look at my post on read-models in DDD for more on this topic.
I'm learning DDD and wanted to start modelling a fairly trivial example, a blog application.
One area I'm a little confused about is defining aggregate roots.
Here's my model so far:
Site
has many
Blog
has reference to Site
has many
Post
has reference to Blog
has Category
has many
Comments
In this example the only thing I am sure of is that Comment is a value object since it makes no sense outside the context of a post.
But then based on:
Only Aggregate Roots can be obtained directly with database queries.
Everything else must be done through traversal.
I would be inclined to make Site, Blog and Post ARs since I would want to obtain them all directly rather than traversing a collection.
I realize that a Blog isn't exactly a complex domain model so doesn't really warrant applying DDD but I just want to understand how these type of relationships are modelled.
It is not because you have a hierarchy that you must define an aggregate. The aggregate construct will come handy if you have invariant to maintain within the hierarchy.
In your example, assume that you want each post in a blog to have a unique 'slug' (Wordpress style, so that the title appears in the URL). Only the 'Blog' entity can enforce this invariant. Similarly, in that case it would make sense to make it the aggregate and have the post added via the blog entity.
Another example: your site can be public or private. This is an attribute of the Site entity. You must therefore make sure to access to a post using traversal from the aggregate root which would be the site since only the site can authorize you or not to access the underlying objects.
If you make the site the aggregate root, you could end up with an url like this:
http://site.com/myblog/apost
Your code would first retrieve the site entity, from that entity it gets the blog, and from the blog entity it fetch the post. How you go about retrieveing the child entities is up to you. This model does not force you to load all blog posts in memory when retrieving the site. It just force you to retrieve the blog from the site, and the posts from the blog.
I'm looking for some advice on architecture for a client/server solution with some peculiarities.
The client is a fairly thick one, leaving the server mostly to peristence, concurrency and infrastructure concerns.
The server contains a number of entities which contain both sensitive and public information. Think for example that the entities are persons, assume that social security number and name are sensitive and age is publicly viewable.
When starting the client, the user is presented with a number of entities, not disclosing any sensitive information. At any time the user can choose to log in and authenticate against the server, given the authentication is successful the user is granted access to the sensitive information.
The client is hosting a domain model and I was thinking of implementing this as some kind of "lazy loading", making the first request instantiating the entities and later refreshing them with sensitive data. The entity getters would throw exceptions on sensitive information when they've not been disclosed, f.e.:
class PersonImpl : PersonEntity
{
private bool undisclosed;
public override string SocialSecurityNumber {
get {
if (undisclosed)
throw new UndisclosedDataException();
return base.SocialSecurityNumber;
}
}
}
Another more friendly approach could be to have a value object indicating that the value is undisclosed.
get {
if (undisclosed)
return undisclosedValue;
return base.SocialSecurityNumber;
}
Some concerns:
What if the user logs in and then out, the sensitive data has been loaded but must be disclosed once again.
One could argue that this type of functionality belongs within the domain and not some infrastructural implementation(i.e. repository implementations).
As always when dealing with a larger number of properties there's a risk that this type of functionality clutters the code
Any insights or discussion is appreciated!
I think that this is actually a great example of using View Models. Your concern seems directly related to the consumption of the entities, because of the data that they contain. Instead of passing your entities all the way up to the UI, you could restrict them to live within the domain only - i.e. no entities are passed into or out of the domain at all, with most/all activities done with a command/query approach on the repositories. Repositories would then return a view model instead of the entity.
So how/why does this apply? You could actually have two different view models. One for authenticated and one for non-authenticated users. You expose the actual values for the sensitive data in the authenticated view model and not for the non-authenticated one. You could have them derived from a common interface, and then code against the interface instead of the object type. For your concrete implementation of the non-authenticated user, you can just populate the non-sensitive data, leaving the sensitive getters to do what you want them to do.
My opinion on a couple of points:
I am not a fan of lazy loading in entities. Lazy loading is a data access responsibility and not really part of the model. For me, it is a first-class member of the things I vehemently avoid in my domain, along with paging and sorting. As for how to relate these items together, I would rather loosely couple the objects via ID pointers to other entities. If I want/need the data contained by one of these entities, then I can load it. It is kind of like lazy loading in a way, but I enforce that it never happens in the domain model itself by doing this.
I am not a fan of throwing exceptions on getters. Setters, on the other hand, is fine. I look at it this way. The entity should always be in a valid state. Getters will not impact the state of the entity - setters will. Throwing on a setter is enforcing the integrity of the model. Using the two view model approach would allow me to move the logic to the presenter. So, I could basically do something like "if user is of type non-authorized, do this; otherwise do something else". Since what you are referring to would ultimately be a case of how the data is presented to the user, and not important to the model, I think it fits well. In general, I use nullable types for my properties that can be null and do not enforce anything on the getters, as it is not part of its responsibility, usually. Instead, I use roles to determine what view model to use.
The obvious drawback is that there is more coding required to use the view models, but it comes at the obvious benefit of decoupling presentation and views from the domain. It also will help in unit/integration testing, where you can verify that a certain view model cannot return a type of data.
However, you can use something akin to AutoMapper (depending on what your platform is) to help in populating your view model from your entities.
I made the mistake of posting the question without creating an OpenId so it looks like I'll have to comment here(?).
First of all, thanks for taking you time to answer - It certainly has more to do with how data is presented than how the model works. However, I feel the need to clarify a few things.
The domain model / entities are never referenced directly from the UI. I'm using a variant of the DM-V-VM pattern for UI/business model separation. For lazy loading and repository implementation in general I have entity implementations in a infrastructure layer where things like serialization, dirty tracking and lazy loading is handled.
So the domain layer has entities like:
class Entity {
virtual string SocialSecurityNumber { get; }
}
And the infrastructure layer adds some other functionality to be able to update and restore entites from a server:
class EntityImpl : Entity {
bool isDirty;
bool isLoaded;
// Provide the means to set value on deserialization
override string SocialSecurityNumber;
}
So the lazy loading behavior would be implemented in the infrastructure layer and never seen by the domain layer.
I agree that throwing on getters wouldn't be nice but my concerns are on how an anonymous view model would retrieve the data. As of now, to retrieve a list of entities the viewmodel would hold a reference to a domain repository, should I have two repositories, one for authenticated(and therefore disclosed) entities, and another one for the unauthenticated users - maybe even two different entities?