a) I'm a bit puzzled whether in most cases we should only have a factory that produces the entire Aggregate or should we also have a factory that creates only the Aggregate root?
b) Should a factory that builds the entire Aggregate build both root and non-root objects by itself or should it delegate the building of non-root entities/VOs to other factories?
Thus, if Aggregate contains 5 different types of non-root entities, should Aggregate factory create these non-root entities by itself or should we have additional five factories ( one factory for each non-root entity ), to which Aggregate factory would delegate the creation of particular type of non-root entity?
Thank you
In Eric Evans' DDD book, page 138, it's written in bold:
Create entire aggregates as a piece, enforcing their invariants.
Then in the next page:
A FACTORY should only be able to produce an object in a consistent
state. For an ENTITY, this means the creation of the entire AGGREGATE
[...]
Concretely, this means that you would only have one factory to create the entire aggregate. There may be other classes (factories) involved in building your non-root entities or value objects, but there is only one factory responsible for creating an aggregate. This factory creates a full aggregate, not just a root object.
The creation of sub-root objects (for example, an OrderItem for an Order) is handled by the root entity itself, so it can enforce variants in a manner invisible to the outside world.
So a typical flow could be:
var newOrder = orderFactory.CreateOrder(customer);
newOrder.AddOrderItem(product, quantity);
A factory might be used within the entity, but it shouldn't be accessed by the outside world.
public class Order
{
private OrderItemFactory _orderItemFactory;
public AddOrderItem(Product product, int Quantity)
{
var newOrderItem = _orderItemFactory.CreateOrderItem(product, quantity);
}
}`
Related
I was wondering whether it would be considered bad practice to use an aggregate identifier across a service in another (extensipn) aggregate which shares that they are both revolving about the same identifiable entity.
The problem I am currently having is that we want to split some logic (bounded context if you so will) into a different service as the one originally creating the aggregate.
In general, this seems to work, as when I send a Command within the second service, it is picked up and updates its state. As I can use EventSourcingHandler to also use Events created in the other service to manipulate its state, I get state information from a source applied by the first services aggregate.
I was worried that the snapshot mechanism would work against me, but apparently it is smart enough to store snapshots separately as long as I make sure the aggregate "type" name is not the same.
So far, so good, the only thing that's a smell for me is that the second aggregate does not have (needs) an initial constructor CommandHandler, as the creation is done in the first aggregate.
So, am I going against the way axon framework intends aggregates to be used, or is this a viable use case?
#Aggregate
#Getter
#NoArgsConstructor
public class Foo {
#AggregateIdentifier
private String fooIdentifier;
#CommandHandler
public Foo(CreateFooCommand command) {
apply(FooCreatedEvent.builder()
.fooIdentifier(command.getFooIdentifier())
.build());
}
#EventSourcingHandler
public void on(FooCreatedEvent event) {
this.fooIdentifier = event.getFooIdentifier();
}
}
#Aggregate
#Getter
#NoArgsConstructor
public class Bar {
#AggregateIdentifier
private String fooIdentifier;
private String barProperty;
#CommandHandler
public void on(UpdateBarCommand command) {
apply(BarUpdatedEvent.builder()
.fooIdentifier(this.fooIdentifier)
.barProperty(command.getBarProperty())
.build());
}
#EventSourcingHandler
public void on(FooCreatedEvent event) {
this.fooIdentifier = event.getFooIdentifier();
}
#EventSourcingHandler
public void on(BarUpdatedEvent event) {
this.barProperty = event.getBarProperty();
}
}
The case for why I tried to split is that we wanted to separate the base logic (creation of the aggregate, in this case a vehicle) from the logic that happens and is handled in a different bounded context and separate microservice (transfers from and to a construction site). Since I cannot publish a creation event (CommandHandler in the constructor, sequence 0) for the same aggregate identifier but different aggregate type twice, I could not separate the two states completely.
So my only options right now would be what I presented above, or use the creation of the second aggregate to set a different aggregateId, but also add internally the aggregateId of the first aggregate to allow for events to be published with the aggregateId information of the first as a reference Id. To make this work I would have to keep a projection to map back and forth between the two identifiers, which also does not look too good.
Thanks in advance,
Lars Karschen
Very interesting solution you've come up with Lars. Cannot say I have ever split the Aggregate logic in such a manor that one service creates it and another loads the same events to recreate that state in it's own form.
So, am I going against the way axon framework intends aggregates to be used, or is this a viable use case?
To be honest, I don't think this would be the intended usage. Not so much because of Axon, but more because of the term Bounded Context you are using. Between contexts, you should share very consciously, as terms (the ubiquitous language) differs per context. Your events are essentially part of that languages, so sharing the entirety of an aggregate's stream with another service would not be something I'd suggest normally.
Whether these services you are talking about truly belong to distinct Bounded Contexts is not something I can deduce right now, as I am not your domain expert. If they do belong to the same context, sharing the events is perfectly fine. Then still I wouldn't recreate a different aggregate based on the same events. So, let me add another concept which might help.
What I take from your description, is that you have something called a Vehicle aggregate which transitions different states. Wouldn't a Polymorphic Aggregate be the solution you are looking for? That way you can have a parent Vehicle aggregate with all the basics, and more specific implementations when necessary? Still, this might not fit your solution completely, something I am uncertain about given your description.
So, I am going to add a third pointer which I think is valuable to highlight:
Since I cannot publish a creation event (CommandHandler in the constructor, sequence 0) for the same aggregate identifier but different aggregate type twice, I could not separate the two states completely.
This line suggests you want to reuse the Aggregate Identifier between different Aggregates, something which comes back in the question's title too. As you've noted, [aggregate identifier , sequence number] pairs need to be unique. Hence, reusing an aggregate identifier for a different type of aggregate is not an option. Know however that Axon will use the toString method of your aggregate identifier class to fill in the aggregate identifier field. If you would thus adjust the toString() method to include the aggregate type, you'd be able to keep the uniqueness requirement and still reuse your aggregate identifier.
For example, the toString method of a VehicleId class containing a UUID would normally output this:
684ec9f4-b9f8-11ea-b3de-0242ac130004
But if you change the toString to include the aggregate type, you would get this:
VehichleId[684ec9f4-b9f8-11ea-b3de-0242ac130004]
Concluding, I think there are three main points I'd like to share:
Axon Framework did not intent to reuse Aggregate Streams to recreate distinct Aggregate types.
Polymoprhic Aggregates might be a means to resolve the scenario you have.
The [aggregateId, seqNo] uniqueness requirement can reuse an aggregateId as long is the toString method would append/prepend the aggregate type to the result.
I hope this helps you on your journey Lars. Please let me know of you feel something is missing or if I didn't grasp your question correctly.
If you have an entity with a value object as an attribute.
Which would be the parameters of the entity constructor, the value object? Or the primitive types of the value object?
First I did it building the value object outside the entity and I passed the value object to the entity constructor... but then I realized that maybe it would be the entity itself that has to build the value object.
I thought this because the entity and the value object are in fact an aggregate, and it is supposed that you have to access the inside of an aggregate through the aggregate root, i.e., through the entity.
So which is the right way? Is it allowed to deal with the value object outside the entity? Or the value object just can be used by the entity?
Thank you.
EDIT:
For example, I have an entity "Task" that is the aggregate root. This entity has a value object "DeliveryDate" (in format "dd/mm/yyyy hh:mm"). The entity has more value objects too.
class DeliveryDate extends ValueObject {
private String formattedDeliveryDate;
private DeliveryDate() {
super();
}
DeliveryDate ( String formattedDeliveryDate ) {
this();
this.setFormattedDeliveryDate ( formattedDeliveryDate );
}
private void setFormattedDeliveryDate ( String formattedDeliveryDate ) {
<< check that the string parameter "formattedDeliveryDate" is a valid date in format "dd/mm/yyyy hh:mm" >>
this.formattedDeliveryDate = formattedDeliveryDate;
}
........
The entity constructor:
Task ( TaskId taskId, Title title, Delivery deliveryDate, EmployeesList employeesList ) {
this();
this.setTaskId(taskId);
this.setTitle(title);
this.setDeliveryDate(deliveryDate);
this.setEmployeesList(employeesList);
}
My doubt is: Is this ok? (passing to the constructor the DeliveryDate object)
Or should I pass the string? (and the constructor creates the DeliveryDate object)
I think it's more a question of "should the outside of the aggregate know about the DeliveryDate concept?"
In general my doubt is about any value object of any entity, not just Task and DeliveryDate (this is just an example).
I have asked the question about the constructor, but it's valid for factories too (if the process of creating an instance is complicated)... should the aggregate factory parameter be the value object? or the primitives to create the value object?
In your case it might seem that the two solutions are similar. It doesn't really matter if you create the value object outside or inside of the entity. But think about when your entity will have more than one value object, the entity constructor will contain too much logic in order to make sure it creates the VOs correctly and at the same time enforce the entity's invariants.
One solution to avoid this unnecessary complexity is to use factories. The factory will abstract the creation process and this will keep you entity code simple.
In DDD, factories are very useful for creating aggregates. In the blue book there is a whole chapter about factories and here is good article about the use of factories in DDD http://culttt.com/2014/12/24/factories-domain-driven-design/
Edit
My doubt is: Is this ok? (passing to the constructor the DeliveryDate object) Or should I pass the string? (and the constructor creates the DeliveryDate object)
Yes, it is ok. Task should not know about how to create the value objects. You should not pass the strings cause that will add more complexity and responsibilities to the Task constructor.
I think it's more a question of "should the outside of the aggregate know about the DeliveryDate concept?"
Yes, it is not problems that the outside of the aggregate knows about the DeliveryDate. It is the same as knowing about strings and integer. Value objects are simple to deal with and reason about and they are part of the domain so I think there is no problems in dealing with them outside of the aggregate.
should the aggregate factory parameter be the value object? or the primitives to create the value object?
Here I would say the Factory should receive the primitive types and encapsulate the objects creation. cause if you pass the values objects to the factory it will just pass the same parameters to the Entity constructor and that is a middleman code smell.
Domain Driven Design doesn't offer any specific guidance here.
A common case might look something like this: we've retrieved a DTO from the database, and now want to create a Entity from it....
class Entity {
private Value v;
Entity (Value v) {
if (null == v) throw new IllegalArgumentException();
this.v = f;
}
Entity (DTO dto) {
this(new Value(dto));
}
// ...
}
Does it really matter if you invoke the second constructor rather than the first? Not much.
A language check:
DTOs are not retrieved from database. What you retreive from a database is an aggregate, not a DTO
I had to abandon that idea - that definition leads to too many problems.
For example, in event sourced designs, the database typically stores representations of events, not aggregates.
Even in traditional designs, it doesn't hold up -- the boundaries of your aggregates are defined by the constraints enforced by the domain model. Once you take the data out of the domain model, what you have left is just representations of state. Expressed another way, we save state in the database, but not behaviors, and not constraints -- you can't derive the constraints from the saved data, because you can't see the boundaries.
It's the model, not the database, that decides which data needs to be kept internally consistent.
I tend to use the term DTO because that's its role: to carry data between processes -- in this particular instance, between the data base and the domain model. If you wanted to use message or document instead, I wouldn't quibble.
Should DDD Repository always return aggregate and all it's value objects and entities?
For an example, I have Invoice object which has it's type and items.
Invoice
--Id
--Issuer
--InvoiceType
--Items
Data are persisted in 4 SQL Tables.
Invoices (FK to invoice type, FK to issuers),
InvoiceTypes
Items(fk to Invoice)
Issuers
If a repository should always return aggregates in it's full state, is it a bit of overkill to include InvoiceType and Items if i need to fetch 50 invoices, and display only ID and IssuerName.
Example for
InvoiceRepository
{
//should this also fetch InvoiceTypes and items from SQL, or i need separate invoice model for this
public List<Invoice> FetchForListing(int page, int take);
}
Should DDD Repository always return aggregate and all it's value objects and entities?
No. In use cases where you are going to be performing a write, you should load everything, because you need the full internal state to ensure that your change satisfies the invariant.
But if you are only going to perform a read, the full state isn't necessary at all -- it's reasonable to limit to the data you pull out.
(For example: when using the cqrs pattern, reads tend to not touch the aggregate at all, but instead copy data from "projections" of aggregate state into a more suitable representation.)
InvoiceRepository
{
// should this also fetch InvoiceTypes and items from SQL,
// or i need separate invoice model for this
public List<Invoice> FetchForListing(int page, int take);
}
So in this case, you wouldn't return a List<Invoice>, since that isn't what you want, and you might not use the same interface to represent the repository
InvoiceSummaryRepository
{
public List<InvoiceSummary> readSummary(int page, int take);
}
Check in your own ubiquitous language to figure out what InvoiceSummary is actually called, to determine whether List<InvoiceSummary> is actually a thing with a name of its own (likely is you are using it to build the representation of a resource in your REST api), and so on.
Domain-driven design suggest that we should create an aggregate root by using a factory to hide the complexity. We can use the following ways to create the aggregate root:
Static factory method in a factory class
Aggregate root that has a factory method
On What basis do we make a selection between (1) and (2)?
Consider having a factory method on the on the AR when the resulting code aligns better with your ubiquitous language and when the AR has some knowledge that will simplify the creation process.
For instance, if in your domain you can add tasks to a project and tasks are modeled as ARs then Task task = project.addTask(taskId, taskName); is more expressive and simple than Task task = new Task(taskId, taskName, projectId);.
Factories are not exactly specific to DDD. You can find the Factory pattern in GoF, for example.
Usually, you make your choice based on the following:
If your factory returns different types, depending on the arguments, it should be placed in a class
If your factory always returns an instance of one class, it should be made as a static method inside this class
When it comes to DDD, you normally would have factory methods on your aggregate roots anyway, to encapsulate the complex creation logic, if you have such logic of course. Factories are named according your Ubiquitous Language and ensure that only consistent aggregates can be created.
Your first suggestion
Static factory method in a factory class
is something you should generally avoid. Public static methods are a code smell if they have service character (which factories do). It's better to create a non-static class, inject it wherever it is used and call the instance method on it. Create an interface if necessary. This approach improves testability and makes dependencies between classes explicit.
If you follow this advice, your question becomes a question of factory method pattern vs abstract factory pattern.
Factory Method
Use factory methods when there are multiple ways to construct an object of a certain class. Factory methods are preferable to direct constructor calls in this case because you can give them a descriptive name. If you use them, it usually makes sense to make the constructor private, so that clients realize that they should not call the constructor, but call the appropriate factory method.
Factory methods just wrap the constructor. As a consequence, they cannot really simplify the construction of an object (apart from giving it a name).
Abstract Factory
If constructing an object is non-trivial, the pattern of choice is the abstract factory pattern. Note that you are not required to have multiple classes to be able to use an abstract factory as suggested by Alexey Zimarev. An abstract factory makes perfect sense with just one type of object that is being created.
Abstract factories are a special kind of a service, namely a service that creates objects. As such, they can have dependencies, which they can provide to the created objects for example.
Example: Let's say you want to create an object that needs a string value and a dependency to ISomeService. Here, an abstract factory can help by providing ISomeService. The interface of the factory would then look like this:
interface IFooFactory {
IBar CreateBar(string value);
}
This factory simplifies creation of an IBar for clients, because they don't have to provide the ISomeService themselves.
In the context of DDD Aggregates
Aggregates often contain references to domain services. As such, instantiation of aggregates is often non-trivial, so the abstract factory pattern is a good fit here.
They are basically the same. Option 1. might help you avoid having a bloated entity class. Option 2. is better if the creation reads more naturally when prefixing by the name of the entity, as in
LoyaltyCard.ForCustomer(...)
SavedSearch.WithCriteria(...)
All material on DDD specify this as a strict no no, but i recently came across a scenario that makes a compelling case for thinking otherwise. Imagine 2 aggregate roots Template and Document where Template --> (1:n) TemplateParam, Document --> (1:n) ParamValue and finally the 2 roots have a reference Document --> (n:1) Template.
Given aggregate root constraint ParamValue should not persist a reference to TemplateParam, only it can refer it through a transient reference obtained through Template aggregate root. Now if i want to have a rule enforce like "each ParamValue of document should refer to a valid TemplateParam belonging to the Template referred to by its owning document". Ideally at db level i would let ParamValue have FK to the TemplateValue, how to do it in DDD paradigm ??
Aggregate Roots are there for a reason. They act as a single entry point to a group of related entities in order to enforce their invariants. They make sure that no external object can mess up with these entities and potentially violate their invariants.
However, in your particular scenario, even if ParamValue holds a direct reference to TemplateParam, TemplateParam is not at risk of being modified by an entity in the Document aggregate. The value associated to a parameter for a given document will be modified, but not the parameter per say.
To make sure this is the case, you can make TemplateParam an immutable value object :
(in C#)
public class TemplateParam
{
private readonly string name;
public TemplateParam(string name)
{
this.name = name;
}
public string Name
{
get { return name; }
}
}
Thus you can encapsulate TemplateParam in ParamValue with no risk that one of the Template aggregate's invariants will be broken due to the "externalization" of TemplateParam.
Technically speaking that may be a violation of DDD's aggregate root constraint, but I don't believe it is one in spirit as long as you keep the "externalized" entity immutable and don't modify the object graph it originally belongs to.
One way you could go about this is to have the Template entity have a factory method for creating Document instances, which can enforce the constraint that all ParamValue instances are associated with appropriate TemplateParam. If the document is immutable then you're done. Otherwise, you can apply updates to the document through its associated template. This template can be referenced directly from the document or with an ID in which case the encapsulating application service would retrieve it when required for an operation. Direct references between ARs are not a strict violation of DDD, in fact the blue book specifies that are the only things that can be referenced by external ARs. It has become a constraint as of late because of other considerations such as consistency, performance, ORM mapping, etc. Take a look at this series of articles on effective aggregate design for some inspiration.