Does it make sense to ever have a Value Object factory when following DDD practices? - domain-driven-design

Recently I was thinking about some issues I had in the past while attempting to design a particular domain model, lets just say Address, that can be editable with a given context but non-editable within another. My current way of thinking is that I would have both a Value Object version of the Address and an Entity for the Address perhaps attached to something like a customer account in order to derive it's identity.
Now I'm realizing that if I'm ever creating a new Address, such as when one is entered in by the user, that I most likely also need to be able to continue to edit that Address and perhaps edit any preexisting Addresses as well within that same bounded context. For this reason I could assume that within this context Address should be modeled as Entity and not a Value Object. This leads me to my main question which is that if you should always be using entities when modifying an existing set of data or creating a new data then does it ever make sense to have a Factory for creating any Value Object?
The rule that is beginning to emerge for me as I follow this line of thinking is that value objects should only be created to represent things that are either static to the application or things that have already been persisted into the database but not things that are transient within the current domain context. So the only place I should any type of creation of value objects would be when they are re-hydrated/materialized within or on the behalf of aggregate root repositories for persistent values or within a service in the case of static values. This is beginning to seem pretty clear to me however it concerns me that I haven't read anywhere else where somebody is drawing the same conclusions. Either way, I'm hoping that somebody can confirm my conclusions or set me straight.

that can be editable with a given context but non-editable within
another
Differences in mutability settings for an entity within different contexts can also be represented in the application tier. It is an operational concern, possibly involving authentication and authorization and an application service is a convenient location for this logic. The distinction between a VO and an entity does not address these concerns directly. Just because a VO should be immutable, does not mean that an entity cannot change the value of a VO that it references. For instance, a user can reference an immutable address value, however an edit operation can update the user to reference a new value. Allowing a user to edit an address in one context and not in another can be represented as permission values associated with the corresponding context.
This leads me to my main question which is that if you should always
be using entities when modifying an existing set of data or creating a
new data then does it ever make sense to have a Factory for creating
any Value Object?
It can certainly make sense to have a factory for creating VO instances. This can be a static method on the VO class or a dedicated object, depending on your preference. However, a VO should not be used to address mutability requirements of the domain model. Instead, as specified above, this should be handled at the application tier.

Related

Domain Driven Design - How does a reconstitution factory bypass invariants?

