Domain Driven Design - where should we put repositories? - domain-driven-design

I am putting together a new system and I would like to have a rich domain for it. However, I am stuck on a little detail I want to know more about.
Suppose I would have a class Customer, where do you actually persist a customer entity or aggregate root?
should it be the customer class that has the knowledge of persistence?
var myCustomer = CustomerFactory.CreateCustomer(id);
myCustomer.Name = ...
myCustomer.LastName = ...
myCustomer.Save()
in this case I would need to pass my repository of Customers into the customer class (either via the factory or some injection). Notice that I could not find a good example of this in the DDD book by Eric Evens.
Another way is keeping the customer free of knowing about persistence
var myCustomer = CustomerFactory.CreateCustomer(id);
myCustomer.Name = ...
myCustomer.LastName = ...
CustomerRepository repository = new CustomerRepository();
repository.Save(myCustomer);
Also I suppose I can have a service class that does it all together like this:
AddCustomerService service = new AddCustomerService(CustomerRepository repository)
service.AddCustomer(myCustomer);
just a little note:
if I don't actually save in the customer class, I find that my customer class is nothing but properties, maybe with a little validation but nothing more. No real behavior is there. Behavior is moved either to service class or repositories used by the client...

The latter is preferable. That is, write your save method in your CustomerRepository class. In DDD entities should be ignorant of persistence logic. It is quite common for your domain entities to not contain behaviour, and to only contain properties (although sometimes they should contain both).

