I'm looking at DDD and I have some thoughts. On a shopping site I have the typical Order.
public class Order
{
public ICollection<OrderRow> OrderRows { get; set; }
public ICollection<Payment> Payments { get; set; }
...
}
Payments seem to be natural to place on the Order. When placing an order or working with the order, payments is a part of the order.
But later an administrator want to handle payments separately. E.g. in the administration interface have list of payments which needs to be handled.
How should I do this? Should Payments be removed from the order and be its own root aggregate?
My understanding is that aggregates can and will overlap, allowing you to define the aggregate that makes the most sense for the business context of the current operation.
So in this instance, yes, when working in terms of Order you'd expose Payments as part of the Order aggregate, but this doesn't prevent you from also having a dedicated PaymentRepository that exposes Payment as an aggregate root.
I think that Payment entity doesn't belong to Order aggregate. As you wrote you have functionality that works with Payments separately. It means that payments are not used in Order context only. It means that Payments doesn't belong to Order aggregate :).
However it is possible to have Payments property in Order class even if it isn't a part of Order aggregate.
If a Payment can't exist without an Order then Payment isn't an aggregate root.
If it's not an aggregate root then loading the appropriate Order objects from an OrderRepository and operating over the Payment entities within seem to have the most DDD integrity.
Related
I have a microservice called reward. When a customer does a certain activity in a different microservice(spent a specific amount of money), that service publishes an event, lets say SpentRewardingMoney.
In reward service, my aggregate root is Customer.
public class Customer: Entity, IAggregateRoot
{
// some properties
public List<CustomerReward> UserRewards { get; private set; } // rewards already given
}
Now in SpentRewardingMoneyConsumer, I have to give reward to that customer.
Problem is, there is some configuration, for simplification suppose a table RewardRule(reward amount, is reward active etc) to disburse reward. According to DDD rule, I have to pull everything through aggregate root but this configuration is not part of aggregate root.
How should I pull this table from the database?.
The rewards can be loaded from a database or any other persistence that you use. It'll be loaded through a repository.
The question other part of your question is: Where should it live in your model?
It depends on your ubiquitous language (UL).
To my understanding, it sounds like "reward amount" and "is reward active" are all values of the Customer Reward object. (This is an educated guess based on my guess about your requirement and UL).
Rewards could also be it's own aggregate (also depends on UL). In which case communicating between aggregates in the same context is straight forward. You might use a service to simplify the interactions in such a case.
I need some clarification on modelling a user for Identity and access domain. The user domain model has a contact information entity (entity because it is mutable), the customer can register with a phone number, but can choose to change it when needed.
The phone number once used by a customer can never be used by any other user. So the model I believe must allow querying the phonenumber table(since it is many to one with the customer, as the old numbers are deactivated and archived).
If creating a domainservice is ok, what should be the Repository as there is no aggregate identified.
With these cases I have a customer(user) aggregate, but to allow querying all the users to see if the phone number provided by the customer is already been used by anyone else, what should be the aggregate, or can I write a DomainService that just can query the database directly to the phonenumber table to check for the uniqueness, am I violating any DDD principle doing so, what are the cleaner alternatives.
An alternative would be to create an Aggregate that makes it explicit in which scope you intend the unique constraint to hold.
As a (contrived) example, a phone number might be unique across a country but not internationally. Thus :
// An Aggregate Root
public class Country {
// Store a lookup structure (userId, phoneNumber) here
public void addUser(userId, phoneNumber) {
// check phone uniqueness here
}
public void changeUserPhone(userId, phoneNumber) {
// check phone uniqueness here
}
}
Since you're using CQRS, phone numbers being in a separate Aggregate doesn't matter because on the Query side, Read Models will reassemble the User and their phoneNumber together.
This also plays well with the "don't create Aggregate Roots" approach since you have a starting point from where to create your User (User is probably an AR) and not just create it out of thin air.
You could have your repository check if the phone number exists, if it does then throw a rule exception else save the change. The key here is to inject an instance of the repository through the application layer and run rule inside the domain layer.
I currently create a Repository for each database table and a corresponding data class for the column values (object to pass around data).
I recently started using some 1 to 1 relationships and I'm not sure what would be the best way to implement them.
For example
If I have a User table and a UserSettings Table in a 1:1 relationship.
// Data classes (Holds all the field value for the table)
public class User
{
public int UserId { get; set; }
public string Name { get; set; }
}
public class UserSettings
{
public int UserId { get; set; }
public bool SomeSetting { get; set; }
}
Questions:
Should I always go through the User object to manipulate the UserSettings object, or should I be able to manipulate them
independently?
Should I include the primary key field in the UserSettings object?
Should I store a reference to the USerSettings object in the User object?
Do I make two repo's one for User and one UserSettings, or do I handle everything in the Users Repo.
The only time I've ever found a 1:1 relationship between aggregate roots to be useful is when the aggregate roots on either side of the relationship are managed by different domains. They must share the same primary key, and therefore if they are both managed by the same domain then they are by definition parts of the same aggregate root. I think you need to approach this question from a different angle:
Is the User object only going to exist for this application?
Do you expect that to always be the case?
If the User is a concept that resides entirely inside of this domain, then there's no reason to have a UserSettings aggretate root that has a 1:1 relationship with a User; you simply make User.Settings a way to retrieve the UserSettings for that User. (And of course that obviates the need for a repository - it becomes the responsibility of the UserRepository to hydrate the UserSettings when it hydrates everything else on the User.)
But, if the User will eventually inform sessions for multiple domains, then User needs to represent its own domain, the services of which your application will consume. Then, you gain a very real need to separate the UserSettings of this application from those of a different application. The User is not specific to this application, but the UserSettings for that User is.
NOTE - In the interest of not refactoring your project at this point, if the answer to either question 1 or 2 above is "no", then you should make UserSettings a separate aggregate root within the same domain, in order to create a seamless transition when you eventually do move User into its own domain.
What exactly do you mean by 'going through the user object' ?
IMHO, no.
You can, but I do not think you should. Is there any reason why you'd want to know to which User the settings belong to ? The only time you'd want to know that -imho- is when you persist it. In your database, you need to know to which User, the UserSettings belong to. In your model, I think you can suffice by a uni-directional relationship
You should only create a repository per aggregate root, in your case 'User' can be an aggregate root. UserSettings is -imho- not even an entity but a value object.
I currently create a Repository for each database table
...
// Data classes (Holds all the field value for the table)
It seems you're adopting a bottom-up (database first/database centric) approach which is uncommon in DDD. As the name Domain Driven Design implies, you usually rather start by modelling your domain, fleshing out your Aggregates, Aggregate Roots and Entities.
Aggregate roots usually have their own Repository while regular entities most often don't. To know whether an entity should be an Aggregate root, you have to ask yourself if that object is going to be one of the main entry points in the application, with a group of related objects gravitating around it and only obtainable through traversal of it.
User is an obvious candidate for an Aggregate root. User Settings in contrast isn't IMO a root, it belongs in the sphere of influence of a User. I'd make it a part of the User Aggregate and only obtainable through traversal of a User. It means having a reference to UserSettings in User but not necessarily the other way around.
I would ask yourself if a UserSettings can exist with out an associated user, and/or does a User always have an associated UserSettings. If so then the UserSettings could easily be made part of the User aggregate rather then being a separate aggregate itself. Yes in the database they will most likely be in different tables with 1:1 relationship between them, but this is a specific concern of the implementation of the repository. Your domain model could consider the UserSettings part of the user.
I am working on an application where we try to use a Domain Model. The idea is to keep the business logic inside the objects in the Domain Model. Now a lot is done by objects subscribing to related objects to react to changes in them. This is done through PropertyChanged and CollectionChanged. This work OK except in the following:
Complex actions : Where a lot of changes should be handled as a group (and not individual property/collection changes). Should I / how can I 'build' transactions?
Persistency : I use NHibernate for persistency and this also uses the public property setters of classes. When NHibernate hits the property a lot of bussiness logic is done (which seems unnecessary). Should I use custom setters for NHibernate?
Overal it seems that pushing all logic in the domain model makes the domain model rather complex. Any ideas???
Here's a 'sample' problem (sorry for the crappy tooling i use):
You can see the Project my container and objects below it are reacting to each other by subscribing. Now changes to Network are done via NetworkEditor but this editor has no knowledge of NetworkData. This data might even be defined in a another assembly sometimes. The flow goes from user->NetworkEditor->Network->NetworkData and the all other object interested. This does not seem to scale.
I fear that combination of DDD and PropertyChanged/CollactionChanged events might now be the best idea. The problem is, that if you base your logic around these events it is extremely hard to manage the complexity as one PropertyChanged leads to another and another and soon enough you loose control.
Another reason why ProportyChanged events and DDD doesn't exactly fit is that in DDD every business operation should be as explicit as possible. Keep in mind that DDD is supposed to bring technical stuff into the world of business, not the other way around. And basing on the PropertyChanged/CollectionChanged doesn't seem very explicit.
In DDD the main goal is to keep consistency inside aggregate, in other words, you need to model the aggregate in such way, that whatever operation you invoke the aggregate is valid and consistent (if the operation succeeds of course).
If you build your model right that there's no need to worry about 'building' transaction - an operation on aggregate should be a transaction itself.
I don't know how your model looks like, but you might consider moving the responsibilities one level 'up' in the aggregate tree, quite possibly adding additional logical entities in the process, instead of relying on the PropertyChanged events.
Example:
Lets assume you have a collection of payments with statuses and whenever a payment changes, you want to recalculate the total balance of customer orders. Instead of subscribing changes to the payments collection and calling a method on customer when collection changes, you might do something like this:
public class CustomerOrder
{
public List<Payment> Payments { get; }
public Balance BalanceForOrder { get; }
public void SetPaymentAsReceived(Guid paymentId)
{
Payments.First(p => p.PaymentId == paymentId).Status = PaymentStatus.Received;
RecalculateBalance();
}
}
You might have noticed, that we recalculate the balance of single order and not the balance of entire customer - and in most cases that's ok as customer belongs to another aggregate and its balance can be simply queried when needed. That is exactly the part that shows this 'consistency only within aggregate' thingy - we don't care about any other aggregate at this point, we only deal with single order. If that's not ok for requirements, then the domain is modeled incorrectly.
My point is, that in DDD there's no single good model for every scenario - you have to understand how the business works to be successful.
If you take a look at the example above, you'll see that there is no need to 'build' the transaction - entire transaction is located in SetPaymentAsReceived method. In most cases, one user action should lead to one particular method on an entity withing aggregate - this method explicitly relates to business operation (of course this method may call other methods).
As for events in DDD, there is a concept of Domain Events, however these are not directly related with PropertyChanged/CollectionChanged technical events. Domain Events indicate the business operations (transactions) that have been completed by an aggregate.
Overal it seems that pushing all logic in the domain model makes the
domain model rather complex
Of course it does as it is supposed to be used for scenarios with complex business logic. However if the domain is modeled correctly then it is easy to manage and control this complexity and that's one of the advantages of DDD.
Added after providing example:
Ok, and what about creating an aggregate root called Project - when you build aggregate root from Repository, you can fill it with NetworkData and the operation might look like this:
public class Project
{
protected List<Network> networks;
protected List<NetworkData> networkDatas;
public void Mutate(string someKindOfNetworkId, object someParam)
{
var network = networks.First(n => n.Id == someKindOfNetworkId);
var someResult = network.DoSomething(someParam);
networkDatas.Where(d => d.NetworkId == someKindOfNetworkId)
.ToList()
.ForEach(d => d.DoSomething(someResult, someParam));
}
}
NetworkEditor would not operate on Network directly, rather through Project using NetworkId.
I'm struggling with aggregates and aggregate roots. I have a natural aggregate root which works for about 60% of the user requests. I.e. those requests naturally apply to the aggregate root.
Within my aggregate I have another entity which can only exist as a member of the aggregate root. Users, however, will be told about this other entity object. It will sometimes make sense, conceptually, for users to operate on this non-aggregate root object directly.
So, I think I have a couple of options:
They can they both be aggregate roots depending on which operation is being requested by the user.
All operations have to go through the top level aggregate root.
Note that the top level aggregate root will hold a collection of this other entity.
Example:
Main aggregate root: Car
Second entity: Seat (a Car has either 2 or 4 seats depending on type). In my domain seats can only exist as part of a car.
Most operations in the domain are at the Car level. So that will be a good candidate for aggregate root. However, (and I'm struggling for examples here), some operations will be at the seat level, e.g. SpillCoffee, ChangeFabric, Clean....
Can Seat and Car both be aggregate roots? Or should I always start with Car?
Thanks
The idea of an aggregate is to guarantee consistency, being the root responsible for data integrity and forcing invariants.
Suppose there's a rule like "The fabric of all seats must be the same", or ""you can only spill coffee on the seat if there's someone inside the car". It will be much harder to enforce these, once the clients will be able to change the fabric separately, or these invariants will need to be forced outside (danger zone).
IMHO, if integrity or forcing invariants is not an issue, then aggregates are not really needed. But, if it is necessary, my advice is to start everything with the car. But always think of the model. If there are invariants like these, then who enforces these invariants? Then try passing this idea to the code, and everything should be fine.
Probably you need some deeper knowledge of some aspect of the domain model. This question shows that you are about to invent a way to organize the entities to supply the system, when, ideally, this kind of questions are already answered before implementation.
When this pops out only on the system implementation, you whether go back to review the domain or you discovered some fragility whose feedback could - and should - aggregate changes on related details of the business to make the domain richer and better modeled.
In the car example, I used the approach of two aggregates who correlate different contexts. The first would be the "car has a seat" approach, and in this aggregate the possible actions for "seat" would be just the ones that make sense to "seat as part of a car". Example: Clean.
The second aggregate would be in the context of "seat", and there would be the possible actions and configurations for seat as a standalone. Example: ChangeFabric, ColorList. This way, the aggregate "car" has "seat", but the clients can know seat on the context that makes sense. Which is dangerous, like said by samuelcarrijo on previous post. If the modifications between contexts affects the domain integrity, you lost all the aggregate concept.
In the case of a shopping cart with an cart and line items I have both of those as aggregate roots since I often modify them independently.
public class Cart : IAggregateRoot
{
public List<LineItem> LineItems {get;}
}
public class LineItems : IAggregateRoot
{
public List<LineItem> LineItems {get;}
}
However, I have a separate bounded context for orders and in this case I only need to have one aggregate root since I no longer need to modify the line items independently.
public class Order : IAggregateRoot
{
public List<LineItem> LineItems {get;}
}
The other option is to have a way of looking up the aggregate root from a child ID.
Car GetCarFromSeatID(guid seatID)