Тёмный

Where Should You Put Repository Interfaces In Clean Architecture? 

Milan Jovanović
Подписаться 106 тыс.
Просмотров 26 тыс.
50% 1

Опубликовано:

 

27 окт 2024

Поделиться:

Ссылка:

Скачать:

Готовим ссылку...

Добавить в:

Мой плейлист
Посмотреть позже
Комментарии : 161   
@MilanJovanovicTech
@MilanJovanovicTech Год назад
Want to master Clean Architecture? Go here: bit.ly/3PupkOJ Want to unlock Modular Monoliths? Go here: bit.ly/3SXlzSt
@10199able
@10199able Год назад
I think some graphics with layers and what you are doing, placed in the start of each section, could really help to understand what is going on :)
@MilanJovanovicTech
@MilanJovanovicTech Год назад
Hmm, didn't think about that, but it's not too difficult to add 🤔
@jannishecht4069
@jannishecht4069 Год назад
I hoped you would discuss the pros and cons putting the interfaces into the domain vs application layer. Maybe in a separate video? Thanks for the content. I always learn something new from it ❤
@MilanJovanovicTech
@MilanJovanovicTech Год назад
Nothing changes significantly if you place them in the Application layer, from a technical standpoint. From a Domain standpoint, I feel like placing them there expresses better the intent of your Domain and what you are allowing the Application layer to do with it i.e. how to orchestrate it.
@ChrisBingham
@ChrisBingham Год назад
It enables injecting the repositories into domain objects. This is can be good and bad
@MortvmMM
@MortvmMM Год назад
It also allows sharing the interfaces with other projects. Say you want to share your domain/intefaces with other projects, without sharing the implementation (only the contracts). Then you can put your interfaces in domain, create a package/nugget with that, and let the user choose the implementation details
@pilotboba
@pilotboba Год назад
I don't think it matters if the domain is isolated to the single application. But if the domain is shared across multiple applications I think defining the repositories at the application layer is a better choice. Since each application may need to persist the domain in a different way.
@dzl82
@dzl82 Год назад
IMHO Repository Interface goes into application layer. Why? Domain is knowledge and data (Model and Domain Services). How that data gets there is completely irrelevant to the business. If you define repository interface in the Domain you make Domain dependant and expecting something from the outer layer. Outer layer depends on the inner layer and never vice versa.
@miroslavgrozdanovski6813
@miroslavgrozdanovski6813 Год назад
Hey Milan, nice video as always. I have two questions related to this. 1) Do you sometimes return a IQueryable from your repositories, or you always prefer returning concrete entities (or a list of them)? 2) How do you avoid method explosions in the repositories, as different Includes or Where clauses are often needed?
@ruekkart
@ruekkart Год назад
Considering that he is talking about a domain-centric architecture, then repositories should only return Aggregates and should return them with all their state loaded. So, answering your questions, you should never return IQueryable from your repositories, and you would only need a few methods to load an Aggregate, even maybe just one to find by the Aggregate id. But again, this is only considering he's talking about domain-centric architecture and using DDD, and you should also consider your specific business case and performance issues by loading some Aggregates whole state.
@alfredorodriguez598
@alfredorodriguez598 Год назад
You could use Lazy loading
@AuraMajonezu
@AuraMajonezu Год назад
For the part about explosion of different methods in repositories - there is a specification pattern that can solve this problem
@elpe21
@elpe21 Год назад
@@AuraMajonezu I'm not a fan of Spec pattern. Perhaps it's the lack of experiance.. @Miroslav -> no , you never expose Iqueryable. @ruekkart -> well, loading whole order to delete one line seems like an overkill that Milan was explaining recently.
@MilanJovanovicTech
@MilanJovanovicTech Год назад
1) Never! Repositories (in the Domain) only return aggregates (and sometimes entities) 2) It won't happen typically, as you only ever need a few methods to implement most of the business logic. In case it does get out of hand, you can always resort to the Specification pattern.
@DongoBongKong
@DongoBongKong Год назад
I know that DDD advocates having the repository interfaces defined in the domain layer but as a general rule interfaces should be defined in the layer where they are consumed, i. e. in this case the application layer. But what frustrates me a bit about all these best practices and patterns is that they sometimes seem a bit rigid. I guess pragmatism is a good thing when applying them
@MilanJovanovicTech
@MilanJovanovicTech Год назад
I like discussing options, and letting people do what feels right for them
@aldmidmitr2223
@aldmidmitr2223 9 месяцев назад
Maybe methods in the repository should return Result? Then at the application leyer you can use the functional approach (described by you earlier) and combine calls to methods from different layers that return Result.
@MilanJovanovicTech
@MilanJovanovicTech 9 месяцев назад
It's an option, I've done something similar once
@trxe420
@trxe420 Год назад
This is the Separated Interfaces Pattern and Unit of Work pattern in action. I have the same implementation as you. Repository Interfaces go in Domain Layer, UoW interfaces goes in Application Layer and the implementations go in the infrastructure layer.
@MilanJovanovicTech
@MilanJovanovicTech Год назад
Do Repos only return aggregates (or entities)?
@trxe420
@trxe420 Год назад
@Milan Jovanović depends on the repo I guess and the query / command. What say you?
@mylesdavies9476
@mylesdavies9476 Год назад
Great content as always and in my opinion this is my preferred approach. Looking forward to the follow up on the query side.
@MilanJovanovicTech
@MilanJovanovicTech Год назад
Also thinking about a UoW pipeline behavior
@AlexLavrik
@AlexLavrik Год назад
Nice video as usually! Can you, please, enable the Tools > Options -> Projects and Solutions -> Track Active Item option? In this case the file you're working on will be highlighted at the Solution explorer and it will be much easier to follow your project structure at your videos.
@MilanJovanovicTech
@MilanJovanovicTech Год назад
I'll think about it - since there's a chance the active item could overlap with my face on the screen 😅
@oucemaz
@oucemaz Год назад
Great content. You mentioned that there are good sides and bad sides to this approach. Only pros were here. Do you have a plan to discuss the cons in the future?
@MilanJovanovicTech
@MilanJovanovicTech Год назад
The "only" con is that people might misuse it and add some EF concerns, otherwise that's about it.
@jamestheloyalkingsfan1103
@jamestheloyalkingsfan1103 Год назад
What are your thoughts on Ardalis' implementation of Clean Architecture, Specifications, and the Repository pattern? Do you think its better to write your own or use one that works out of the box?
@robertmarriott1008
@robertmarriott1008 Год назад
+1 I'm interested in his thoughts on this as well. Ardalis's package offers a generic, abstract repository, which I know is generally frowned upon. However, he combines it with the specification pattern so, in theory, the combination would avoid violating the open-closed principle because you wouldn't have to create a God-object repository that has to be altered every time a new requirement comes along.
@MilanJovanovicTech
@MilanJovanovicTech Год назад
Definitely no need to reinvent the wheel with the Specification pattern, and you can use his library. I think it's pretty good. I can't recall the Specification class itself exposes some hard dependencies on EF.
@birukayalew3862
@birukayalew3862 Год назад
Thanks Milan. I'm a bit confused; last time you showed us the EF Core implementation instead of the repository pattern. Which approach do you recommend, the Repository Pattern or EF Core?
@ProtectedClassTest
@ProtectedClassTest Год назад
Ff. Im confused as well.. what use cases do you use context directly or repositories?
@MilanJovanovicTech
@MilanJovanovicTech Год назад
My personal preference is: - Commands (business logic) - Specific repository, like here - Queries - EF directly, SQL, services, whatever works (just keep it simple) For super-simple applications - use EF everywhere.
@nicolasrey3383
@nicolasrey3383 Год назад
@@MilanJovanovicTech I also follow this same pattern. People like Alexey Zimarev also recommend to follow it for the query side. Then when putting this abstraction layer for the command side it allows to express the intent way much better as you just said (domain oriented), and it makes unit tests way more easier with test doubles instead of relying on any ORM specific feature (like InMemory() with EF core). For the read side, where you don't want any kind of logic, but just fetching data/formatting, the abstraction layer makes less sense, you won't use unit test here (so no need to mock any dependencies), but you'll prefer integration tests against a real database (see TestContainers or Ductus.FluentDocker)
@guillaumedotnet
@guillaumedotnet Год назад
This one is sooo great! Thanks Milan!
@MilanJovanovicTech
@MilanJovanovicTech Год назад
Thanks a lot, Guillaume 😁
@francescoguagnano1212
@francescoguagnano1212 Год назад
Why don’t put repo interfaces in the application layer?
@muhammedulas4970
@muhammedulas4970 Год назад
You may need to access to database from somewhere that is not dependent on application layer, in this case placing repository interfaces in the domain layer will allow you to use it from almost anywhere with DI.
@billqian7274
@billqian7274 Год назад
the same confusion, for my design, I would put IXXRespository and IUnitOfWork in application layer, and the implementation in the Infra layer.
@MilanJovanovicTech
@MilanJovanovicTech Год назад
A few reasons: - I consider them part of my Domain logic - I only use them in Command handlers (business logic) - They always return aggregates
@pablolopezponce
@pablolopezponce Год назад
Precisely because you only use them in the command handlers (which is app layer) and to avoid (mis)using them from domain methods, it makes more sense to place them in the application layer. They return aggregates that are the entry point to your domain methods.
@billqian7274
@billqian7274 Год назад
@@pablolopezponce agreed
@emanuelrodriguez3155
@emanuelrodriguez3155 Год назад
Great video! Quick question, why we introduce an abstraction IUnitOfWork for the SaveChanges and just do that SaveChanges on the method in the repository? After all you have the ApplicationDbContext inside the repository.
@elpe21
@elpe21 Год назад
I believe this is for transaction block so that operations from different repos are done in single transaction block
@MilanJovanovicTech
@MilanJovanovicTech Год назад
I like to do only 1 save changes call per request, also planning to cover a behavior that will wrap the UoW
@rodrigolira83
@rodrigolira83 Год назад
Hello Milan! In order to ensure that only the repository's methods can be called wouldn't you have to move the IApplicationDbContext somewhere else? What I mean is that any application layer class could just inject the IApplicationDbContext and query in any way and perform any operations on the entity set.
@krccmsitp2884
@krccmsitp2884 Год назад
I assume you now can safely remove that interface since it's no longer of use.
@MilanJovanovicTech
@MilanJovanovicTech Год назад
Yes, planning that for another video when I tackle the query side
@mehranlabour
@mehranlabour Год назад
Perfect Milan Thank you
@MilanJovanovicTech
@MilanJovanovicTech Год назад
Sure thing :)
@marinobjelopera4444
@marinobjelopera4444 Год назад
Great content Milan! One question, how would you hide the Active record and specifically EF core functionalities such as AsNoTracking(), AsSplitQuery() behind an abstraction that we introduce?
@MilanJovanovicTech
@MilanJovanovicTech Год назад
Just place it in the repository implementation and forget about it
@marinobjelopera4444
@marinobjelopera4444 Год назад
@@MilanJovanovicTech Fair, however let's say you have a repository function that retrieves aggregate FooBar by ID. You invoke this function in multiple command/query handlers. Of course, in command you may want this aggregate to be tracked, but in queries you just want to return data and run the query AsNoTracking. I am currently exposing asNoTracking bool in the repository interface but I find it very ugly as it's tightly coupled to EF core.
@MilanJovanovicTech
@MilanJovanovicTech Год назад
@@marinobjelopera4444 I don't use repositories on the query side
@zimcoder
@zimcoder Год назад
Do you have an end-to-end tutorial in C# building this application?
@MilanJovanovicTech
@MilanJovanovicTech Год назад
No, but I'm working on an end-to-end course that will cover a lot of these concepts (and more)
@acevinicius
@acevinicius Год назад
I usually put my repository interfaces in the application layer because I only add the dependency on the C# projects in the layer n to the layer n-1. For example Infra -> application -> domain. Infra knows about the application, but doesn't know about the domain. Application knows about the domain, but doesn't know about the infra. And the domain doesn't know about any other layer. It feels wrong (out of place) to put them in the application layer, as there belongs to the domain layer, but I didn't want to add the infra -> domain dependency. As a work around, we can use Interface inheritance, where the real interface is in the domain layer, the application layer has interfaces that inherits from those in the domain layer and they should be visible in the infra layer, but was really defined in the domain layer. Not an elegant solution, but keeps the layers isolated. What do you think about this approach?
@MilanJovanovicTech
@MilanJovanovicTech Год назад
I don't see any problem with Infrastructure referencing Domain. Moreover, if Application is referencing Domain, and Infrastructure is referencing Application, then you have a transitive reference from Infrastructure to Domain. 😁
@krccmsitp2884
@krccmsitp2884 Год назад
I like that approach an do nearly the same for my current and new projects.
@MilanJovanovicTech
@MilanJovanovicTech Год назад
That's awesome!
@rustamhajiyev
@rustamhajiyev Год назад
In my humble opinion, repository over ef is unnecessary redundancy. But with dapper it's quite ok. As always be pragmatic, don't dogmatic 😉 Anyway, thanks for the content 👍
@MilanJovanovicTech
@MilanJovanovicTech Год назад
I like it as an additional way of expressing my Domain logic
@pilotboba
@pilotboba Год назад
@@MilanJovanovicTech I don't think you should have domain logic in your repository since you implement it in your persistence layer. Your persistence layer isn't Core (clean architecture). Interfaces are not behavior either.
@krzysztoffrydrych204
@krzysztoffrydrych204 Год назад
Repositories are nice if you avoid lazy loading and want to encapsulate query that builds your agregate (whole graph of objects) Ideally you want your agregates to be as small as possible to protect the business rules. It depends on the complexity of the system and approach you take rather than the case of using ORM or not. For simple projects with anemic entities and minimal logic, repositories, DDD, CQRS and other sexy words in most cases is just an overengineering. Saying that in the same time there are projects where you should use those paterns to reduce complexity of already complex by nature domains.
@mateuszkaleta1495
@mateuszkaleta1495 11 месяцев назад
13:03 - I know that it works, but I cannot understand that one, You register IApplicationDbContext and IUnitOfWork as scoped. If we will assume that scoped is treated as one request , we are creating two instances of ApplicationDbContext Then we add some entities in repositories to one context and saveChanges on second context, which should not works... How it works here? where is only one instance of dbContext?
@MilanJovanovicTech
@MilanJovanovicTech 11 месяцев назад
No - scoped means that when you resolve IApplicationDbContext and IUnitOfWork you will get the same object instance back (for that scope)
@mateuszkaleta1495
@mateuszkaleta1495 11 месяцев назад
Yes, I checked it and that's make sense, @@MilanJovanovicTech , anyway thank's a lot for response :) great material as always :)
@Mytthewx
@Mytthewx Год назад
Thanks for video!
@MilanJovanovicTech
@MilanJovanovicTech Год назад
You're welcome!
@witChaos
@witChaos Год назад
Hello Milan, thanks for your awesome videos!! I have a question. I have a library that extends entity framework core. In this library there are all the entities and the repositories of the database, a test app project and unit test project. Could I use this library in clean architecture if yes, in which Iayer I could put it?
@MilanJovanovicTech
@MilanJovanovicTech Год назад
Most likely Infrastructure layer
@witChaos
@witChaos Год назад
@@MilanJovanovicTech Do you think is better to define the interfaces and the entities in the domain layer and the implementation of them in the infastracture layer or to have it together in a seperate library which is referenced in the infastructure layer as I did? Thanks :)
@rilwans
@rilwans Год назад
Thanks for what your do! I was wondering we have over 100 Entities and Repositories interface, do we have to manually them inject Dependency Injection
@MilanJovanovicTech
@MilanJovanovicTech Год назад
How are you doing it right now?
@rilwans
@rilwans Год назад
@@MilanJovanovicTech Manually registering them all 🥲 is there a better way?
@pabloferrando6471
@pabloferrando6471 Год назад
What is the benefit on defining repositories in the domain layer rather than in the application layer?
@MilanJovanovicTech
@MilanJovanovicTech Год назад
Exposing what are the allowed operations on your Domain. The Aplication layer has to use only that conntract. In essence, moving more of the logic into Domain, which is always a good thing.
@krccmsitp2884
@krccmsitp2884 Год назад
If you have Domain Services in your Domain Layer that want or need to access "the DB" you need the repository interfaces right there.
@emmanuelrf
@emmanuelrf Год назад
Wouldn't it be more convenient to have your repositories as properties within the UnitOfWork? This way, you can access them by simply injecting the UnitOfWork.
@krccmsitp2884
@krccmsitp2884 Год назад
That might be easier to accomplish, but has some drawbacks: First and foremost it defies the Explicit Dependencies Principle, but also looks similar to a Service Locator, which is mostly seen as an anti-pattern.
@emmanuelrf
@emmanuelrf Год назад
​@@krccmsitp2884 You might be right, but in the end, those principles act as guidance, and sometimes they bring nothing but complexity, like the one we're discussing. Repositories should be part of the UnitOfWork instead of being scattered throughout the application. They only require an instance of the DbContext, which is injected in the constructor of the UnitOfWork. To me, that seems more pragmatic.
@MilanJovanovicTech
@MilanJovanovicTech Год назад
I particularly dislike that approach because it makes the dependencies implicit
@krzysztoffrydrych204
@krzysztoffrydrych204 Год назад
Again it depends on the approach you take. I personally don't buy the argument of implicit/explicit dependencies of the application services / command handles simply because in many cases I DO NOT TEST handlers! Yes! I use them for loading objects into memory and to invoke methods on domain objects or domain services. With this approach you don't have to mock anything for unit tests, you simply use your objects in test cases. But hey you should do whatever works for you 😉
@Paul-uo9sv
@Paul-uo9sv 11 месяцев назад
Yo Milan, Great channel, do you by chance have a video on "Using Multiple DbContexts with Repository Pattern with IUnitOfWork" ?
@MilanJovanovicTech
@MilanJovanovicTech 11 месяцев назад
I have this for the initial set up: ru-vid.com/video/%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE--_AKTzDrYVc.html
@ayodejisamuelfakunle9981
@ayodejisamuelfakunle9981 11 месяцев назад
Hey Milian, I am still a bit consused by the repository, looking at many examples, repositoy interface is in the domain layer, but it is implemented in the presistence layer, my question is, doesnt this expose the Entity data.
@MilanJovanovicTech
@MilanJovanovicTech 11 месяцев назад
How does it expose entity data?
@ayodejisamuelfakunle9981
@ayodejisamuelfakunle9981 11 месяцев назад
@@MilanJovanovicTech Considering that the repository is implemented in the persistence layer and interfaces are defined in the domain layer, it follows that the implementation accepts arguments of types defined in the interfaces. For instance, when saving a Schedule, the interface method is defined to take a Schedule entity as an argument, possibly returning something. Similarly, when retrieving a schedule, the interface expects data of Schedule type. This implies that we need to import the entity inside the repository implementation.
@eleonorakolb466
@eleonorakolb466 Год назад
Thanks Milan for your Videos, they are much appreciated! I also wonder why the repo interfaces are in the domain layer, when the IUnitOfWork is not. It means that the persitence layer has a dependency on the application layer. Is that intended? Also I would really like to see how you would do an update. If the object beeing updated can only update a few propertys, how is it best practice in clean architecture to receive some parameters through web api and persist these to the database? Kind regards
@MilanJovanovicTech
@MilanJovanovicTech Год назад
For updates, just apply the changes (covering that in the next video though) and persist it. Let EF Core take care of the rest. For repo in Domain: - I consider it part of my Domain - I only ever return aggregates (no DTOs)
@SebieCodes
@SebieCodes 4 месяца назад
Have you considered providing a git repository with the code that you're working on so that viewers can follow along?
@MilanJovanovicTech
@MilanJovanovicTech 4 месяца назад
I share the code on Patreon: www.patreon.com/milanjovanovic
@ozkankoc4373
@ozkankoc4373 Год назад
is this not enough? public interface IRepository where T : BaseEntity { IQueryable Table { get; } Task Insert(T entity, CancellationToken cancellationToken = default); void Remove(T entity); Task SaveAll(CancellationToken cancellationToken = default); }
@krccmsitp2884
@krccmsitp2884 Год назад
This might be OK for CRUD, but not for domain-driven apps.
@MilanJovanovicTech
@MilanJovanovicTech Год назад
You don't want to be coupled to IQueryable
@dsfgato
@dsfgato Год назад
Hi Milan, I've been using repository pattern for a long time and now I'd like to switch to EF Core repository.. but how to test my handlers (for example) if I can't mock EF Core repository? A video regarding this approach would be nice! Thanks for you content.
@PelFox
@PelFox Год назад
Integration test with a db container.
@MilanJovanovicTech
@MilanJovanovicTech Год назад
You mean mocking a DbSet?
@dsfgato
@dsfgato Год назад
@@MilanJovanovicTech yeahh. I'll give a look at PelFox suggestion as well. Thanks a million
@Greenthum6
@Greenthum6 Год назад
Yup, integration testing EF dependent code works well. There are too many moving parts with mocking and/or in-memory db. Postgres containers start and run tests in seconds.
@dilipmevada
@dilipmevada 3 месяца назад
Hi Milan, Which approach is best in real project ? We should go for repository or use EF.
@MilanJovanovicTech
@MilanJovanovicTech 3 месяца назад
You decide
@ilovethenetherlaands
@ilovethenetherlaands Год назад
Hey Milan, doesn't the reference to the IUnitOfWork interface from the domain layer break clean architecture, since it is referencing the application layer from the domain layer?
@MilanJovanovicTech
@MilanJovanovicTech Год назад
There's no reference to the UoW in Domain layer
@iorch82
@iorch82 Год назад
Hot take I guess, repositories are application layer concerns just as third party api clients. Placing repositories in Domain layer implicitly opens up the "pure" Domain types to start referencing repository interfaces , which according to some authors is an anti-pattern Besides, I am a totally EF for full application kind of guy. All repository pattern ends up leaking implementation details of underlying ORM tech, eg. implicit Entity Tracking in Entity Framework.
@MilanJovanovicTech
@MilanJovanovicTech Год назад
If you go all in on EF, I support you completely. I don't think there's a wrong choice in software, just tradeoffs.
@phw1009
@phw1009 Год назад
Damn, I had to SMASHED the like button.
@MilanJovanovicTech
@MilanJovanovicTech Год назад
This is the way
@ravindranaths513
@ravindranaths513 9 месяцев назад
This is regarding Domain reference to Persistance. With respect to my knowledge, only application should have reference right. This is what Onion architecture. Please explain your view on this.
@MilanJovanovicTech
@MilanJovanovicTech 9 месяцев назад
Any outer layer is allowed to reference inner layers
@nicolasundiano8406
@nicolasundiano8406 Год назад
for example if we create a method in the repo GetPaginatedProducts in which we have to return paginated data with sorting sent from the client for example (nameAsc, nameDesc). Do we have to do that logic in the implementation of the repo? i mean switch between the sort argument if we have to sort by name, price, etc. Or is it a bussines logic and we have to encapsulate it and send it to the repo method?
@MilanJovanovicTech
@MilanJovanovicTech Год назад
That would be a Query, I handle those separately from my repository. I use Repositories only on the command side.
@Beachjfb
@Beachjfb Год назад
Thanks Milan for the very informative video. For the remove order line item method, should it be a good idea to add a method removeOrderLineItem in the Order AggregateRoot? I thought any state changes has to be managed within the Aggregate Root. Thanks a lot again 😀
@MilanJovanovicTech
@MilanJovanovicTech Год назад
Isn't there an order.RemoveLineItem method?
@appliveinc
@appliveinc Год назад
@@MilanJovanovicTech my bad :D
@francescoguagnano1212
@francescoguagnano1212 Год назад
If I have a method in my repo interface which has a parameter typed as IIncludableQueryable, how can I break the EF Core dependency?
@MilanJovanovicTech
@MilanJovanovicTech Год назад
Get rid of the dependency on IIncludableQueryable, and wrap it inside a well named method. Or try using the specification pattern.
@nicolasundiano8406
@nicolasundiano8406 Год назад
@@MilanJovanovicTech but if we use specification pattern with expressions we are depending on ef core, because sql query cant apply expressions. And using specifications with strings for example we wont have compiling errors
@mohamedsherif5129
@mohamedsherif5129 Год назад
i need ur opinion about make uow create repositories inside i always take this approach and i feel more comfortable in that first i don't need in handler inject every repository i just inject uow and call whatever repo i need second i just add to startup service uow and i don't need to interduce every repo and i repo might i violate some solid principles but i feel it worth what's ur opinion about this approach ?!
@MilanJovanovicTech
@MilanJovanovicTech Год назад
With multiple repositories you're being explicit about your dependencies (and what you need to mock for testing). With UoW + Repo inside approach it's all a bit implicit. Right?
@efimov90
@efimov90 Год назад
In this implementation - you make too much coupling on EF. Because your IUnitOfWork isn't provider of repositories and you can call SaveAsync, because you know - implementation can make this. But what if you use not EF? How will it work with Dapper or NHibernate or Redis or something else?
@MilanJovanovicTech
@MilanJovanovicTech Год назад
I'm pretty sure NHibernate would be similar. Dapper (SQL) is a different thing, since there's no built-in UoW concept.
@efimov90
@efimov90 Год назад
@@MilanJovanovicTech for sure NHibernate have it, but what if i need several unit of works? How it can be implemented?
@MilanJovanovicTech
@MilanJovanovicTech Год назад
@@efimov90 That's a lot of what ifs that may never actually happen. You never want to have multiple unit of works, because that implies a distributed transaction.
@efimov90
@efimov90 Год назад
@@MilanJovanovicTech actually, i work on a project, that have more than 1 unit of work at same time, much more. It's enterprice desktop application for inner usage with direct access to database.
@AboutCleanCode
@AboutCleanCode Год назад
Wouldn't we almost always mock the database for execution speed of our tests?
@MilanJovanovicTech
@MilanJovanovicTech Год назад
Not a proper test though
@AboutCleanCode
@AboutCleanCode Год назад
@@MilanJovanovicTech Why not? Just because such a test wouldn't test the entire application stack? Wouldn't you agree to different testing levels? And if we want to focus on "acceptance level testing" (pure functionality) wouldn't we try to be independent from complexity of the infrastructure? What about the UI? Would u include this in your acceptance tests?
@kennedydre8074
@kennedydre8074 6 месяцев назад
Hi Milan, thank you for the video, can I please get the example code?
@MilanJovanovicTech
@MilanJovanovicTech 6 месяцев назад
Will post it under the video next week
@kennedydre8074
@kennedydre8074 6 месяцев назад
@@MilanJovanovicTech thank you so much.
@GiovanniCostagliola
@GiovanniCostagliola Год назад
It’s a serious bad idea breaking the integrity of the Aggregate by fetching just a part of it. This violate the sense of having DDD in place. Aggregates MUST BE manipulated only through the AggregateRoot.
@MilanJovanovicTech
@MilanJovanovicTech Год назад
Even when the risk is low?
@GiovanniCostagliola
@GiovanniCostagliola Год назад
@@MilanJovanovicTech That's not a matter of risk but integrity of your system. AggregateRoots are the place to manage the invariants of the aggregate. By putting some "logic" within the repository (when you say "low risk") you're violating the ragion d'étre of the AggregateRoot, therefore your solution is not DDD compliant. Suppose your requirements evolve in a direction where you have to validate a delete operation based on the other items… you'll be in very big troubles
@chrisharrington6279
@chrisharrington6279 Год назад
I think you should add to each folder a README that explains in a few sentences the organizational purpose of that folder. Making a folder is making an opinion and you should share it.
@MilanJovanovicTech
@MilanJovanovicTech Год назад
That seems overly verbose 🤔
@chrisharrington6279
@chrisharrington6279 Год назад
@@MilanJovanovicTech Your material is great. I'm a fan, I'm a Patreon subscriber, and I've been programming since way before you were born. There's a wide gap between no documentation (what you have) and verbose. Adding a readme file to explain your reasoning is not crossing over to "verbose". I began my career in the nuclear industry. We measured our documentation in feet-width of binders. That was verbose.
@Hello_there_777
@Hello_there_777 Год назад
Sooooo where should i put it?
@MilanJovanovicTech
@MilanJovanovicTech Год назад
You have to decide 😁 I like placing them in the Domain, because I consider them part of my Domain logic
@cwevers
@cwevers Год назад
Nice 🙏🙏
@MilanJovanovicTech
@MilanJovanovicTech Год назад
Thanks!
@Embriiii
@Embriiii Год назад
in DDD approach you should act on a single aggregate per transaction
@MilanJovanovicTech
@MilanJovanovicTech Год назад
Yes
@coding-in
@coding-in 7 месяцев назад
How to register all repository automatically using reflection?
@MilanJovanovicTech
@MilanJovanovicTech 7 месяцев назад
Try Scrutor: www.milanjovanovic.tech/blog/improving-aspnetcore-dependency-injection-with-scrutor
@paulward5701
@paulward5701 Год назад
This approach has an entanglement problem. Wheb dealing with the database you should always preference an approach that results in you only dealing with a single entity type at this level and stack more complex business logic layers on top of this.
@MilanJovanovicTech
@MilanJovanovicTech Год назад
Care to point me where you see the issue? Couldn't figure out from your comment 🤔
@paulward5701
@paulward5701 Год назад
@@MilanJovanovicTech think of it like ICrud then you're injecting multiple implementations of that with different T's in to this "handler". You get cleaner code if you layer your higher orders of logic in my experience.
@MortvmMM
@MortvmMM Год назад
put them in the domain core, or domain interfaces 🙂
@MilanJovanovicTech
@MilanJovanovicTech Год назад
Agree!
@alfredorodriguez598
@alfredorodriguez598 Год назад
I use CQRS and inject the dbContext interface directly into the handler. I don't like to use repositories if I use CQRS, it seems redundant to me.
@nicolasundiano8406
@nicolasundiano8406 Год назад
but how yo can constraint the add, update, delete methods to be an aggregate root?
@MilanJovanovicTech
@MilanJovanovicTech Год назад
That's a perfectly fine approach. There's never "one" right answer
@karthikeyanR87
@karthikeyanR87 Год назад
Referencing domain in Persistence will not break Clean Architecture
@MilanJovanovicTech
@MilanJovanovicTech Год назад
I agree
@joga_bonito_aro
@joga_bonito_aro Год назад
Trick question... You shouldn't use repositories at all
@MilanJovanovicTech
@MilanJovanovicTech Год назад
Not necessarily, but at least have a good reason for using them.
Далее
Думайте сами блин
18:15
Просмотров 663 тыс.
Write cleaner APIs in .NET 7 with MediatR
15:25
Просмотров 59 тыс.
How To Use Domain-Driven Design In Clean Architecture
30:27
The Beginner's Guide to Clean Architecture
13:19
Просмотров 28 тыс.
The Only .NET Scheduler You Should Be Using!
16:38
Просмотров 54 тыс.
Максим Морев - DDD в действии
51:54
"Clean Architecture" and indirection. No thanks.
25:06