I have a DDD project. There are 4 layers in this order (because I am not using WCF else there would be more):
1. UI
1.1 MVC4.csproj
... (Repository Interfaces)
... (Repository Implementations)
2. Service Layer
2.1 Service.cs
...DTOs
3. Business Layer
3.1 DomainObjects.csproj
4. Data Access Layer
4.1 DAL.csproj (Entity framework 5)
... (Repository Interfaces)
... (Repository Implementations

Related

DDD Effective modelling of aggregates and root aggregation creation

We are starting a new project and we are keen to apply DDD principles. The project is using dotnet core, with EF core providing the persistence to SQL Server.
Initial view of the domain
I will use an example of a task tracker to illustrate our issues and challenges as this would follow a similar structure.
In the beginning we understand the following: -
We have a Project
Users can be associated to Projects
A Project has Workstreams
A Workstream has Tasks
Users can post Comments against a Task
A User is able to change the status of a Task (in progress, complete etc)
A Project, with associated Worksteams and Tasks is initially created from a Template
The initial design was a large cluster aggregate with the Project being the root aggregate holding a collection of ProjectUsers and Workstreams, Workstreams has a collection of Tasks etc etc
This approach was obviously going to lead to a number of contention and performance issues due to having to load the whole Project aggregate for any changes within that aggregate.
Rightly or wrongly our next revision was to break the Comments out of the aggregate and to form a new aggregate using Comment as a root. The motivation for this was that the business envisaged there being a significant number of Comments raised against each Task.
As each Comment is related to a Task a Comment needs to hold a foreign key back to the Task. However this isn't possible following the principle that you can only reference another aggregate via its root. To overcome this we broke the Task out to another aggregate. This also seemed to satisfy the need that the Tasks could be Completed by different people and again would reduce contention.
We then faced the same problem with the reference from the Task to the Workstream the Task belongs to leading to us creating a new Workstream aggregate with the foreign key in the Task back to the Workstream.
The result is: -
A Project aggregate which only contains a list of Users assigned to the project
A Workstream aggregate which contains a foreign key to the Project
A Task aggregate which contains a foreign key to the Project
A Comments aggregate which contains a foreign key back to the Task
The Project has a method to create a new instance of a Workstream, allow us to set the foreign key. I.e. slightly simplified version
public class Project()
{
string _name { get; private set;}
public Project(Name)
{
_name = Name;
}
public Workstream CreateWorkstream(string name)
{
return new Workstream(name, Id);
}
....+ Methods for managing user assignment to the project
}
In a similar way Workstream has a method to create a Task
public class Workstream()
{
string _name { get; private set;}
public int ProjectId { get; private set; }
public Workstream(Name, Id)
{
_name = Name;
_projectId = Id;
}
public Task CreateTask(string name)
{
return new Task(name, Id);
}
private readonly List<Task> _activities = new List<Task>();
public IEnumerable<Task> Activities => _activities.AsReadOnly();
}
The Activities property has been added purely to support navigation when using the entities to build the read models.
The team are not comfortable that this approach, something doesn't feel right. The main concerns are:-
it is felt that creating a project logically should be create project, add one or more workstreams to the project, add task to the workstreams, then let EF deal with persisting that object structure.
there is discomfort that the Project has to be created first and that the developer needs to ensure it is persisted so it gets an Id, ready for when the method to Create the template is called which is dependent on that Id for the foreign key. Is it okay to push the responsibility for this to a method in a domain service CreateProjectFromTemplate() to orchestrate the creation and persistence of the separate objects to each repository?
is the method to create the new Workstream even in the correct place?
the entities are used to form the queries (support by the navigation properties) which are used to create the read models. Maybe the concern is that the object structure is being influence by the how we need to present data in a read only
We are now at the point where we are just going around in circles and could really use some advice to give us some direction.
The team are not comfortable that this approach, something doesn't feel right.
That's a very good sign.
However this isn't possible following the principle that you can only reference another aggregate via its root.
You'll want to let go of this idea, it's getting in your way.
Short answer is that identifiers aren't references. Holding a copy of an identifier for another entity is fine.
Longer answer: DDD is based on the work of Eric Evans, who was describing a style that had worked for him on java projects at the beginning of the millennium.
The pain that he is strugging with is this: if the application is allowed object references to arbitrary data entities, then the behaviors of the domain end up getting scattered all over the code base. This increases the amount of work that you need to do to understand the domain, and it increases the cost of making (and testing!) change.
The reaction was to introduce a discipline; isolate the data from the application, by restricting the application's access to a few carefully constrained gate keepers (the "aggregate root" objects). The application can hold object references to the root objects, and can send messages to those root objects, but the application cannot hold a reference to, or send a message directly to, the objects hidden behind the api of the aggregate.
Instead, the application sends a message to the root object, and the root object can then forward the message to other entities within its own aggregate.
Thus, if we want to send a message to a Task inside of some Project, we need some mechanism to know which project to load, so that we can send the message to the project to send a message to the Task.
Effectively, this means you need a function somewhere that can take a TaskId, and return the corresponding ProjectId.
The simplest way to do this is to simply store the two fields together
{
taskId: 67890,
projectId: 12345
}
it is felt that creating a project logically should be create project, add one or more workstreams to the project, add task to the workstreams, then let EF deal with persisting that object structure.
Maybe the concern is that the object structure is being influence by the how we need to present data in a read only
There's a sort of smell here, which is that you are describing the relations of a data structure. Aggregates aren't defined by relations as much as they are changes.
Is it okay to push the responsibility for this to a method in a domain service CreateProjectFromTemplate
It's actually fairly normal to have a draft aggregate (which understands editing) that is separate from a Published aggregate (which understands use). Part of the point of domain driven design is to improve the business by noticing implicit boundaries between use cases and making them explicit.
You could use a domain service to create a project from a template, but in the common case, my guess is that you should do it "by hand" -- copy the state from the draft, and then send use that state to create the project; it avoids confusion when a publish and an edit are happening concurrently.
Here is a different perspective that might nudge you out of your deadlock.
I feel you are doing data modeling instead of real domain modeling. You are concerned with a relational model that will be directly persisted using ORM (EF) and less concerned with the actual problem domain. That is why you are concerned that the project will load too many things, or which objects will hold foreign keys to what.
An alternative approach would be to forget persistence for a moment and concentrate on what things might need what responsibilities. With responsibilities I don't mean technical things like save/load/search, but things that the domain defines. Like creating a task, completing a task, adding a comment, etc. This should give you an outline of things, like:
interface Task {
...
void CompleteBy(User user);
...
}
interface Project {
...
Workstream CreateWorkstreamFrom(Template template);
...
}
Also, don't concentrate too much on what is an Entity, Value Object, Aggregate Root. First, represent your business correctly in a way you and your colleagues are happy with. That is the important part. Try to talk to non-technical people about your model, see if the language you are using fits, whether you can have a conversation with it. You can decide later what objects are Entities or Value Objects, that part is purely technical and less important.
One other point: don't bind your model directly to an ORM. ORMs are blunt instruments that will probably force you into bad decisions. You can use an ORM inside your domain objects, but don't make them be a part of the ORM. This way you can do your domain the right way, and don't have to be afraid to load too much for a specific function. You can do exactly the right things for all the business functions.

Initializing Domain Objects - observing SOLID, Tell, Don't Ask

I'm trying to follow some of the more current design principles including SOLID and Domain Driven Design. My question is around how people handle "Initializing" Domain Objects.
Here's a simple example:
Based on SOLID, I should not depend on concretions, so I create an interface and a class. Since I'm taking advantage of Domain Driven Design, I create an object with relevant methods. (i.e. not anemic).
Interface IBookstoreBook
{
string Isbn {get; set;}
int Inventory {get; set;}
void AddToInventory(int numBooks);
void RemoveFromInventory(int numBooks);
}
public class BookstoreBook : IBookstoreBook
{
public string Isbn {get; set;}
public int Inventory {get; private set;}
public void AddToInventory(int numBooks);
public void RemoveFromInventory(int numBooks);
}
To help with testing and be more loosely coupled, I also use an IoC container to create this book. So when the book is created it is always created empty. But, if a book doesn't have an ISBN and Inventory it is invalid.
BookstoreBook(string bookISBN, int bookInventory) {..} // Does not exist
I could have 4 or 5 different classes that use a BookstoreBook. For one,
public class Bookstore : IBookstore
{
...
public bool NeedToIncreaseInventory(BookstoreBook book) { ...}
...
}
How does any method know is getting a valid book? My solutions below seem to violate the "Tell Don't Ask" principle.
a) Should each method that uses a Bookstore book test for validity? (i.e. should NeedToIncreaseInventory test for a books validity? I'm not sure it should have to know what makes a BookstoreBook valid.)
b) Should I have a "CreateBook" on the IBookstoreBook object and just "assume" that clients know they have to call this anytime they want to initialize a BookstoreBook? That way, NeedToIncreaseInventory would just trust that "CreateBook" was already called on BookstoreBook.
I'm interested in what the recommended appreach is here.
First off, I think your BookstoreBook doesn't have any really relevant methods, which means it doesn't have any relevant behavior, no business rules at all. And since it doesn't contain any business rules it actually is anemic. It just has a bunch of Getters and Setters. I would argue that having a method like AddToInventory that ends up just adding +1 to a property is no meaningful behavior.
Also, why would your BookstoreBook know how many of its type are in your Bookstore? I feel like this is probably something the Bookstore itself should keep track of.
As for point a): no, if you're creating books from user input you should check the provided data before you even create a new book. That prevents you from ever having invalid books in your system.
As for the creation of the object, the question is will you ever have more than one book type? If the answer is no you can drop the interface and just instantiate a book in a class that is responsible for creating new books from user input for example. If you need more book types an abstract factory may be useful.
First of all, a great way to make sure that entity state only can be set by behavior (methods) so to make all property setters private. It also allows you to make sure that all related properties are set when the state changes.
But, if a book doesn't have an ISBN and Inventory it is invalid.
There you have two business rules. Let's start with ISBN. If a book is not valid without it it HAVE to be specified in the constructor. Otherwise it's fully possible to create a book which is invalid. An ISBN also have a specified format (at least the length). So that format have to be validated too.
Regarding the inventory I believe that it's not true. You might have books that are sold out or books that can be booked before their release. Right? So a book CAN exist without an inventory, it's just not likely.
If you look at the relation between inventory and books from the domain perspective they are two separate entities with different responsibilities.
A book is representing something that the user can read about and use that information to decide whether it should be rented or purchased.
An inventory is used to make sure that your application can fulfill your customers request. Typically it can be done by a delivery directly (decrease the inventory) or by a backorder (order more copies from your supplier and then deliver the book).
Thus the inventory part of the application do not really need to know everything there is to know about the book. Thus I would recommend that the inventory only knows about the book identity (that's typically how root aggregates can reference each other according to Martin Fowler's book).
An inversion of control container is typically used to to manage services (in DDD the application services and the domain services). It's job is not to act as a factory for domain entities. It will only complicate things without any benefit.
To help with testing and be more loosely coupled, I also use an IoC container to create this book.
Why is your IoC container creating books? That's a bit strange. Your domain model should by container agnostic (wiring together the interfaces and the implementation is the concern of your composition root).
How does any method know is getting a valid book?
The domain model knows it is getting a valid book, because it says so right there in the interface.
The data model knows it is producing a valid book, because the constructor/factory method accepted its arguments without throwing an exception.
Should each method that uses a Bookstore book test for validity?
No, once you have a Book, it is going to stay valid (there shouldn't be any verbs defined in your domain model that would create an invalid data model).
Should I have a "CreateBook" on the IBookstoreBook object and just "assume" that clients know they have to call this anytime they want to initialize a BookstoreBook? That way, NeedToIncreaseInventory would just trust that "CreateBook" was already called on BookstoreBook.
It's normal to have a factory for creating objects. See Evans, chapter 6.
books can be created from a database and many other places. I'm assuming others have had to solve this issue if they are using DDD and I am wondering about their approach. Should we all be using factories - as you suggest that take the needed data as input?
There are really only two sources for data -- your own book of record (in which case, you load the data via a repository), and everywhere else (where you need to make sure that the data conforms to the assumptions of your model.
Based on SOLID, I should not depend on concretions
If you're referring to the Dependency Inversion principle, it does not exactly say that.
- High-level modules should not depend on low-level modules. Both should depend on abstractions.
- Abstractions should not depend on details. Details should depend on abstractions.
No domain entity is of a higher level than another and normally no object in the Domain layer is a "detail", so DIP usually doesn't apply to domain entities.
I also use an IoC container to create this book
Considering that BookstoreBook has no dependency, I'm not sure why you would do that.
How does any method know is getting a valid book?
By assuming that the book is Always Valid, always consistent. This usually requires having a single Book constructor that checks all relevant rules at creation time, and state-changing methods that enforce invariants about the Book.
a) ...
b) ...
You're mixing up two concerns here - making sure that Book is in a consistent state wherever it is used, and initializing a Book. I'm not sure what your question is really about in the end, but if you apply the "always valid" approach and forget about Book being an interface/higher level abstraction, you should be good to go.