I'm having some difficulties figuring out how a reconstitution factory works when paired with DDD.
From what I understand, this factory would be owned by the repository layer (or rather, not the domain) and is simplified, as it expects all entities stored to be valid already.
Where I get confused, is how could a factory that lives in a layer outside the domain, know how to create a domain object while essentially bypassing any invariant checks? I only open specific methods on the aggregate to allow creation/updating of that entity. For example, a Survey has a list of people on it and I expose a method to add a person to the Survey (domain checks to make sure you're not adding 1 person multiple times). I have no other way of adding people to that Survey aggregate.
If it helps, the reason I'm considering this option is because after I send a Survey, I want to differentiate people who have received the Survey and those who haven't when adding them to the Survey aggregate. That way when I send to new people, I know who should receive it vs those who have already received it. I could just allow a nullable time parameter when adding a person, but I felt like that did not adequately communicate intent.
Thanks for reading.
How does a reconstitution factory bypass invariants?
The usual answer for a factory is that it doesn't use the domain methods to initialize the aggregate, but instead copies information into the aggregate via constructors.
In other words, the responsibility of the factory is to construct the object graph, and nothing else. It takes information out your data model, copies it into value objects, initializes entities, and ensures that your new in memory representation is in the same state as when the aggregate was stored.

DDD: Domain Objects Structure

I'm new to DDD and I want to clearly understand each domain object structure and role:
Aggregate Root:
1.1. The only contact point the client can interact with the domain objects, the client should not be able to modify or create new Entities or value objects whiteout the aggregate root? (Yes/No)
1.2. Can an aggregate root contain only value objects ? for example User root, it contain only address, phone, things which are value objects as far as I understand. So is it a sign of bad design when your aggregate root contain only value objects? shall it contain only entities and via entities interact with value objects?
Entities: Shall the entities contain only value objects? or it can also contain other entities? can you give me a simple example please ?
Value Objects: shall I go ahead and encapsulate every primitive type in an value object? I can go deep and make every primitive type as an value object, for example: PhoneNumber can be a string or an value object which contains country code, number. the same thing can be applied to all other primitive type value such as name, email. So where to draw the line ? where to say "Ok I'm going to deep", or going deep is the right way of doing DDD?
Factories: Do I really need them? I can go ahead and write an static method within the domain object which knows more precisely how to construct it, am I doing wrong ?
Sorry for the long questions, but I'm feeling little lost despite of continues reading, if you can help me I would be glad.
I'll try to answer all your questions:
1.1. The only contact point the client can interact with the domain objects, the client should not be able to modify or create new Entities or value objects whiteout the aggregate root? (Yes/No)
Entities live within ARs and allowing the client to create them would violate encapsulation, so for entities you are correct, ARs create their own entities which don't get exposed to the outside (copies/immutable views could be).
On the other hand, value objects are generally immutable and therefore there's no harm in having them supplied to the AR as data inputs.
In general all modifications needs to go through the AR so that the AR is aware of the modification. In special situations the AR could detect modifications within it's cluster by listening to events raised by internal entities when it's impractical to go through the root.
1.2. Can an aggregate root contain only value objects ? for example User root, it contain only address, phone, things which are value objects as far as I understand. So is it a sign of bad design when your aggregate root contain only value objects? shall it contain only entities and via entities interact with value objects?
Favor value objects as much as you can. It's not unusual for all parts of an AR being modeled as values. However, there's no limitation or law stating whether or not an AR should have only values or entities, use the composition that's fit to your use case.
Entities: Shall the entities contain only value objects? or it can also contain other entities? can you give me a simple example please ?
Same answer as above, no limitation nor law.
Value Objects: shall I go ahead and encapsulate every primitive type in an value object? I can go deep and make every primitive type as an value object, for example: PhoneNumber can be a string or an value object which contains country code, number. the same thing can be applied to all other primitive type value such as name, email. So where to draw the line ? where to say "Ok I'm going to deep", or going deep is the right way of doing DDD?
Primitive obsession is worst than value object obsession in my experience. The cost of wrapping a value is quite low in general, so when in doubt I'd model an explicit type. This could save you a lot of refactoring down the road.
Factories: Do I really need them? I can go ahead and write an static method within the domain object which knows more precisely how to construct it, am I doing wrong ?
Static factory methods on ARs are quite common as a mean to be more expressive and follow the UL more closely. For instance, I just modeled as use case today where we had to "start a group audit". Implemented a GroupAudit.start static factory method.
Factory methods on ARs for other ARs are also quite common, such as var post = forum.post(author, content) for instance, where Post is a seperate AR than Forum.
When the process requires some complex collaborators then you may consider a standalone factory though since you may not want clients to know how to provide and setup those collaborators.
I'm new to DDD and I want to clearly understand each domain object structure and role
Your best starting point is "the blue book" (Evans, 2003).
For this question, the two important chapters to review are chapter 5 ("A model expressed in software") and chapter 6 ("the life cycle of a domain object").
ENTITIES and VALUE OBJECTS are two patterns described in chapter 5, which is to say that they are patterns that commonly arise when we are modeling a domain. The TL;DR version: ENTITIES are used to represent relationships in the domain that change over time. VALUE OBJECTS are domain specific data structures.
AGGREGATES and FACTORIES are patterns described in chapter 6, which is to say that they are patterns that commonly arise when we are trying to manage the life cycle of the domain object. It's common that modifications to domain entities may be distributed across multiple sessions, so we need to think about how we store information in the past and reload that information in the future.
The only contact point the client can interact with the domain objects, the client should not be able to modify or create new Entities or value objects whiteout the aggregate root?
Gray area. "Creation patterns are weird." The theory is that you always copy information into the domain model via an aggregate root. But when the aggregate root you need doesn't exist yet, then what? There are a number of different patterns that people use here to create the new root entity from nothing.
That said - we don't expect the application to be directly coupled to the internal design of the aggregate. This is standard "best practice" OO, with the application code coupled to the model's interface without being coupled to the model's implementation/data structure.
Can an aggregate root contain only value objects ?
The definition of the root entity in the aggregate may include references to other entities in the same aggregate. Evans explicitly refers to "entities other than the root"; in order to share information with an entity other than the root, there must be some way to traverse references from the root to these non-root entities.
Shall the entities contain only value objects?
The definition of an entity may include references to other entities (including the root entity) in the same aggregate.
shall I go ahead and encapsulate every primitive type in an value object?
"It depends" - in a language like java, value objects are an affordance that make it easy for the compiler to give you early feed back about certain kinds of mistakes.
This is especially true if you have validation concerns. We'd like to validate (or parse) information once, rather than repeating the same check every where (duplication), and having validated vs unvalidated data be detectably different reduces the risk that unvalidated data leaks into code paths where it is not handled correctly.
Having a value object also reduces the number of places that need to change if you decide the underlying data structure needs improvement, and the value object gives you an easily guessed place to put functions/methods relating to that value.
Factories: Do I really need them?
Yes, and...
I can go ahead and write an static method within the domain object
... that's fine. Basic idea: if creating a domain object from so sufficient set of information is complicated, we want that complexity in one place, which can be invoked where we need it. That doesn't necessarily mean we need a NOUN. A function is fine.
And, of course, if your domain objects are not complicated, then "just" use the objects constructor/initializer.

Updating a value object from the aggregate in one-to-many relationship

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.

DDD: Who is responsible for the creation of value object and entity?

In domain driven design, client talk to aggregate root directly to implement the business logic, aggregate root could be created by factory or loaded from repository. In order to implement the business logic, we have to create a new value object in some cases, so my question is:
Should aggregate responsible to the creation of value object, meaning that we encapsulate the creation of value object in aggregate root.
Can I create value object directly in application service without aggregate?
Can I create value object directly in application service without aggregate?
Sure, go right ahead. That's a pretty common pattern - for example, in a client/server architecture, the client will send a message to the application inviting some action (command/query) on the domain model. That message will be designed to cross process boundaries - in other words, it's a data transfer object. The application component will take that message, and re-express it as value objects that will be understood by the domain.
Example: a query of the domain might ask for details of some Account, which is identified by a UUID. So the initial DTO might be a string. Application layer throws that string into a JSON parser, then finds the account id argument (which is "just data"), and use it to create an AccountId value object (which the domain will recognize).
Part of the point of value objects is that equal objects freely substitute for one another. Nobody cares which 7 you have.
we encapsulate the creation of value object in aggregate root.
Your aggregate code is likely to create value objects too. Changes to your aggregate's state will often require creating/computing new values. Nothing wrong with that.

Can an aggregate be part of a domain-event?

Consider an aggregate with many properties. For example UserGroup. If I want to publish a UserGroupCreatedEvent I can do 2 things:
duplicate the properties from the just created UserGroup to
UserGroupCreatedEvent and copy their values. OR:
Refer to the new UserGroup within the UserGroupCreatedEvent
In many examples, like Axon's Contacts App, I've seen property duplication. I wonder why, and if in real-world CQRS applications, this is not a lot of overhead, and developers choose to refer the aggregate instead.
An event is a DTO and it's meant to cross boundaries. Including the aggregate directly has the following problems:
The aggregate is a concept that makes sense only in its own bounded context;
An event should contain only the relevant changes, not the whole state of the concept;
Because an event is a DTO, at one point it will be (de)serialized and that would be a technical problem with properly encapsulated objects;
Every component/context receiving handling the event would have a dependency of the component where the aggregate is defined;
These are the main reasons why a Domain Event should be just a flattened representation of the relevant state changes.
P.S: If you need to include the whole state in your event, maybe the events is improperly designed or you're dealing with a simple data structure. Usually an aggregate contains some value objects and/or encapsulates some business constraints.
An important property of domain events is that they are immutable. Bearing that in mind, the two possibilities you mention differ greatly:
Duplicating properties records their value at the time the UserGroup was created.
Referencing the UserGroup by ID just tells you that a UserGroup was created, but not the properties it had at the time. If the UserGroup has been deleted in the meantime, this means that the information is lost.
Which properties you copy depends on just that difference. Do you need to be able to look up e.g. the name of a UserGroup at its creation time? Add it as a property. If not (and if it's not expected that it ever will be required), don't.
Also, domain events have a global scope (i.e. they are meaningful outside of your BC), so you should include all information that clients outside of your BC need to make sense of the domain event.
Note that attaching the whole aggregate root object to a domain event violates the immutability rule of domain events, so this is most probably a bad idea.

Resources