DDD - Problems in constructor and methods in entities design - domain-driven-design

I have a problem with regards to entity design. As I've read, when you design a DDD entity, the constructor should contain the values needed for an entity to "exist". For example, in the domain I am working on, a Class entity cannot exist without a Section and a Level:
public class Class
{
public Class(short id, string section, Level level)
{
ID = id;
Section = section;
Level = level;
}
//
// Properties
//
public short ID { get; private set; }
public string Section { get; private set; }
public Level Level { get; private set; }
//
// Methods
//
public static IList<Class> GetClassesByTeacher(short teacherID)
{
List<Class> classes = new List<Class>();
classes.Add(new Class(1, "a", null));
classes.Add(new Class(2, "b", null));
classes.Add(new Class(3, "c", null));
return classes;
}
}
Here Level is also an entity. As I am not yet finished in the design, Level's contructor might also contain an entity SchoolYear. What bothers me is for me to call GetClassesByTeacher method, I need to instantiate a Class along with other entities (Level, and also SchoolYear, needed in Level's constructor).
Is this the correct? I think it's bothersome when I just want to call the method. Are there other ways? I considered making it static but others said testability would suffer. I'm not sure if CQRS is one of the solution for what I want to do as I haven't yet read too much about it, but if it is, are there any other techniques aside from CQRS I can employ, or is it when going DDD, this is how it really is? Or is my entity design incorrect?