resource lookup for entity construction in DDD

I am fairly new to DDD and here is my dilemma:
I have to persist an entity A that has a reference to entity B (let us consider both are entity roots). The UI layer gathers all these info (at controller) through A_DTO (DTO class for A), maps the attributes to a new instance of A from the DTO, now for the reference to B in A , UI sends an id. As I am using an ORM behind the repositories I would want to lookup for the object instance of B from BRepository , populate the reference on the new A instance that we are building and finally call ARepository.save(A instance).
I have a few options here
Do all these in UI layer(either in controller or some kind of service facade) or
Do this in a ApplicationService called createA or even a domain Service .
Which of options will be correct ??. Here what really stands out is the process of looking up of B by its id to get the reference to set on A object, this can be equally argued as process to keep ORM satisfied or to keep the domain model consistent. There might be some implicit business rules and validations around the process of setting reference of B on A, these I think are the driving points for the decision here.
Also what could queer the pitch further here will be a consideration for validations, should validations be weaved in the process of creation of an entity and say the constructors and/or setters through specific errors that can be bubbled to the client through UI and have another level of validatins through repos ?? or as an explicit step happening in the controllers ??
The DTO is merely a convenience class for transporting data within the UI layer. The fact that you use an ID to refer to B is an implementation detail of the UI layer. So it should be the job of the UI layer / controller to map the DTO to a domain object, including translating IDs to references.
Validation, on the other hand, belongs rightly in the domain layer. In this regard, the only job of the UI is to set values in the domain object and display any errors arising from this.
Both options can be viewed as correct, but I tend to prefer option 2 because the encapsulation provided by application services helps in reading and understanding the code. It also makes it easier to consolidate the API of your domain. The argument in favor of option 1 over 2 is that the additional layer of encapsulation resulting from use of application services is needless complexity, though of course you be the judge. Validation is usually manifested in several layers of a application, including the presentation layer and the domain layer. It seems ideal to write validation logic once and have it reused everywhere else, in practice it is usually easier to duplicate validation logic. That means the the presentation layer, such as ASP.NET MVC, has its own validation declarations for view models. Then the application service and domain entities should also perform any validation that is needed in that context. Take a look at my posts on services in DDD as well as validation in DDD for in depth discussion on these topics.

