I have question regarding ddd and bounded contexts.
Suppose there are two bounded contexts. In the first one the aggregate root is Customer who is able to publish an advertisement on a webpage. I suppose that falls in his behavior, in turn he has a method of PublishAdvertisement().
But the second bounded context has Advertisement as aggregate. That imposes that Advertisement has a Customer property, due to its nature of belonging to a Customer.
Both Customer and Advertisement are unique in the system and database.
My question is:
Is it advisable to delegate the creation of Advertisement from Customer to a factory or dependency injection?
Edit:
I thank you for your answers and apologize for the lack of info.
Dependency injection:
I was wondering what is the best manner to resolve a given situation. The company has a Stock of Advert templates, if a template is in stock its good for use, if it's not, then it's rented to someone. The company has a plan on having more Stocks. If a Customer wants to make an advert in these templates he chooses a template and if its in stock all is good to go. Reading this as it is I assumed that there should be a service(domain) CheckAvailability(template), due to the nature of the service it does not fit in a specific aggregate because it uses several aggregates with validations and queries the database. In future when there would be more Stocks(some rented from other companies, maybe someone else's database), I was planing on using dependency injection to add these Stocks to the service without changing the implementation. Question is , does this seem as a good idea?
Bounded contexts:
In regards to bounded contexts and database. Yes, there is one database object and two contexts that use the same database object. Order has a reference to Customer, due to belonging to a Customer, looks something like this
Order()
Customer customer(get; private set;)
///other properties and methods
I would appreciate any additional information via link, video, book in terms of implications of having 2 contexts like these (Customer->Order___1:M) relate to the same database. Thank you.
Both Customer and Advertisement are unique in the system and database.
If that is the case, then having these concepts in two bounded contexts that use the same DB objects is a problem! The separation between two bounded contexts is a strong one, so they shouldn't communicate by changing the same DB object.
So I think you have some major design issues there. Try to fix them first by creating a model that corresponds to the real-world problem, discuss it with your domain experts.
And now to answer your main question:
Creating entities through factories is a good idea. The factory hides the (potentially complex) mechanism to create an entity and provide it with the required services. The factory receives these services through DI in the first place, and can forward them to the entity during instantiation.
Absolutely.
One thing is associating domain objects and another thing is working with them. An ad has some associated customer, and the customer and ad must be created in their respective domain layers (i.e. repository and service at least...).
This is separating concerns in the right way, since you don't want customers to be created where ads are also created and vice versa.
I guess you already know the single responsibility principle.
What are the customer related invariants enforced by Customer.PublishAdvertisement() ?
If there aren't any, you'll be better off moving that method to the
Advertisement aggregate root in the other BC, perhaps making it a constructor or to an AdvertisementFactory if the construction logic is complex. Just because the physical world user who creates an ad is a Customer doesn't automatically imply that their aggregate root should have that method. The ad creation process can stay in the Advertisement BC, with an Advertisement application service as the entry point.
If there are, then Customer could emit an
AdvertisementPublished event that the Advertisement BC subscribes
to. You should be aware though that if you follow the "aggregate as
consistency boundary" good practice, Customer can't be immediately
consistent with Advertisement which means that there can be a delay
and inconsistencies can be introduced between when the event is emitted and when the Advertisement is persisted and thus visible to other clients.
It is usually not an issue when you are creating a new AR, but keep in mind that the state of the Customer that checked the invariants and decided to create the Advertisement can change and the invariants be violated in the mean time, before Advertisement is persisted.
Obviously, given that the 2 BCs share a common database (which is probably not a good idea as #theDmi pointed out), you could decide to break that rule and make your transaction span across the 2 aggregates. Not necessarily that bad if you just persist a new Advertisement and not modify one that can potentially be accessed concurrently.
As far as dependency injection, I can't see the connection here -- what is the dependency to be injected ?
Related
I have a repository for an aggregate: Order and OrderRepository. Order has Products, Customer, etc. I'm using a micro ORM called dapper and .net core.
Here is my issue, when I need to save, I don't see how I can't break some DDD principle. I would like to have repositories for child entities of the aggregate i.e. ProductRepository, CustomerRepository and when I save the order it uses those repositories to save child entities but I understand that you can only have one repo per aggregate. I decided to just make a class called ProductPersistor, that would be internal to my infrastructure class library and called by the OrderRepository however then I can't use DI as it's configured .NET Core's DI framework in a different project. Furthermore it's still accessible by the classes in that class library. I can add all the insert update of all child entities into OrderRepository but that would be a gross SRP issue and still can't be injected using a DI container.
With regards to queries, the same issue stands although with dapper I can write a massive SQL JOIN and split it into different entities although that's not very efficient or flexible though.
I feel like I'm missing something. Can someone help?
Edit: As the comments below pointed out, Product and Customer can be their own Aggregate root. So let's replace those with Order and OrderLineItem.
Product and Customer seem like aggregates on their own, so they will need to have their own repositories ProductRepository and CustomerRepository. They should not be child entities of Order.
Your Order aggregate would be linked to Product and Customer, and the best way to do it between aggregates is to link on their unique identifiers.
A Repository is not equal or same as the underlying table - at least that is what DDD recommends. The Repository pattern sits between the aggregate data structure and the table/document structure, and represents the domain side of things. It's methods usually represent valid domain concepts: GetCompletedOrders(), GetTotalTaxAmount(), and so on.
An Application Service is supposed to handle the task of loading/persisting aggregates with the help of repositories, and that's the place where you would handle multiple repositories required for a process. This is where you can query other aggregates and get their identifiers, if necessary.
But I wouldn't recommend using multiple repositories as part of a single transaction in an Application Service. It violates the guideline that each business transaction should touch at most one aggregate. All other aggregates should be updated via Domain Events - they should become eventually consistent. Good for scaling and performance, this way. In your case, you may update Order aggregate, and bubble domain events to update Product and Customer, if necessary.
If you have complex queries and expect to run into performance problems (which I think you will as your system scales between Order, Product, and Customer), I would suggest you explore CQRS as an option. You don't have to implement it fully, but have readily available "Read" models in the background, with data already constructed in the format you want to consume. Background workers populate these "Read" models on a near real-time basis.
Please ask if this explanation does not cover all your questions or doubts.
The Problem
How are large collections implemented in DDD that "feel" like they should be a part of the aggregate root, yet would be impractical if they were? Here are a few examples based on my domain.
Employee Aggregate Root
Announcements Collection
Direct Messages Collection
Product Aggregate Root
Stock Items Collection
etc. etc..
What I'm Thinking
I would like to keep the ability to navigate to these large collections from the aggregate root but since I'm wrapping my O/RM with Repositories lazy loading isn't really an option... Unless I implement lazy loading by injecting either the necessary repository. But I know from what I've read about DDD that domain entities should not know about any such repositories..
The other option would be to take the approach that any potentially large collection of entities in my domain is an Aggregate Root and should have its own repository with the required interface to get the collection of items by another aggregate root. Eg.
public interface IStockRepository
{
IEnumerable<StockItem> FetchByProduct(Product product);
// ...
}
This "I would like to keep the ability to navigate to these large collections from the aggregate root" ... is a smell. You seem pretty obsessed, if you don't mind me saying, with the structure of your aggregate and not with its behavior, what problem(s) it is solving, any invariants that come into play. Frankly, the feeling you have is misplaced. It's a residue of our structural, database oriented way of thinking.
In general, I'd say, one should not have these large collections in the first place. For one loading them will require resources (memory, cpu, bandwidth) better spent elsewhere. From a more functional perspective people tend to not deal with large amounts at once anyway, and even computers can do more work when you break things down into units of work. As such, try to stay away from large collections and always question "why" you'd need them in the first place.
An announcement could be its own aggregate, referring to the employee by its id, so we know who the announcement was about (or for?). If the announcements are targeted at groups of employees, you might want to look into what defines that group, and model it explicitly. A direct message could also be its own aggregate because it is probably a message from one person to another. One could say the employee has the role of being a message recipient and/or sender. Again, referring to the employee aggregate by id might suffice. A stock item might be treated individually and refer to the product it represents within the stock by its productid. What is the behavior of an employee, an announcement, a direct message, a product, a stockitem? How and when does changing the state of its collaborators affect them and really, why is that? It's a means to a root cause. Find it.
All that said, there are times when you can bend the rules a bit, but they should be few.
Take a look at the Forum DDD example from Vaughn Vernon. He modeled the large collections out of the aggregate root. Creation is done by a factory method on the aggregate to keep control of some thing, like a dicussion can not be created when the Forum is closed. Actions are done through the AR Forum (like startDiscussion and moderatePost).
The method returns an entity (Post) that need to be saved in a separate repository (PostRepository) by the application service. Now you can have large collections without the need to load every time.
https://github.com/VaughnVernon/IDDD_Samples/tree/master/iddd_collaboration/src/main/java/com/saasovation/collaboration/domain/model/forum
I'm fairly new to the whole .NET scene and I'm still trying to figure this thing out.
One thing that seems to be very advocated for is the Domain Driven Design pattern. And eager as I am to get a flying start in the .NET world and doing it proper I dived in trying to apply it to my project.
As I understand it is bad practice to give a domain object access to persistence layer functions like repositories, but then I'm really struggling on how to get around the problem of eager loading when working with heavily connected graphs. It usually ends up with having pretty much no logic in the domain model and moving all of it to a service layer which does calculations and fills the model objects with data or returns the result directly, for example price = productService.CalculatePriceFor(product, user); instead of price = product.Price(user) since the latter cannot be accomplished without eager loading the whole productgroup tree and discount matrix when first requesting the object.
What is good practice here? Implement subclasses of product where the information for getting the user price is calculated at load time and have another subclass of it when I don't need the user price?
In proper DDD you don't have any heavily connected graphs. Vaughn Vernon's article about the aggregates design should help you catch the idea.
http://dddcommunity.org/library/vernon_2011/
Also consider if product and user belong to the same bounded context. I would say they don't. In different context there might be similar ideas implemented in different way, for example, in Pricing Context, the Client class might be a simple aggregate providing some rebates but no information about shipping, invoices etc. However, is Shipping Context there would be a similar user class being only an value object (with an address) within a Shipping aggregate. User class seems to be a part of Authentication Context.
For a large project, would it make sense to have one datacontext which maps out your database, which you can interact with from your classes?
Or would it make more sense to split this up into small datacontexts which are focused on the specific tasks within the database that will be required.
I'm curious as to the performance. It's my understanding that the datacontext itself is a very lightweight object, which only initializes its internal collections as they're required etc. Therfore dealing with a datacontext with many defintions but only two tables of data should be as fast as dealing with a special datacontext with only those two tables in it.
I also think you would benefit at the JIT time, as the first class to do data access will compile your dc which is now available to all classes.
I'm assuming you're asking about design versus runtime pattern. I general I'd say no:
While it may be possible to partition your database into multiple data contexts, then that would be desirable if and only if there was zero overlap between the two contexts.
Overlap is Bad
e.g. you have a WebsiteContext and an AdminContext. The WebsiteContext is for displaying Product and fulfilling Orders. A WebsiteUser is attached to an Order. The AdminContext is for your Staff members to process refunds for cancelled Orders, which also reference WebsiteUser. The AdminContext also needs to reset passwords and update other details for the WebsiteUser.
You're thinking of doing this because you don't want the website to process or even know about Returns
WebsiteContext
Product -- Order -- WebsiteUser
AdminContext
Staff -- Returns -- Order -- WebsiteUser
In the above, we can see we're duplicating many objects in the different Data Contexts. This smells bad, and it really indicates that artificially dividing the database into different data contexts is a the wrong decision. Do you have >2 databases after all, or just the one? The duplication violates the DRY principle (Dont Repeat Yourself) because WebsiteContext.WebsiteUser is not the same as AdminContext.WebsiteUser and in all likelihood the code is going to be messy when something needs to care which one they're referencing.
The Linq Data Context is just an OR mapper, and needs to be treated as a fancy black box that makes writing some of the data access code easier. Some linq demos make it look like you no longer need the other layers, but a program of any complexity still benefits from a layered design.
You're probably better off treating the Linq objects as just objects for easily transferring data and create a Domain layer that hides them as an implementation detail. Have a read of DDD - Domain Driven Design.
On their own, just using the Linq objects from the UI most resembles the Transaction Script pattern. In such a case you'd still benefit from having a logic layer that takes care of the details.
While you may not want the responsibility of a context to be so broad, the data context is just a representation of the database. It's not a security mechanism, and it can't prevent you from corrupting the data.
From a "repository pattern" angle, there is something to be said for having separate aggregates and minimizing the navigation properties between aggregates. I'm not 100% sure what that something is though... at the moment I'm considering using a moderately-sized dbml, with multiple repositories using it (the UI doesn't use the datacontexts directly - only the repository classes), with the navigation properties marked internal so the DAL can use them... Maybe...
I generally try and keep all related entities in the same repository. The following are entities that have a relationship between the two (marked with indentation):
User
UserPreference
So they make sense to go into a user repository. However users are often linked to many different entities, what would you do in the following example?
User
UserPrefence
Order
Order
Product
Order has a relationship with both product and user but you wouldn't put functionality for all 4 entities in the same repository. What do you do when you are dealing with the user entities and gathering order information? You may need extra information about the product and often ORMs will offer the ability of lazy loading. However if your product entity is in a separate repository to the user entity then surely this would cause a conflict between repositories?
In the Eric Evan's Domain Driven Design ( http://domaindrivendesign.org/index.htm ) sense of things you should first think about what about your Aggregates. You then build you repositories around those.
There are many techniques for handling Aggregates that relate to each other. The one that I use most often is to only allow Aggregates to relate to each other through a read only interface. One of the key thoughts behind Aggregates is that you can't change state of underlying objects without going through the root. So if Product and User are root Aggregates in your model than I can't update a Product if I got to it by going through User->Order->Product. I have to get the Product from the Product repository to edit it. (From a UI point of view you can make it look like you go User->Order->Product, but when you hit the Product edit screen you grab the entity from the Product Repository).
When you are looking at a Product (in code) by going from User->Order->Product you should be looking at a Product interface that does not have any way to change the underlying state of the Product (only gets no sets etc.)
Organize your Aggregates and therefor Repositories by how you use them. I can see User and Prodcut being their own Aggregates and having their own Repositories. I'm not sure from your description if Order should belong to User or also be stand alone.
Either way use a readonly interface when Aggregates relate. When you have to cross over from one Aggregate to the other go fetch it from its own Repository.
If your Repositories are caching then when you load an Order (through a User) only load the Product Id's from the database. Then load the details from the Product Repository using the Product Id. You can optimize a bit by loading any other invariants on the Product as you load the Order.
By repository you mean class?
Depending on the use of the objects (repositories) you could make a view that combines the data on the database and create a class (repository) with your ORM to represent that view. This design would work when you want to display lighter weight objects with only a couple columns from each of the tables.
If SQL Server is your database, and by repository you mean a database, then I would just stick the information in whatever database makes sense and have a view in dependent databases that selects out of the other database via three-dot notation.
I'm still confused by what you mean by "repository." I would make all of the things you talked about separate classes (and therefore separate files) and they'd all reside in the same project.