I am wondering whether it is good (and possible practice) to split one piece of data (property?) into two aggregates. Let's consider the following example:
There are Debt, Description and Tag properties.
There are 2 business requirements that if Debt value is bigger than 50.0 you cannot change Tag or Description anymore
The very first solution that comes to my mind is to create an aggregate like this along with Optimistic locking
public class Aggregate {
decimal Debt { get; private set; }
string Description { get; private set; }
string Tag { get; private set; }
int ConcurrencyToken { get; private set; }
void IncreaseDebt(decimal value) {
Debt += value;
ConcurrencyToken++;
}
void ChangeDescription(string description) {
Description = description;
ConcurrencyToken++;
}
void ChangeTag(string tag) {
Tag = tag;
ConcurrencyToken++;
}
}
Consistency of business rule is achieved, however modifying Tag and Description at the same time would cause ConcurrentAccessException. From business perspective user should be allowed to modify two of them at the same time.
The only solution that I see is to perform automatic retry on the client's side whenever changing Tag or Description and ConcurrentAccessException occurs. How to approach such problems?
The way I see it, using an optimistic concurrency check is the right approach, but if modifying Tag and Description can be done concurrently, then you can implement the retries at the server level, not the client. So, if you have two requests coming in exactly at the same time, the behaviour from the client's point of view will be the same as if they came one after the other.
One consideration you have to make though is the experience from the user's point of view. A user makes the decision to modify the information based on the information that was presented on the screen. But when they submit the changes, someone has changed that information. For example, user A fixes a typo in the description and before submitting user B adds a full paragraph. If you just implement automatic retries (either at the client or the server) the description will be overridden. In these scenarios, you can use the Concurrency Token to detect the change (even before executing the business operation and attempting to save the aggregate) and show the user the updated information.
That said, I don't understand what you mean in the title of the question, because these two properties belong to a single aggregate and this type of solution will only work this way. In fact, that is the main point of the aggregates: maintaining data consistency based on the business rules. Data in multiple aggregates can only be eventually consistent.
Related
What would be a rule of thumb when designing an aggregate in DDD?
According to Martin Fowler, aggregate is a cluster of domain objects that can be treated as a single unit. An aggregate will have one of its component objects be the aggregate root.
https://martinfowler.com/bliki/DDD_Aggregate.html
After designing aproximatelly 20 DDD projects I am still confused about the rule of thumb when choosing domain objects that would create an aggregate.
Martin Fowler uses order and line-items analogy and I don't think it is a good example, because order+line-items are really tightly bounded objects. Not much to think about in that example.
Lets try with car analogy where CarContent is a subdomain of a car dealer domain.
CarContent would consist of at least one or more aggregate/s.
For example we have this AggregateRoot (i am keeping it as simple as possible)
class CarStructureAggregate
{
public int Id {get; private set;}
public ModelType ModelType {get; private set;}
public int Year {get; private set;}
public List<EquipmentType> {get; private set;}
}
Alternative could be this (example B)
class CarStructureAggregate
{
public int Id {get; private set;}
public ModelType ModelType {get; private set;}
public int Year {get; private set;}
}
class CarEquipmentAggregate
{
public int Id {get; private set;}
public List<EquipmentType> {get; private set;}
}
Car can be created without equipment but it cannot be activated/published without the equipment (ie. this can be populated over two different transactions)
Equipment can be referenced trough CarStructureAggregate in example A or using CarEquipmentAggregate in example B.
EquipmentType could be an enum, or could be a complex class with many more classes, properties.
What is a rule of thumb when choosing between examples A and B?
Now imagine that car could have more information such as
photos
description
maybe more data about the engine
and CarStructureAggregate could be an extremely large class
So what is it that makes us split Aggregate into new Aggregates? Size? Atomicity of a transaction (although that would not be an issue since usually aggregates of a same sub domain are usually located on the same server)
Be careful about having too strong OO mindset. The blue book and Martin Fowler post are a little bit old and the vision it provides is too narrow.
An aggregate does not need to be a class. It does not need to be persisted. Theese are implementation details. Even, sometimes, the aggregate do things that does not implies a change, just implies a "OK this action may be done".
iTollu post give you a good start: What matters is transactional boundary. The job of an aggregate is just one. Ensure invariants and domain rules in an action that, in most of the cases (remember that not always), change data that must be persisted. The transactional boundary means that once the aggregate says that something may, and has, be done; nothing in the world should contradict it because, if contradiction occurs, your aggregate is badly designed and the rule that contradict the aggregate should be part of aggregate.
So, to design aggregates, I usualy start very simple and keep evolving. Think in a static function that recives all the VO's, entities and command data (almost DTO all of them except the unique ID of the entities) needed to check domain rules for the action and returns a domain event saying that something has be done. The data of the event must contain all data that your system needs to persist the changes, if needed, and to act in consequence when the event reach to other aggregates (in the same or different bounded context).
Now start to refactoring and OO designing. Supress primitive obsession antipattern. Add constraints to avoid incorrect states of entities and VO's. That piece of code to check or calculate someting related to a entity better goes into the entity. Put your events in a diet. Put static functions that need almost the same VO's and entities to check domain rules together creating a class as aggregate root. Use repositories to create the aggregates in an always valid state. And a long etc. You know; just good OOP design, going towards no DTO's, "tell, don't ask" premise, responsibility segregation and so on.
When you finish all that work you will find your aggregates, VO's and entities perfectly designed from a domain (bounded context related) and technical view.
Something to keep in mind when designing aggregates is that the same entity can be an aggregate in one use case and a normal entity in another. So you can have a CarStructureAggregate that owns a list of EquipmentTypes, but you can also have an EquipmentTypeAggregate that owns other things and has its own business rules.
Remember, though, that aggregates can update their own properties but not update the properties of owned objects. For example if your CarStructureAggregate owns the list of EquipmentType, you cannot change properties of one of the equipment types in the context of updating the CarStructureAggregate. You must query the EquipmentType in its aggregate role to make changes to it. CarStructureAggregate can only add EquipmentTypes to its internal list or remove them.
Another rule of thumb is only populate aggregates one level deep unless there is an overriding reason to go deeper. In your example you would instantiate the CarStructureAggregate and fill the list of EquipmentTypes, but you would not populate any lists that each EquipmentType might own.
I believe, what matters here is transactional boundary.
On one hand, you can't establish it more narrow than it is sufficient for preserving an aggregate's consistency.
On the other hand, you don't want to make it so large to lock your users from concurrent modifications.
In your example, if users should be able to modify CarStructure and CarEquipment concurrently - then I'd stick to implementation B. If not - it would be simpler to use A.
in a very simple sentence, I can say:
basically, a business use case that aims to change and consists of one or more relevant entities, value objects, and invariants based on the business in domain-driven design is aggregate. being a model command is important because if you only need to read, you don’t need an aggregate.
Well I am trying to apply domain driven design principles for my application, with a rich domain model that contains both data fields and business logic. I've read many DDD books, but it seems that their domain models(called entities) are very simple. It becomes a problem when I have a domain model with 10-15 data fields, such as the one below:
class Job extends DomainModel{
protected int id;
protected User employer;
protected string position;
protected string industry;
protected string requirements;
protected string responsibilities;
protected string benefits;
protected int vacancy;
protected Money salary;
protected DateTime datePosted;
protected DateTime dateStarting;
protected Interval duration;
protected String status;
protected float rating;
//business logic below
}
As you see, this domain model contains a lot of data fields, and all of them are important and cannot be stripped away. I know that a good rich domain model should not contain setter methods, but rather pass its data to constructor, and mutate states using business logic. However, for the above domain model, I cannot pass everything to the constructor, as it will lead to 15+ parameters in constructor method. A method should not contain more than 6-7 parameters, dont you think?
So what can I do to deal with a domain model with a lot of data fields? Should I try to decompose it? If so, how? Or maybe, I should just use a Builder class or reflection to initialize its properties upon instantiation so I wont pollute the constructor with so many arguments? Can anyone give some advice? Thanks.
What you've missed is the concept of a Value Object. Value objects are small, immutable objects with meaning in the respective domain.
I don't know the specifics of your domain, but looking at your Job entity, there could be a value object JobDescription that looks like this:
class JobDescription {
public JobDescription(string position, string requirements, string responsibilities) {
Position = position;
Requirements = requirements;
Responsibilities = responsibilities;
}
public string Position {get;}
public string Requirements {get;}
public string Responsibilities {get;}
}
This is C# code, but I think the idea should be clear regardless of the language you are using.
The basic idea is to group values in a way that makes sense in the respective domain. This means of course that value objects can also contain other value objects.
You should also ensure that value objects are compared by value instead of by reference, e.g. by implementing IEquatable<T> in C#.
If you refactor your code with this approach, you will get fewer fields on your entity, so using constructor injection (which is highly recommended) becomes feasible again.
Further notes regarding your example code that are not directly connected to the question:
The domain model is the whole thing, an entity is part of it. So your base class should be called Entity and not DomainModel.
You should make the fields of your class private and provide protected accessors where required to maintain encapsulation.
There's an awful lot going on in your Job domain model object - it seems to mix a huge number of concerns, and (to me at least) suggests a number of bounded contexts, some of which are easy to discern for the sake of making an example.
Remuneration (pay, benefits)
Organisational position (reporting line)
Person spec (skills)
Job specification (responsibilities)
etc.
When you consider the things that interact with your 'Job' model, are there any that need to inspect or mutate BOTH the Salary property and the Industry property, for example?
Without knowing the full nuances of the domain, the Salary you get for holding a position and the Industry you work in are not really connected, are they? Not a rhetorical point; these are the questions you NEED to ask the domain experts.
If they DON'T have any interaction then you have identified that these two things exist in two different BOUNDED CONTEXTS. The Salary side has no need of any interaction with the Industry side and vice versa, and even if they did, do they need to be held as state in the same process at the same time?
Think about the lifecycle of how a person becomes an employee; a person applies for a job. The job has a specification, salary range. The person attends an interview. The hirers offer the person the position. The person accepts. The person is now an employee, not a candidate any longer. The new employee is now accruing holiday and benefits and has a start date etc.
DDD teaches us that a single, unified view of the world rarely serves ANY of the concerns correctly. Please explore BOUNDED CONTEXTS - your software will be much more pliable and flexible as a result.
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 know there are a million questions like this. I'm sorry. I think mine is different but it may not seems so. I am new to DDD and trying to get a grip.
Part of my domain is like this.
Location 1-* Field
Field 1-* Event
Field 1-* Task
Task - Employee
now it would seem that the AR is the Location. and if I wanted to get a particular task I would have to traverse down to the task through the collection of fields in to the collection of tasks.
This sounds pretty laborious since I am dealing with tasks and events a lot and almost never with a location per say. The location serves to segregate a group of fields and their corresponding entities. So in the ui, I may pick a location and get a list of fields. I then would pick a field. From there I might edit one of it's tasks. So I have a collection of tasks and I pick one so I have the Id of the task. I then need to traverse up to location and get his Id so I can get the AR and traverse back down to the task. Or rather I would be keeping the Id of the AR around so that I could get it. So should I be keeping the Id of the Field around too? so what I return to the server would be the AR.Id, the Field.Id and the Task.Id that I want to look at?
Secondly, an employee of course could not be an Entity it would most likely be an AR. Is it ok for an Entity on an AR to have a collection of ARs?
So perhaps the way it should be structured is like this?
public class Location // is an aggregate Root
{
public IEnumerable<Field> Fields {get;set;} //in real code encapsulated. not here for brevity
}
public class Field // is an Aggregate Root
{
public Location Location {get;set;} //reference to AR
public IEnumerable<Task> Tasks {get;set;}
public IEnumerable<Events> Events {get;set;}
}
public class Task // is an Aggregate Root
{
public Field Field {get;set;} // reference to AR
public IEnumerable<Employee> Employees {get;set;}
public TaskType TaskType {get;set;} // probably Value Object
public IEnumerable<Equipment> Equipment {get;set;} // maybe Entity or AR
}
This makes it much easier to deal with the objects that are modified the most and to traverse their relationships, but it also feels sort of like plain old OOP and that AR doesn't really mean anything.
Again I'm new to DDD and don't have anyone to run this by for a sanity check. Please help me get a grip on how these boundaries are drawn, and if it is the first way, is there an easier way to handle dealing with the Entities then carrying around the AR.id, ParentParent.Id, ParentId and finally the object of interest Entity.Id
Thanks for any thoughts
R
Ok, upon some more googling I found this great series of articles.
https://dddcommunity.org/wp-content/uploads/files/pdf_articles/Vernon_2011_1.pdf
to get to part 2 and so on just change the last didgit in the url.
Here I discovered that, much like Yves points out, I was misunderstanding the purpose of Aggregates and Aggregate Roots. Turns out they are about maintaining consistency between related entities rather then just bundling up a bunch of entities that have relations to each other.
So if a Field could only have 3 Tasks on any given day, then a Field would be a good candidate for an AR since if you were just adding Tasks willy nilly you could easily create an invalid state in the system, where as if you had to add a Task via a method on Field, then it could easily be checked whether that is acceptable.
Further one wants to avoid giant aggregate roots because they take a lot of resources to load, and can cause concurrency problems. etc etc read the articles they address my above question beautifully
I'm looking for some advice on how much I should be concerned around avoiding the anemic domain model. We are just starting on DDD and are struggling with analysis paralysis regarding simple design decisions. The latest point we are sticking on is where certain business logic belongs, for example we have an Order object, which has properties like Status etc. Now say I have to perform a command like UndoLastStatus because someone made a mistake with an order, this is not as simple as just changing the Status as other information has to be logged and properties changed. Now in the real world this is a pure administration task. So the way I see it I have two options I can think of:
Option 1: Add the method to order so something like Order.UndoLastStatus(), whilst this kinda make sense, it doesn't really reflect the domain. Also Order is the primary object in the system and if everything involving the order is placed in the order class things could get out of hand.
Option 2: Create a Shop object, and with that have different services which represent differant roles. So I might have Shop.AdminService, Shop.DispatchService, and Shop.InventoryService. So in this case I would have Shop.AdminService.UndoLastStatus(Order).
Now the second option we have something which reflects the domain much more, and would allow developers to talk to business experts about similar roles that actually exists. But its also heading toward an anemic model. Which would be the better way to go in general?
Option 2 would lead to procedural code for sure.
Might be easier to develop, but much harder to maintain.
Now in the real world this is a pure administration task
"Administration" tasks should be private and invoked through public, fully "domain`ish" actions. Preferably - still written in easy to understand code that is driven from domain.
As I see it - problem is that UndoLastStatus makes little sense to domain expert.
More likely they are talking about making, canceling and filling orders.
Something along these lines might fit better:
class Order{
void CancelOrder(){
Status=Status.Canceled;
}
void FillOrder(){
if(Status==Status.Canceled)
throw Exception();
Status=Status.Filled;
}
static void Make(){
return new Order();
}
void Order(){
Status=Status.Pending;
}
}
I personally dislike usage of "statuses", they are automatically shared to everything that uses them - i see that as unnecessary coupling.
So I would have something like this:
class Order{
void CancelOrder(){
IsCanceled=true;
}
void FillOrder(){
if(IsCanceled) throw Exception();
IsFilled=true;
}
static Order Make(){
return new Order();
}
void Order(){
IsPending=true;
}
}
For changing related things when order state changes, best bet is to use so called domain events.
My code would look along these lines:
class Order{
void CancelOrder(){
IsCanceled=true;
Raise(new Canceled(this));
}
//usage of nested classes for events is my homemade convention
class Canceled:Event<Order>{
void Canceled(Order order):base(order){}
}
}
class Customer{
private void BeHappy(){
Console.WriteLine("hooraay!");
}
//nb: nested class can see privates of Customer
class OnOrderCanceled:IEventHandler<Order.Canceled>{
void Handle(Order.Canceled e){
//caveat: this approach needs order->customer association
var order=e.Source;
order.Customer.BeHappy();
}
}
}
If Order grows too huge, You might want to check out what bounded contexts are (as Eric Evans says - if he had a chance to wrote his book again, he would move bounded contexts to the very beginning).
In short - it's a form of decomposition driven by domain.
Idea is relatively simple - it is OK to have multiple Orders from different viewpoints aka contexts.
E.g. - Order from Shopping context, Order from Accounting context.
namespace Shopping{
class Order{
//association with shopping cart
//might be vital for shopping but completely irrelevant for accounting
ShoppingCart Cart;
}
}
namespace Accounting{
class Order{
//something specific only to accounting
}
}
But usually enough domain itself avoids complexity and is easily decomposable if You listen to it closely enough. E.g. You might hear from experts terms like OrderLifeCycle, OrderHistory, OrderDescription that You can leverage as anchors for decomposition.
NB: Keep in mind - I got zero understanding about Your domain.
It's quite likely that those verbs I'm using are completely strange to it.
I would be guided by the GRASP principles. Apply the Information Expert design principle, that is you should assign the responsibility to the class that naturally has the most information required to fulfill the change.
In this case, since changing the order status involves other entities, I would make each of these low-level domain objects support a method to apply the change with respect to itself. Then also use a domain service layer as you describe in option 2, that abstracts the whole operation, spanning multiple domain objects as needed.
Also see the Facade pattern.
I think having a method like UndoLastStatus on the Order class feels a bit wrong because the reasons for its existence are in a sense outside of the scope of an order. On the other hand, having a method which is responsible for changing the status of an order, Order.ChangeStatus, fits nicely as a domain model. The status of an order is a proper domain concept and changing that status should be done through the Order class, since it owns the data associated with an order status - it is the responsibility of the Order class to keep itself consistent and in a proper state.
Another way to think of it is that the Order object is what's persisted to the database and it is the 'last stop' for all changes applied to an Order. It is easier to reason about what a valid state for an order might be from the perspective of an Order rather than from the perspective of an external component. This is what DDD and OOP are all about, making it easier for humans to reason about code. Furthermore, access to private or protected members may be required to execute a state change, in which case having the method be on the order class is a better option. This is one of the reasons why anemic domain models are frowned upon - they shift the responsibility of keeping state consistent away from the owning class, thereby breaking encapsulation among other things.
One way to implement a more specific operation such as UndoLastStatus would be to create an OrderService which exposes the domain and is how external components operate upon the domain. Then you can create a simple command object like this:
class UndoLastStatusCommand {
public Guid OrderId { get; set; }
}
An the OrderService would have a method to process that command:
public void Process(UndoLastStatusCommand command) {
using (var unitOfWork = UowManager.Start()) {
var order = this.orderRepository.Get(command.OrderId);
if (order == null)
throw some exception
// operate on domain to undo last status
unitOfWork.Commit();
}
}
So now the domain model for Order exposes all of the data and behavior that correspond to an Order, but the OrderService, and the service layer in general, declare the different kind of operations that are performed on an order and expose the domain for utilization by external components, such as the presentation layer.
Also consider looking into the concept of domain events which considers anemic domain models and ways of improving them.
It sounds like you are not driving this domain from tests. Take a look at the work of Rob Vens, especially his work on exploratory modeling, time inversion and active-passive.