DDD saving "same" entity for different context boundaries

This is only an example.
Say that you have 2 entities for 2 different context boundaries. The first context is the SkillContexter, the entity is 'Player' and has 3 properties: Id, Name and SkillLevel. In the other context (Contactcontext) the entity is 'Player' and has 3 properties: Id, Name and EMail.
How do I persist these entities to the database? I only want one table (Player) and not two tables (PlayerContact, PlayerSkill). Shall I have two different repositories for player that save the different context-entities, but into same table? Or shall I have a "master" player entity that holds all properties that I need to save, so that I create a new entity called PlayerMaster that has 4 properties: Id, Name, EMail and SkillLevel?
The first solution gives me more repositories, and the second makes me make a "technical" entity that only purpose is to save data to a database, and that feels really wrong, or is there a better solution that I have missed?
How have you guys solved it?
When I first started with DDD, I also wrestled with the Context + Domain + Module + Model organization of things as well.
DDD is really meant to be a guide to building your domain models. Once I stopped trying to sub-organize my Contexts and boundies, and started thinking of what really is shared between entities - things started to fit together better.
I actually do not use contexts, unless it is a completely different application (app = context). Just my preference. But, I do have Modules that only share base abstracts and interfaces common throughout code (IRepository, IComponent, etc). The catch is, DDD says that Modules can share entities between modules - but, only on a very limited scale (you really don't want to do it often).
With that in mind, I would get away from using contexts and move to a "what really am I trying to accomplish, what do these models have in common). Here's what I would think, reading your question (if I understand them).
Person() is a base entity. It has ID and Name.
PlayerSkill() is a Value Object, that is
accessable from Person().PlayerSkill.
Contact() is an entity that inherits Person(),
so it inherits ID and Name, and has additional Contact properties you want.
Now, I just tore up your domain. I know.
You can use a hybird approach as well:
Person() is a base entity. It has ID and Name.
Player() inherits Person(), applies Skill()
and other VOs.
Contact() inherits Person(), applies Address()
and other VOs.
I'm not quite sure what you mean by context boundaries, so my answer may be off.
Do the two Player entities represent the same physical entity (person)? If so, then I would create a single Player entity with all four attributes and store their data in a single table.

Domain Objects and Services

In this question someone replies "You never let the domain object implementations call services by themselves!". Is this statement a hard fast rule of DDD or does it depend on your own application and architecture?
Contrived example:
As an example lets suppose we have a UserImage object in our model that gets populated from an uploaded image by a user. And then lets suppose that we can submit this image to a 3rd party service that can identify thumb prints and return a Guid if a match is found.
public IThumbPrintService {
Guid FindMatch(Bitmap image);
}
public class UserImage {
public Bitmap Image {get; set;}
public Guid ThumbPrintId {get; set;}
public bool FindThumbPrintMatch() {
// Would you call the service from here?
ThumbPrintId = _thumbPrintService.FindMatch(this.Image);
return ! ThumbPrintId.CompareTo(Guid.Empty);
}
}
public class RoboCopUserImageService : IUserImageService {
// Or move the call to a service method
// since it depends on calling a separate service interface
public bool FindThumbPrintMatch(UserImage userImage) {
userImage.ThumbPrintId = _thumbPrintService.FindMatch(userImage.Image);
return !userImage.ThumbPrintId.CompareTo(Guid.Empty);
}
}
What is avoided or gained by not letting domain objects call services themselves?
EDIT: Are there any good online articles that discuss this specific topic?
This is the Spreadsheet Conundrum: does the phone dial the phone number, or does the phone number dial itself on the phone?
You might find Double Dispatch to be interesting reading, though overkill in your situation, I reckon.
The Single Responsibility Principle is often at odds with the OO tenet of Tell, Don't Ask. My feeling on the subject has oscillated, and I have settled on the following conditions when logic should go into a domain object:
The logic should be domain logic, i.e. nothing like image.load() or image.save()
The logic shouldn't give the object more than "one reason" to change in the domain. This is a re-statement of the SRP.
The logic shouldn't be forced into the object. In other words, if you end up doing something like trying to calculate the sum of some property in a list of domain objects without using a getter, think twice.
In your situation, I'd opt against putting the call to the service inside the entity object, mainly because the service doesn't seem like it is related to your domain, but more related to persistence. Domain objects should be coupled to domain concepts, and I don't think the service you gave qualifies.
An example where I think calling a service in an entity might be acceptable would be if your application used a third-party workflow server to manage parts of its state. Essentially, this is the State Pattern with the states defined at run-time.
I think it is acceptable to have domainObject.moveToNextState() (assuming this code "makes sense" in your ubiquitous language) call the service that talks to your server because the workflow server manages a part of the domain model.
I'll add that DDD is very interested with following the language of the domain. Do you hear domain experts saying "A user image finds if its thumb print matches those in the XYZ vendor service"? Or do they say "The XYZ vendor service, given a thumb print, indicates whether that thumb print exists"? Go with the one that makes the most sense in your domain.
Some more thoughts (I've thought about this issue a lot because it is central to design):
In the Evans DDD book, an Account
entity has methods like
credit(Amount), debit(Amount), transferTo(Account, Amount) and
accrue(), but a FundsTransferService has a transfer(Account, Account, Amount) method. The transferTo method doesn't call any service, but merely handles the logic that involves Accounts, like crediting and debiting the right amounts.
The FundsTransferService, in addition to co-ordination, has its own rules to check, rules that don't fit into Accounts. The exact amount to credit or debit might involve outside parties. This makes it awkward for transferTo to call the service.
For simple objects, like the UserImage, significant domain logic that can fit in the object itself might be scarce because it isn't, as far as I can tell, an Aggregate. Aggregates, I think, present more of an opportunity to house domain logic. The Account example is likely an Aggregate.
One disadvantage I see is that allowing your domain object to call services may make it harder to serialize, or at least cause some issues after serializing it when someone on the other side calls its service method(s).
If you allow an Entity Object to call a service it is performing two roles Data Object and Service Object. Generally, each object should have on responsibility, not only in implementation but also in usage.
In your case, the lowly UserImage seems to be both an Image and a ThumbPrint Recognizer.
I think it's better not to call repositories or services from entities or value objects, but sometimes it's necessary, for example, if an entity has to return other entity which should be loaded from database but it cannot navigate to it using object graph. Then dependency inversion principle comes to help, which means that entities and value objects depend on interfaces of services and repositories and not on implementations.

Resources