Really great! I know that in .NET you usually have a separate project for the tests but I like to put them next to the use case on the vertical slice folder. I think that works really well.
@MilanJovanovicTech Great demo thanks, can you please explain how Modular Monolith is different from Vertical Slices? To me till now both architecture look similar
Modular monolith is essentially vertical slices on a bigger scale. The nuances is how we control communication and data isolation between modules. I've made a few videos about modular monoliths, you can check them out.
How will we use the use-case (RegisterUser) in the API? Are all the use-cases supposed to be added to DI container? Till now, I’ve been more familiar with the service driven architecture where we have a service and every “use-case” is a method. The service is added to DI container. I suppose what you have shown, every use-case as a class, is CQRS. If I’m right, I know the concept but not very familiar with it.
Great Milan , but I did notice that you igonre the Mediator is this the new way when using the vertical slices? there no need for the more complication
Great video, I'm going to try this on my next small project. Would you place the implementation of IPasswordHasher and IUserRepository in the Users Folder?
Thanks Milan, (topic apart) Do you recommend GUID on large DB’s?? Any video about that topic?? I’m really concerned about DB performance in the future, I appreciate your point of view.
Hello Milan, having a quick question.. What happens if I have a dependency that is shared between multiple slices? Lets pretend we have an IEmailSender infrastructure dependency, that needs to be used after creating a user, and after placing an order. Where would you place the interface and where would you place the implementation? I have learned a ton with your videos, you are an excellent teacher!! Thank you!!! 🙌
Create an Email/ folder and place it inside. What's important is the direction of dependencies. So the implementation can even be in the same folder. I'm actually working on an interesting article to showcase this.
@MilanJovanovicTech returning access token feels to me more like an infrastucture thing for security at the endpoint level than part of the domain itself, I wonder how its feets in the application/domain use case you created here, what abstraction would you pass in to handle it and what would the Handle method return if not a User object?
i have a quesction witch is : for what type of project we can/should use Vertical Slice Architecture ? for example for Auth service or some business service it's write to user DDD for Auth service and Vertical Slice for business service ?
I think it's not the right way to think about it. CA = this type of project or VSA = this type of project. Rather, think about the qualities that you get by following these principles. Then look at your project, and ask yourself if you need these qualities.
Like you mentioned, the userRepository.Exists approach is subject to a race condition. If you went with the database index approach how would you be able to do your second test where you check for a duplicate? It wouldn't be possible, and you would not be able to capture that part of the business logic on the use case. We can already see that there's already a tradeoff between performance and correctness. In order to capture the business logic at the use case level you either have a race condition with the exists approach, or a hit to your concurrency with the lock approach. If you go with the database unique key/index approach you no longer capture that part of the business logic on the use case and can't test. Any suggestions on how to handle this?
@@gigantedocil We dont need to test for a race condition, really. Just the correctness. I have a video on this coming in a few weeks, but TL;DR. Use an index. Catch the DB exception and return something meaningful to the client.
@@MilanJovanovicTech Yes, but what I meant is that you're leaking business rules to outside the domain/use case if you use the index approach. If not having duplicate emails is a business rule then it should be explicit and enforced at the use case level. Now that business rule is being implemented by the database implementation. The domain is not enforcing this rule anywhere and a blind implementation of the repository would not know to add the unique key to the email column. This is a real life scenario that I think shows well some of the shortcomings of doing these type of abstractions and clean code. You could do it at the use case with a lock like you mention, but you would incur a big performance penalty. Anyways, I'll be waiting for your video, interested in what you have to say.
@@gigantedocil I would say be pragmatic about it. The chance this will occur with two people registering at the very same time with the same email address would be very rare if not nonexistent. Going the extra mile to have a software lock or other domain logic enforced is not worth the effort. Having a db unique index is very cheap compared to anything else. And also, an index is somewhat implied by the emailExists method, why not hit two birds with just one (cheap) stone?
@@ryan-heath 100% agree I was just stating that if you go about clean code in a dogmatic way you'll soon find out that you'll run into many issues such as this. The idea that you can abstract all the dependencies away completely ignoring how their implementations work will soon put you in this sort of situation.
Thank you for this valuable video. I want to ask is it a good approach to start with CA when we are developing MVP and we want to get to market very soon, or start with other simple approaches? Then when we will have time to refactor.
My advice: start with the clean architecture + VSA; and make sure the code coverage of the 'Domain' and 'Application' layers is above 70-80%. Given the tutorials and video's here this is not a huge upfront cost, but will allow you to iterate fast AND reliable over the MVP. That way you'll be able to grow your MVP into a real production application and not stack up lots of tech debt. Because when the MVP takes off and it is time to grow your market share, you do not want to be in a (bad) place where the only solution is a (huge) refactor (or even rewrite). That will kill your product fast.
@@MilanJovanovicTech is there any other way? BTW even though I'm a typescript developer I have found your content very helpful. I would really appreciate it if you can do a more complete example, with more than one entity and more use cases, thanks
Homework assignment?! I didn’t know I was enrolled into a course … 😅 Great video! Also agreeing with use of primary constructors. Nobody will change the input parameters!
Good simple video, simple comment though: You are leaking security info by returning "The email is already in use". With a datadump of hacked email/password combos, one could hack into the system. I understand this is a simple tutorial video, and you can't capture all the best practices (like doing this TDD style would make it even better)
Even large social media networks return info about something like that. Just tested it with Facebook, for example. We could return something more generic like 'That email address is not available'
@@MilanJovanovicTech Big companies will probably have other tech to negate the problem (like rate limiting, and other detection methods) and will not allow to data mine their system. We negated this problem by adjusting our flow, as when a user registers we would send an e-mail with a unique link to complete the registration. So 1) the attacker can never know it the email is registered and 2) the user would be made aware his account is potentially exposed. But again, I would not expect you to go all this way or explain it in a nice simple tutorial video.
What a shady practice that you highlight incorrect statement under my comment. "wow that’s a bad video with wrong information. " - @ryan-heath you were first with talk is cheap comment and now you doing exactly same. Abstraction brings cost, oop is making gaps in memory allocation which is not cpu friendly. Thats video show exactly that. "Clean code" is at some point a way that it looks like "organized code" but its in cost of perfomance. If you make each request as seperate class, its huge allocation cost in real time systems, in big scale you need to think in different way than just i like this "code visual".
@@ryan-heath your comment is cheap and useless. "Clean" Code, Horrible Performance - Molly Rocket type in search bar above, all you need to know is there.
@@frontalachivment3604 wow that’s a bad video with wrong information. The comments are disabled, that’s a telling fact … The guy is doing micro measurements and based on those timings he says to never ever use those rules. 🤦♂️ “Clean code” are guide lines as I see it. Use it where it seems fit. Generalizing to never ever use polymorphism becasuse it is “slow” is just laughable. 99.9% of the code the average Joe is writing doesn’t need to be highly optimized code because the slowness is in the IO not in the CPU. From that POV better have maintainable code then super optimized code that only the Einsteins will comprehend and even they are hesitant to modify or extend it …
Simplify your development process - download my free Clean Architecture template: bit.ly/3Andaly
Do you use Vertical Slice Arch in course?
@@stasasekulic6917 Not explicitly. But everything is organized around slices. There's a respective slice in each layer.
Really great! I know that in .NET you usually have a separate project for the tests but I like to put them next to the use case on the vertical slice folder. I think that works really well.
So your "use case" project is also a test project? 🤔
@@MilanJovanovicTech Yes. You can exclude the dlls and the files for the release build if you are worried of having them there.
Great video.Thank you for your work!
Thanks for watching!
love your content! Could you make a tutorial on generating presigned URLs and uploading files to an S3 bucket. Thanks for all your great work!"
Can do, that's a great topic!
@@MilanJovanovicTech
Thank you so much it's been a 3 days stuck on it i get the url but when i try upload to s3 always fail😢😢😢
Would you generally recommend to create your own JWT implementation rather than using the bearertoken services from identity ?
No, I recommend using an Identity Provider. But it doesn't hurt to know how things work under the hood. :)
@MilanJovanovicTech Great demo thanks, can you please explain how Modular Monolith is different from Vertical Slices?
To me till now both architecture look similar
Modular monolith is essentially vertical slices on a bigger scale.
The nuances is how we control communication and data isolation between modules.
I've made a few videos about modular monoliths, you can check them out.
agreed w/ leaving out DDD when desired as its not a requirement of CA/VS
👉
How will we use the use-case (RegisterUser) in the API? Are all the use-cases supposed to be added to DI container?
Till now, I’ve been more familiar with the service driven architecture where we have a service and every “use-case” is a method. The service is added to DI container. I suppose what you have shown, every use-case as a class, is CQRS. If I’m right, I know the concept but not very familiar with it.
You're exactly on point there
Thanks
Sure thing :)
amazing Video
Thanks!
Great Milan , but I did notice that you igonre the Mediator is this the new way when using the vertical slices? there no need for the more complication
You can always introduce MediatR, no problem there.
Great video, I'm going to try this on my next small project. Would you place the implementation of IPasswordHasher and IUserRepository in the Users Folder?
Yes, we can create an /Infra folder to hold the implementations? Whatever makes sense.
Thanks Milan, (topic apart) Do you recommend GUID on large DB’s?? Any video about that topic??
I’m really concerned about DB performance in the future, I appreciate your point of view.
Check out this video: th-cam.com/video/-f03gnTreCU/w-d-xo.html
Hello Milan, having a quick question..
What happens if I have a dependency that is shared between multiple slices?
Lets pretend we have an IEmailSender infrastructure dependency, that needs to be used after creating a user, and after placing an order.
Where would you place the interface and where would you place the implementation?
I have learned a ton with your videos, you are an excellent teacher!! Thank you!!! 🙌
Create an Email/ folder and place it inside. What's important is the direction of dependencies. So the implementation can even be in the same folder. I'm actually working on an interesting article to showcase this.
@@MilanJovanovicTech Thank you very much! that makes sense :) and I really appreciate your prompt response!!
Fantastic
Thank you! Cheers!
@MilanJovanovicTech returning access token feels to me more like an infrastucture thing for security at the endpoint level than part of the domain itself, I wonder how its feets in the application/domain use case you created here, what abstraction would you pass in to handle it and what would the Handle method return if not a User object?
It's use case as any other. Why wouldn't it be? The handle method can just return a simple string representing the access token.
i have a quesction witch is : for what type of project we can/should use Vertical Slice Architecture ? for example for Auth service or some business service it's write to user DDD for Auth service and Vertical Slice for business service ?
I think it's not the right way to think about it. CA = this type of project or VSA = this type of project. Rather, think about the qualities that you get by following these principles. Then look at your project, and ask yourself if you need these qualities.
Like you mentioned, the userRepository.Exists approach is subject to a race condition. If you went with the database index approach how would you be able to do your second test where you check for a duplicate? It wouldn't be possible, and you would not be able to capture that part of the business logic on the use case. We can already see that there's already a tradeoff between performance and correctness. In order to capture the business logic at the use case level you either have a race condition with the exists approach, or a hit to your concurrency with the lock approach. If you go with the database unique key/index approach you no longer capture that part of the business logic on the use case and can't test. Any suggestions on how to handle this?
@@gigantedocil We dont need to test for a race condition, really. Just the correctness. I have a video on this coming in a few weeks, but TL;DR. Use an index. Catch the DB exception and return something meaningful to the client.
@@MilanJovanovicTech Yes, but what I meant is that you're leaking business rules to outside the domain/use case if you use the index approach. If not having duplicate emails is a business rule then it should be explicit and enforced at the use case level. Now that business rule is being implemented by the database implementation. The domain is not enforcing this rule anywhere and a blind implementation of the repository would not know to add the unique key to the email column. This is a real life scenario that I think shows well some of the shortcomings of doing these type of abstractions and clean code. You could do it at the use case with a lock like you mention, but you would incur a big performance penalty. Anyways, I'll be waiting for your video, interested in what you have to say.
@@gigantedocil I would say be pragmatic about it.
The chance this will occur with two people registering at the very same time with the same email address would be very rare if not nonexistent.
Going the extra mile to have a software lock or other domain logic enforced is not worth the effort.
Having a db unique index is very cheap compared to anything else.
And also, an index is somewhat implied by the emailExists method, why not hit two birds with just one (cheap) stone?
@@ryan-heath 100% agree I was just stating that if you go about clean code in a dogmatic way you'll soon find out that you'll run into many issues such as this. The idea that you can abstract all the dependencies away completely ignoring how their implementations work will soon put you in this sort of situation.
Thank you for this valuable video.
I want to ask is it a good approach to start with CA when we are developing MVP and we want to get to market very soon, or start with other simple approaches?
Then when we will have time to refactor.
VSA + some sane abstractions works great. I think with a few more videos in this series it'll start to make sense.
My advice: start with the clean architecture + VSA; and make sure the code coverage of the 'Domain' and 'Application' layers is above 70-80%. Given the tutorials and video's here this is not a huge upfront cost, but will allow you to iterate fast AND reliable over the MVP.
That way you'll be able to grow your MVP into a real production application and not stack up lots of tech debt. Because when the MVP takes off and it is time to grow your market share, you do not want to be in a (bad) place where the only solution is a (huge) refactor (or even rewrite). That will kill your product fast.
cool video
Thanks!
I personally perfer this pattern it is easily understandable.
Cool 😁
Could you share the repo?
you need to pay money for this
Grab the (free) template from the pinned comment
@@MilanJovanovicTech You are the best!
@@MilanJovanovicTech thank you dear sir
Does this mean that I will have a lot of classes with just a single method in it?
Yes, kinda. That's what a use case is - one piece of functionality.
@@MilanJovanovicTech is there any other way?
BTW even though I'm a typescript developer I have found your content very helpful.
I would really appreciate it if you can do a more complete example, with more than one entity and more use cases, thanks
Homework assignment?!
I didn’t know I was enrolled into a course … 😅
Great video!
Also agreeing with use of primary constructors. Nobody will change the input parameters!
Is that too much to ask for? I can't be doing all the work here 😁
Good simple video, simple comment though: You are leaking security info by returning "The email is already in use".
With a datadump of hacked email/password combos, one could hack into the system.
I understand this is a simple tutorial video, and you can't capture all the best practices (like doing this TDD style would make it even better)
Even large social media networks return info about something like that. Just tested it with Facebook, for example. We could return something more generic like 'That email address is not available'
@@MilanJovanovicTech Big companies will probably have other tech to negate the problem (like rate limiting, and other detection methods) and will not allow to data mine their system.
We negated this problem by adjusting our flow, as when a user registers we would send an e-mail with a unique link to complete the registration. So 1) the attacker can never know it the email is registered and 2) the user would be made aware his account is potentially exposed. But again, I would not expect you to go all this way or explain it in a nice simple tutorial video.
We need a special price for Latin America. the price for 1 course is our salary 😂
There already is, check the course page on my website
What a shady practice that you highlight incorrect statement under my comment. "wow that’s a bad video with wrong information. " - @ryan-heath you were first with talk is cheap comment and now you doing exactly same. Abstraction brings cost, oop is making gaps in memory allocation which is not cpu friendly. Thats video show exactly that. "Clean code" is at some point a way that it looks like "organized code" but its in cost of perfomance. If you make each request as seperate class, its huge allocation cost in real time systems, in big scale you need to think in different way than just i like this "code visual".
Would've been best to keep under the original comment 🤷♂️
This channel is for serious people where we discuss ideas like adults.
Clean code, horrible perfomance.
What makes it less performant? What would you change to make it more performant?
@@frontalachivment3604 talk is cheap 🙃
@@ryan-heath your comment is cheap and useless. "Clean" Code, Horrible Performance - Molly Rocket type in search bar above, all you need to know is there.
@@frontalachivment3604 wow that’s a bad video with wrong information. The comments are disabled, that’s a telling fact …
The guy is doing micro measurements and based on those timings he says to never ever use those rules. 🤦♂️
“Clean code” are guide lines as I see it. Use it where it seems fit. Generalizing to never ever use polymorphism becasuse it is “slow” is just laughable.
99.9% of the code the average Joe is writing doesn’t need to be highly optimized code because the slowness is in the IO not in the CPU.
From that POV better have maintainable code then super optimized code that only the Einsteins will comprehend and even they are hesitant to modify or extend it …
@@ryan-heath lol, do you know why games use ecs architecture instead of oop??
Awesome and useful content thank you Milan
Sure thing