I have some questions about the Aggregate Objects for Repositories.
I'm making a Rest Service with DDD/UoW/Repo and Service pattern. Our new cloud web-apps shall use this service. In order to do this, we also have to sync data from the old databases, which are still in production. We created a "SyncService" which read and writes to/from the cloud and down to earth.
In my Rest/DDD-design. And I don't want the business logic to run on these, so in the original test project I have a repository for every model and the endpoints just do some simple validation and push the data straight to the database using the repository.
Let's say I have these entities:
Customer
Order
OrderLine
Article
Database Relationsships:
A customer can have many orders.
An Order can only have one customer.
An Order can have many OrderLine's.
An OrderLine can have one Article.
Questions:
Are all of these aggregates except Article?
And which of these Entities would have a repository?
What would the repository look like?
Should I make endpoints for the "SyncService" to only talk to generic repositories for insertion?
Thanks in advance.
Are all of these aggregates except Article?
I believe it's impossible to answer this question without having access to the business logic and understanding how the whole Domain should look like. E.g. In some system, the Customercould be an aggregate and Order just an entity and in some other backward.
This decision should be made by an architect.
2,3,4. If you are using DDD you access your entities by your aggregates. I'd say the concept of using the repository pattern is optional. In some cases, you can just use pure DB context and e.g. if you are using for example Entity Framework Core you don't have to build extra repository layer over it as it is already a repository by itself. So the answer to these questions would be- it all depends.
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.
In typical DDD architecture we have 3 layers:
Domain - no references
Application - it has reference to Domain layer
Infrastructure - it has reference to Domain layer
(+ Web / UI project)
Domain models live of course in Domain layer. But in which layer should live read models (projections) for read database, for example MongoDb?
Short answer, both Application Services (Application layer) and Repositories (Infrastructure layer) know about the READ models. The domain layer remains transparent to underlying persistence and loading mechanisms.
Long answer, the exact usage mechanism depends on how you use the read models. You could either be using them to construct objects used in your domain layer or more typically, only as responses to API queries.
First case: Use Read Models as objects in the domain layer
The Application service loads the READ model from the repository into the domain entity. It is the repository's responsibility to populate the READ model correctly into the domain entity. The repository is also responsible for transforming the domain entity into the WRITE model to persist in the primary database.
By the time you get to the Domain model, objects are already loaded into memory with the help of repositories. So the domain layer does not even know about the READ model and a WRITE model; it only deals with the domain entity.
Second case: Use Read Models for storing pre-built responses to API queries
This scenario is a more typical use of the READ models. Usually, there are more than one read models for the same Entity/Aggregate because they are custom-built for specific API requests.
In this case, we don't even touch the domain layer. The Application Service accepts the request, uses the READ model repository to load the object, and return a response to the application server.
There's no written law that dictates in which project a read model should live. In my personal opinion, I think having a separate read model project has its benefits. With command query responsibility segregation things tend to get pretty confusing if the command-part of the application can access the query-part of the application. I think the two should be clearly separated.
I've spent some time working on an example project that demonstrates how to set up your DDD/ports-and-adapters/CQRS application. I've dropped the code on GitHub: https://github.com/appie2go/steal-this-code
I've also spent some time to explain the choices I've made in detail in the following articles:
https://medium.com/#abstarreveld/implementing-dddomain-models-ports-adapters-and-cqrs-with-c-2b81403f09f7 and,
https://medium.com/#abstarreveld/dddomain-models-ports-adapters-and-cqrs-reference-architecture-c-504817df65ec
Hope it helps!
Cheers
To be honest, it doesn't really matter. There's no default structure for neither DDD-oriented implementation or event sourcing-oriented implementation.
You can perfectly have a single project if the system is small. If you want to keep your domain clean of external references - you can keep it in a separate project and take care of having zero references except for something you need to support the domain model basis, like entity base class and so on.
Read models and projections are completely orthogonal to the domain model and you usually need them for the query API or query services. You will benefit from keeping read models (documents in case of MongoDB) and projections in one place. You can either reference this project from your API project or keep the query API, query services, query models, read models and projections together.
Again, I would argue that such a thing as a "typical DDD architecture" doesn't exist, because DDD is not architecture to start with. Splitting projects is more a developer convenience and discipline concern and splitting the system is the architectural concern, which is not DDD-specific.
One thing that also comes to my mind is that if you really think DDD, you might first want to find out what is your context map, how many domain models you really need and maybe there you can find some ideas about separation, not based on technical concerns really.
In our web application we have repositories with CRUD operations and a generic finder function, for instance userRepository.Get(u => u.Username == someString).
And UserRepository will return only User objects.
But what if I have a complex query which do the join between Table1, Table2 and Table3 and returns CustomObject which contains some properties from these 3 tables.
Should I put those queries in a Service layer?
Should repositories only contain basic CRUD and finder function and return basic entity object and nothing else? I ask because some people told me that no queries should be in Service layer...
I would probably create a type CustomObjectRepository which encapsulates the joining of tables and returns only CustomObjects. Exactly how to implement the generic finder function depends on what type of ORM you use (it will be trivial with EF, complicated but not at all impossible if you do manual mapping).
You can either have a Business logic View oriented Repository which stands one level on top of your current repository and name in according to that business logic.
Or you might apply hierarchical logic assigning this query to one of your existing repositories.
For example.
If you have 3 tables (Driver - Car- DriveSessions) and you need to display the User's First-Last Name, The car make,license plate and all the info of the last Drive session .
Using the 1st approach you would create a "Summaries" Repository.
Or you would add this in the "Driver" repository since all of these entities are oriented around a "Driver".
My opinion is adding a Repository in top of EF is an overkill . Some business models are so complex that it's kinda impossible to abstract everything on single repositories. That's why EF was designed for, with IQueryables. Encapsulating all your entities behind concrete repositories you lose most of the candy EF has to offer.
Opinions about using Repository pattern on top of EF
In my application i think not a single entity is non complex. Using a concrete per table repository would decrease performance and increase development time A LOT
Use the Query Object pattern. It's a much more SOLID approach. Furthermore, separating querying and CRUD, creates opportunities to use different, more appropriate infrastructure that might be better suited to custom querying. Also see: this
If you can, investigate what Vaughan Vernon calls a 'use cas optimal query' and beware of the smell that he calls 'repository masks aggregate mis-design'.
I've been reading articles on StackOverflow and other sites all day about best architecture practices and there are just so many conflicting ideas and opinions.
I've finally settled on an approach, but I am having a really hard time deciding where to place the EF objects (DbContext, Fluent APIs, Seeding data, etc). Here is what I currently have:
ASP.NET MVC Project: The actual web project. Contains the standard views, controllers and View Models (inside a Models folder).
Domain Model Project: Contains all POCO classes that define the database (domain) objects. Currently, does not mention or reference any EF objects.
Service Layer Project: Contains service objects for each type of domain object (e.g., IProductService, IOrderService, etc). Each service references EF objects like DbSets and handles business rules - e.g., add a Product, fetch a Product, append a Product to an Order, etc.
So the question is, in this configuration, where do EF classes go? Initially I thought in the Service Layer, but that doesn't seem to make sense. I then thought to put them in the Domain Model Layer, but then it ties the Domain Models to EF, which is essentially a DAL / Repository. Finally, I thought about creating a separate DAL Project just for EF, but it seems like a huge waste considering it will likely have 3-4 files in it (DbContext and a few other small files).
Can anyone provide any guidance?
There is no need for Domain Model since it will be redundancy. EF classes directly can act as Domain Model and they are converted to View Models while sending it to View. EF can be separated into different class library. Most of them use repository pattern along with any ORM incase it would be easy if they go for replacement. But I've seen criticism over using repository pattern, check this out.
Here is what I do:
Data:
Has one class inheriting from DbContext.
It has all the db sets.
Overrides OnModelCreating.
Mapping primary keys and relationships.
Entities:
Has every POCO classes.
Each property is decorated with needed data annotations.
Services:
Each service has common methods (GetList(), Find(), Create(), etc.).
Business:
Called from clients, orchestrate using services to perform a specific task UserChangePassword (this will check if this can be performed, then perform the task, or return error/unauthorized statuses among many others to make the client shows the correct information regarding the task. This on my case is where I log.
Clients (Desktop/Web/Wpf/etc).
I'm not saying this is the best approach, I'm just sharing what's been working for me.
Please help on choosing the right way to use the entities in n-tier web application.
At the present moment I have the following assembleis in it:
The Model (Custom entities) describes the fields of the classes that the application use.
The Validation is validating the data integrity from UI using the reflection attributes method (checks data in all layers).
The BusinessLogicLayer is a business facade for additional logic and caching that use abstract data providers from DataAccessLayer.
The DataAccessLayer overrides the abstarct data providers using LinqtoSql data context and Linq queries. And here is the point that makes me feel i go wrong...
My DataLayer right before it sends data to the business layer, maps (converts) the data retrieved from DB to the Model classes (Custom entities) using the mappers. It looks like this:
internal static model.City ToModel(this City city)
{
if (city == null)
{
return null;
}
return new model.City
{
Id = city.CountryId,
CountryId = city.CountryId,
AddedDate = city.AddedDate,
AddedBy = city.AddedBy,
Title = city.Title
};
}
So the mapper maps data object to the describing model. Is that right and common way to work with entities or do I have to use the data object as entities (to gain a time)? Am I clear enough?
You could use your data entities in your project if they are POCOs. Otherwise I would create separate models as you have done. But do keep them in a separate assembly (not in the DataAccess project)
But I would not expose them through a webservice.
Other suggestions
imho people overuse layers. Most applications do not need a lot of layers. My current client had a architecture like yours for all their applications. The problem was that only the data access layer and the presentation layer had logic in them, all other layers just took data from the lower layer, transformed it, and sent it to the layer above.
The first thing I did was to tell them to scrap all layers and instead use something like this (requires a IoC container):
Core (Contains business rules and dataaccess through an orm)
Specification (Seperated interface pattern. Contains service interfaces and models)
User interface (might be a webservice, winforms, webapp)
That works for most application. If you find that Core grows and becomes too large too handle you can split it up without affecting any of the user interfaces.
You are already using an ORM and have you thought about using a validation block (FluentValidation or DataAnnotations) for validation? Makes it easy to validate your models in all layers.
It may be a common practice to send out DTOs from serivce boundary (WCF service, etc.) but if you are directly using your "entities" in your presentation model, I don't see any benefit in doing that.
As to the code snippet you have provided, why not use AutoMappter? It helps by eliminating writing of boiler-plate mapping codes and does that for you if you have a set of convention in place.
Get rid of the model now, before removing it later will require refactoring the whole application. The last project i worked on used this architecture and maintaining the DTO layer and mappings to the database model layer is a huge pain in the arse and offers no usefull benefits. One of the main things that is anoying is that LinkToSql does not effectively support a disconnected data model. You cannot update a database table by creating a new DB entity with a primary key matching an existing record and then stick it into the data context. You have to first retrieve the entity from the database, update it then commit the changes. Managing this results in really nasty update methods to map all the properties from your DTOs to your LinqtoSql classes. It also breaks the whole deferred execution model of LinqToSql. Don't even get me started on the problems it causes with properties on parent classes that are collections of child DTOs (e.g. a customer DTO with an Orders property that contains a collection of order DTOs), managing those mappings is really really fiddly, i had to do some extensive optimisations because retrieving a few hundred records ended up causing LinqToSql to make 200,000 database calls (admittedly there was also some pretty dumbass code as well but you get the picture).
The only valid reason to use DTOs is if you want to have multiple pluggable Data Access Layers e.g. LinqToSql and NHibernate for supporting different DB servers. That way you can swap out the data access later without having to change any other layers. If you don't need to do this then save yourself a world of pain and just use the LinqToSql entities.