You should reconsider you domain model, as you actually say it seems there something wrong.
I may refer to Single Responsibility Principle (SRP) in which any class should have one one reason to change. In your example, what happens if we added a new field to 'Class', we will modify 'Class' it self and is right, but what happens if we decide that the listing should be on reversal order, or if you need a new type of list taking into account only interim teachers... you should change 'Class' but 'Class' has nothing to do with listings.
To answer you question, you might take a look at Repository pattern. Repositories are where you could ask for these type of listings.
I might split Class into two:
one for 'Class' model
other for 'Class' repositories
In summary:
public class Class
{
public Class(short id, string section, Level level)
{
ID = id;
Section = section;
Level = level;
}
//
// Properties
//
public short ID { get; private set; }
public string Section { get; private set; }
public Level Level { get; private set; }
}
public class ClassRepository
{
private IList<Class> contents;
//
// Methods
//
public IList<Class> GetClassesByTeacher(short teacherID)
{
List<Class> classes = new List<Class>();
for (Class elem: contents) {
if (elem.getTeacher().equals(teacherID) {
classes.Add(elem);
}
}
return classes;
}
}
repository = new ClassRepository;
level1 = new Level();
repository.Save(new Class(1, "a", level1));
repository.Save(new Class(2, "b", level1));
repository.Save(new Class(3, "c", level1));
result = repository.GetClassesByTeacher(1);
There are other details like using a ClassRepositoryInterface and implement with an InMemoryClassRepository, you will miss also Teacher information in class, as long as one one teacher drives the class, if not you might change how to filter by teacher, etc, etc.
I'm not a Java developer and the code will not compile but I expect you get the idea.

The GetClassesByTeacher method does indeed belong in some kind of repository or service class. Your Class entity is meant to represent an instance of that thing in the real world. An entity is not meant to provide instances (say, from some underlying persistence) - they are only meant to represent them. A ClassRepository would be a way to provide instances of the Class entity into your domain.
You also mentioned that Class cannot exist without a Level. You are speaking about aggregates here. There is a lot of DDD material online with regards to designing aggregates. Here are a couple:
DDD: Aggregates and Aggregate Roots
DDD: The Aggregate And Aggregate Root Explained
EDIT:
When an entity needs another entity to exist, should it always be an
aggregate?
No, just because entity A depends on entity B's existence, it doesn't mean that entity A needs to belong to entity B's aggregate.
As now I have a model in which many entities (like Class, Level,
Subject, Adviser, Teacher, etc.) exists only in a certain SchoolYear
(an entity). Is it OK for an aggregate to get that large?
An aggregate this large could result in performance and consistency issues.
Why performance? You could be loading a huge graph of data in memory for some aggregate root. You most likely only need to work on a fraction of that aggregate for whatever unit of work is occurring and not all the entities involved.
What consistency issues? The larger the aggregate, the more likely data can be changed in another part of the system while it has been retrieved into memory. When saving, data loss can occur.
Vaughn Vernon covers exactly these problems in his three-part Effective Aggregate Design series. It's a bit daunting if you aren't familiar with DDD lingo, but I highly recommend this read!
Also, by what you said, the Entity should not use the repository. If
some business logic in the Entity needs database access for it to be
processed, should it directly use DAL?
Entities should not know anything about repositories or services (or anything else, for that matter). They should not have any dependency on any other 'layer' in the system. Everything can know about your entities, but your entities shouldn't know about anything else. Provide me with an example of why you would want an entity to call on a repository and maybe I can provide a better answer.

Related

How to design, Order and State in DDD?

Supose I have an order and it can be in an state.
Order it would be the root entity, and State another root entity in the same bundary context than the order.
I was thinking that State it should be an entity too because it would be in this way:
State
{
long Id,
string State;
bool AllowModifyOrder;
bool AllowAceptorder;
//another properties that define what is possible to do in the state.
}
So I think it is needed that the State it is another entity, not a value object. But I am not sure if this it would be the best option.
Another doubt that I have is that the order need a property to point to the state, but not to the class, but to the ID, because I have read that an entity it is better to use the ID instead of the object, to avoid try to access or modify a root entity from another. But in this case, when I need some data of the state, for example if it can be accepted or if it can be modify. How could I do that if I only have the ID of the state?
Thanks.
Your State has to be a property of an Order because your Ubiquitous Language says "An Order can be in a state". You are tieing yourself too closely to the Database Model. That's why you have Id's and properties that look like Columns in your class.
If an Order has a State and there's a finite amount of States, then your State can be modeled as an Enum. Take this C# code for an example:
public Enum OrderState {
Draft,
Open,
Closed
}
public class Order {
OrderState State { get; private set; }
}
Your Repositories and Factories will take care of translating what you have in your Database and Inputs into Domain Classes like Order.

Question about aggregate examples from red book

In the red book (Implementing Domain-Driven Design) Vernon Vaughn shows an aggregate example for a Scrum Core Domain. Unfortunately the code samples are just fragments.
For the second attempt the model is split in multiple aggregates instead of using a single large aggregate. As a result the method contract for the planBacklogItem method changes from
public class Product ... {
...
public void planBacklogItem(
String aSummary, String aCategory,
BacklogItemType aType, StoryPoints aStoryPoints) {
...
}
...
}
to
public class Product ... {
...
public BacklogItem planBacklogItem(
String aSummary, String aCategory,
BacklogItemType aType, StoryPoints aStoryPoints) {
...
}
}
The application service looks then like this:
public class ProductBacklogItemService ... {
...
#Transactional
public void planProductBacklogItem(
String aTenantId, String aProductId,
String aSummary, String aCategory,
String aBacklogItemType, String aStoryPoints) {
Product product =
productRepository.productOfId(
new TenantId(aTenantId),
new ProductId(aProductId));
BacklogItem plannedBacklogItem =
product.planBacklogItem(
aSummary,
aCategory,
BacklogItemType.valueOf(aBacklogItemType),
StoryPoints.valueOf(aStoryPoints));
backlogItemRepository.add(plannedBacklogItem);
}
...
}
I understand the idea of aggregates and the sample code, but I wonder why planBacklogItem is not declared as static in the multiple aggregate version. The method does not access any instance data. Separate aggregates were used to achieve better concurrent access. Therefore I don't understand why the application service first pulls a full product from the repository, while none of its data is needed.
Since the BacklogItem uses Ids it can be created without reading the product from the repository. In case the product aggregate has lots of data and child aggregates are accessed frequently, the implementation can cause performance issues.
The only explanation I could come up with is that it should ensure the existence of the product. But why would you not use a method like productRepository.existsProduct(productId) instead?
I'm working with C# and don't understand all the magic of #Transactional. Vaughn did not say anything about the isolation level. Race conditions between reading the product and writing the BacklogItem could occur. Does #Transactional create a serializable transaction? I doubt it since not all storages support it. If the isolation level of the transaction is not serialized or the product is not locked during read it could be deleted before the BackLogItem was written. (It might not be a business case for the scrum examples, but it is a general concern).
I'm afraid that I miss something major. Thanks for any help.
The method does not access any instance data.
Not sure if the book examples are incorrect, but it does use instance data on GitHub samples.
public BacklogItem planBacklogItem(
BacklogItemId aNewBacklogItemId,
String aSummary,
String aCategory,
BacklogItemType aType,
StoryPoints aStoryPoints) {
BacklogItem backlogItem =
new BacklogItem(
this.tenantId(), // <--
this.productId(), // <--
aNewBacklogItemId,
If the isolation level of the transaction is not serialized or the product is not locked during read it could be deleted before the BackLogItem was written.
Indeed, there could be a race condition (assuming we can remove products). TBH I don't know LevelDB enough and didint' dug into the actual implementation details, but a traditionnal foreing key constraint could prevent orphans in a relationnal DB.
However, that wouldn't really work for logical deletes (e.g. archiving) so in these cases I guess there's those choices:
Ignore the problem. Perhaps it doesn't actually matter that a backlog item gets planned a millisecond after a product has been archived? Race Conditions Don't exist?
Lock the Product AR. That could be done in numerous ways, such as forcing an optimistic locking version bump.
Apply an eventually consistent compensating action, such as unplanning a planned backlog item.

Immutability in aggregate child entities

I have begun using domain driven design principles but are currently stuck with a specific problem.
I have an Aggregate which has multiple layers of nested child entities as shown below:
public class Aggregate: Entity<AggregateId>, IAggregateRoot {
private readonly List<ChildOne> childOnes;
}
public class ChildOne: Entity<ChildOneId> {
public string ChildOneValue1;
public string ChildOneValue2;
public string ChildOneValue3;
private readonly List<ChildTwo> childTwos;
}
public class ChildTwo: Entity<ChildTwoId> {
public string ChildTwoValue1;
public string ChildTwoValue2;
public string ChildTwoValue3;
}
In a domain service I need to access all values of ChildOne and ChildTwo including their ids.
public interface IDomainService {
public IEnumerable<INotification> Analyze(Aggregate aggregate);
}
However, I cannot return the entities as they are since this would violate the immutability principle.
This got me thinking that my domain model probably might not be optimal, but I cannot see how this can be different since the nested entities never can exist without the respective parent.
Another approach could be to have a single value object which holds all values of a given entity and then return this value object instead of the entity. But then a deep mapping needs to be performed since the domain service needs access to the values of all nested entities.
Any suggestions on to how to approach this?
Any suggestions on to how to approach this?
There are a couple of possibilities.
One is to invert your proposed API - design the domain service to accept immutable values as arguments, and then pass the instance of that service to the Aggregate, rather than the other way around.
public interface IDomainService {
public IEnumerable<INotification> Analyze(IEnumerable<DomainValue> values);
}
If you recall the Visitor pattern from the Gang of Four book, it is a very similar idea.
In some cases, an in-memory state machine might be a reasonable alternative to a stateless domain service. In that case, the API might look like
public interface IDomainService {
public void OnAnalyze(DomainValue value);
public IEnumerable<INotification> Notifications();
}
Another possibility is to design the Aggregate to act as a Collection
public class Aggregate {
// ...
public IEnumerable<DomainValue> YourCleverNameHere();
}
For use cases where you are not changing the state of the Aggregate, just leave the aggregate out of it, and work directly with an immutable in memory representation of the current state.
However, I cannot return the entities as they are since this would violate the immutability principle.
The entites don't need to be immutable. It's only value object that are immutable in tactical design of domain driven design.
As far as entities are aggregates are concerned, you should be able to get/save an aggregate from the repository only using the aggregate root. You should not be able to get/save an entity that is not an aggregate root.

Domain-Driven Design: how to model nested product category hierarchy? Even worse, what if the product category is an Aggregate Root?

I am practicing Domain-Driven Design so why not build a demo product catalog project? Apparently Product is the Core Domain here, but since I like to make the project more interesting, I would love to support nested Category hierarchy. In other words, a Category could have many child Category.
Moreover, I would want to separate Category from Product domain and make it its own Supporting Domain.
Question: Marking Category as AggregateRoot doesn't sound right to me. A Category could have many child Category, which are also AggregateRoots?!! How can I go about modeling this? Nested product category is pretty common in E-Commerce real life situation.
namespace DL.Demo.Domain.Shared
public abstract class ValueObjectBase<T> : IEquatable<T>
where T : ValueObjectBase<T>
{
public abstract bool Equals(T other);
public abstract override bool Equals(object obj);
public abstract override int GetHashCode();
}
public abstract class EntityBase : IEquatable<EntityBase>
{
public Guid Id { get; private set; }
protected EntityBase()
{
this.Id = Guid.NewGuid();
}
// Some Object overrides
}
And I actually have AggregateRoot inherents from Entity because I guess only an Entity could be an AggregateRoot?
public abstract class AggregateRoot : EntityBase
{
}
namespace DL.Demo.Domain.Catalog
public class Category : AggregateRoot
{
public string Name { get; private set; }
public Guid? ParentCategoryId { get; private set; }
public CategoryStatus CategoryStatus { get; private set; }
}
Having a nested list of AggregateRoot just doesn't sound right to me. If you don't mark the Category as the AggregateRoot, how would you go about modeling this?
I am new to DDD and all other related cool stuff like Domain Events, Event Sourcing, etc. I will be appreciated if somebody who had experience can tell me if I am going to the right way.
I am new to DDD and all other related cool stuff like Domain Events, Event Sourcing, etc. I will be appreciated if somebody who had experience can tell me if I am going to the right way.
You are on the right way.
Category should be an Aggregate root, with a reference to parent category by it's ID and this is very good.
Nested categories are a good candidate for event-sourcing, even if there are no special invariants to protect because of the different modes that this hierarchy could be projected in the Read models. You are not limited in any way on that representation, although the Aggregate is straight-forward. In every used Read model you could implement them differently as:
Model Tree Structures with Parent References
Model Tree Structures with Child References
Model Tree Structures with an Array of Ancestors
Model Tree Structures with Materialized Paths
Model Tree Structures with Nested Sets
See more here about implementing tree structures (this link points to MongoDB but that is not relevant).
The Category Aggregate just emits simple events as ACategoryWasCreated, ACategoryHasMovedToOtherParent and so on and the Read models just adapt to reflect those events.
I've implemented a tree structure like this and the queries on the read-side (the query side) are very very fast. You could select the products in a category and all child categories with no joins. Or you could build a category path, again, with no joins.
The key to defining an aggregate is to define first a transactional boundary. Outside of an aggregate boundary consistency is eventual - achieved by reacting to the domain events emitted by an aggregate.
Aggregate can hold another aggregate ID (Value Object) as a reference, however, is not responsible to be transactionally consistent with another aggregate.
So, the main question - Is your tree transactionally consistent? If yes, linked list won't scale well. You have to model it differently.
Modeling is context specific and is not cookie-cutter exercise. Maybe your category is just a value object that could be modeled as a path. Hard to say without broader context.
If you want to have a category tree, then the tree itself should probably be your aggregate root (I see you were coming to this conclusion on your own in the comments already). And this would have functions to add or remove children and so on.
And yes, with very large trees you could probably gain a lot of performance in having a read-only projection of your tree in for instance json format (stored in MongoDb, cache, file or whatever). Especially considering how such a category tree is typically updated only a tiny fraction of how often it is read, you could also easily get away with always just maintaining that json and foregoing a normalised database table tree altogether.

DDD and Factories

Hi I have a few questions regarding Domain Driven Design and using Factories / Factory Methods.
Per the Domain Driven Design Blue Book (Eric EVan's Book) it states that complex constructors should be encapsulated inside Factories / Factory Methods / Builders so there is a consistent place where you check all the invariants, so my question is regarding this:
Let's say I am developing a magic organizer application where you can make CRUD like operations on magic effects (like a post on a blog + several attributes like effect duration, materials used (list of strings), patter associated with the magic effect) and some of the invariants are that a magic effect must always have a title, a content of the magic effect, a duration and an optional patter and must be published by a user registered in the application.
So since I have quite a few invariants I have a EffectBuilder that builds MagicEffect objects and checks all the invariants.
Is it ok to do something like this in the user class?
public class User {
// Several attributes and business methods
public MagicEffect publishEffect(final String title, final String content, final Long duration, final Collection<String> elements) [
EffectBuilder builder = new EffectBuilder();
builder.withAuthor(this);
builder.withTitle(title);
builder.withContent(content);
builder.withDuration(duration);
builder.withElements(elements);
return builder.build();
}
};
Or should I do something like:
public class User {
// Several attributes and business methods
public EffectBuilder publishEffect() [
EffectBuilder builder = new EffectBuilder();
builder.withAuthor(this);
return builder;
}
};
And somewhere else
User user = userRepository.findById(userId);
MagicEffect effect = user.publishEffect().withTitle(title).withContent(content).withDuration(duration).withElements(elements).build();
userRepository.save(user);
I mean the first example I have a huge method with huge amount of parameters but I make sure all the invariants are set in the effect when it's built, in the other scenario I programatically improve the code readability by having a fluent interface but I canot make sure the invariants are met 100% of the time.
Which is the better approach? Is there a more balanced approach of doing it?
Thanks
Pablo
I think that your second approach is better. The whole point of Builder is to avoid large list of parameters like you have in your first example. Builder is not responsible for enforcing invariants in the object that it builds. Object itself enforces them. I think it is perfectly fine to have an instance of EffectBuilder without Title or with a default title. As long as the MagicEffect itself enforces 'Every effect should have a title' invariant.

Resources