No video

Make Your Business Rules Cleaner With Fluent Validation

  Рет қаралды 27,973

Milan Jovanović

Milan Jovanović

Күн бұрын

Пікірлер: 93
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Want to master Clean Architecture? Go here: bit.ly/3PupkOJ Want to unlock Modular Monoliths? Go here: bit.ly/3SXlzSt
@djoka4203
@djoka4203 Жыл бұрын
Even if i won't watch it immediately I must enter, just to smash that like button for our good friend Milan. Hvala ti brate!
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Haha, thanks a lot, brate! 😁
@GiovanniCostagliola
@GiovanniCostagliola Жыл бұрын
Hi Milan, thanks for sharing. My two cents: Command validation pertain to the Behavioural layer of the application and should be costrained to that layer. Assumed your stack, the best and elegant approach is to implement an CommandValidationBehaviour into the Mediatr pipeline. This middleware would throw a CommandValidationException that can be further processed by the upstream layers, presentation in particular. MOREOVER, and this is the point, you can also (and SHOULD) implement a (synchronous and "singletoned") validation at Request layer. This latter validation layer is to guard from malformed user request (aka 404): stateless, light, focused on syntax rather then semantics, and very performant (the "why" of singleton). while the former, is to protect from business violation rules (aka 401, 400 and so on…): deeper and semanthics reach. A bit of duplication may arise but in complex application, where you reuse commands in multiple use cases, this design is very scalable. The point to recognize is that validation is a topic that you should address at every layer of your onion… Thanks for your time
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
I agree, and I already have a video about implementing the Validation pipeline behavior. How would the request validation be implemented? What's your approach?
@m5s10
@m5s10 Жыл бұрын
I was just about to write that you should index database calls that you use in validator, but then you showed the ef configuraiton. Nice work :)
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
I already knew what a few people were going to say 😁
@Andy01010
@Andy01010 Жыл бұрын
Would be nice to have these rules in the domain layer, to really encapsulate the domain logic where it belongs
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
How would you do it?
@gianlucalocri
@gianlucalocri Жыл бұрын
I know... I am pedantic, but I am trying to understand and your videos are a gold mine. That said, why put the validation in the application layer? It seems that email uniqueness is a business rule, so validation must occur in the domain layer. Am i missing something? Thanks for your patience Milan.
@_JustBeingCasual
@_JustBeingCasual Жыл бұрын
I think in the Persistance 'CustomerConfiguration' he already assigned it to be unique, so duplicates can never happen; to be honest I don't like the idea of giving the model on creation a repository and then do a 'check', if it already exists (from performance perspective also), but I did like the idea to enforce everything. I don't think a repository belongs in a model, anyways because there are probably ways to get DI working in there.
@pilotboba
@pilotboba Жыл бұрын
So you want to inject persistence into your domain layer? If not, how would you enforce this in the domain? Not sure I like those dragons.
@gianlucalocri
@gianlucalocri Жыл бұрын
@@pilotboba I hope the above comment will not be banned for containing two links. If it is so, please tell me so I can provide information about where to find the resources without providing the direct URL.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
It's the everlasting debate of domain purity vs completeness vs performance You can't have all three.
@fredericmerouze4876
@fredericmerouze4876 Жыл бұрын
great video milan ! for my projects, i use the pipeline behavior with mediatr to doesn't have redundancy in my handle method :).
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Yeah, I already have a video about that
@christianmorales3496
@christianmorales3496 Жыл бұрын
should we use fluentvalidation for the domain layer? in this case it is used as an "application rule" right? How do we differentiate business rules and application rules?
@efimov90
@efimov90 Жыл бұрын
Very good question, but shouldn't domain layer be referencesless?
@moviedomof
@moviedomof Жыл бұрын
Buena sugerencia : Seria los mismo que una API comun de streeming Task UploadFile() con var file = Request.Form.Files[0];. Luego Internamente en la capa de Infra un FTPWrapper que lo envie al FTP server. (Obtions-> previouslyconfigurated. not harcoded ajjaja )
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Application is also part of the Core (where Domain also is) so it's one and the same
@bbualdo
@bbualdo 2 ай бұрын
You are just like MS Docs. Assuming that everyone is an expert already and just writing code without explaination.
@MilanJovanovicTech
@MilanJovanovicTech 2 ай бұрын
Yes, I assume that my audience has some prior experience
@29Aios
@29Aios Жыл бұрын
И вообще, что это за подход - проверять уникальность email перед вставкой юзера ? Нужно иметь уникальный ключ в БД по email, попробовать вставить в транзакции, и затем добавлять юзера, а если такой email уже есть, то все откатить - хотя email просто частный случай, а более общий - валидация на уровне БД, вставляем, не получается по уникальному индексу, откатываем что сделали до этого. Т.е. в нагруженных системах, между проверкой уникальности и вставкой проходит время, хоть и миллисекунды, но это надо учитывать - и единственный вариант, индекс, транзакции - это если еще что-то связанное вставляем.
@Maxim.Shiryaev
@Maxim.Shiryaev Жыл бұрын
Или блокировка всей таблицы с момента чтения до момента записи нового email. Что в высоконагруженной системе невозможно.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Pessimistic vs optimistic approach
@29Aios
@29Aios Жыл бұрын
@@MilanJovanovicTech Верно. Но сам подход должен быть пессимистичным, и все должно быть решено на уровне БД, а не клиента БД. С email, оптимистичный подход может сработать, и за 10 лет никогда в такую ошибку можно не попасть, даже в высоконагруженных системах, но в других случаях это невалидно, и если уж взялись учить, то учите правильно.
@CodeWithAnup
@CodeWithAnup Жыл бұрын
how to export the metadata of entity validation rules into Json for front end. The problem I am trying to solve here, when our client side is SPA (Angular/React) we have to write same validation logic twice in back end and also in front end. I wan't to create a unified validation both back end & front end. So that I only write validation rules once. For example I wan't to export rules in following format : { "Name": { "NotEmpty": true, "MinLength": 3, "MaxLength": 200 } ... .... }
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
I don't see much value in that... You'll write it twice (once...) and forget about it
@abdelrahmananwar885
@abdelrahmananwar885 7 ай бұрын
keep up the great content
@MilanJovanovicTech
@MilanJovanovicTech 7 ай бұрын
Will do!
@javiermayorga9857
@javiermayorga9857 11 ай бұрын
Hi Milan, thanks for your amazing videos I learn a lot from them. I do have a question regarding of how Can keep my service class clean and elegant when I need to implement more than 1 validators in the constructor?
@MilanJovanovicTech
@MilanJovanovicTech 11 ай бұрын
You can inject IEnumerable and validate all of them - but at that point you're better off using some sort of middleware
@Paul-uo9sv
@Paul-uo9sv 8 ай бұрын
thanks buddy. Good stuff right here.
@MilanJovanovicTech
@MilanJovanovicTech 8 ай бұрын
Appreciate it!
@dragannikolic568
@dragannikolic568 Жыл бұрын
Its very helpful to follow your videos. I see here many are bugging you with wanting some ideal code in the video. I see that I can build application together with you and learn and improve knowledge. So once again, great and very helpful approach in videos content, the plan on what you publish with compromise and refactoring in later videos. Thx. a lot. And by the way you have call to repo by passing email where name should be passed in comand handler class. Just wanted to brag that I'm closely watching and implementing your examples 😉
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
It's funny how everyone expects me to implement a complete production ready application in a 10-min video, and I only want to focus on something specific while disregarding everything else. As long as people like you can see the value, that's all I care about. Yeah, the double Email in the constructor pissed me off but I didn't want to re-record to fix it 😅
@dragannikolic568
@dragannikolic568 Жыл бұрын
@@MilanJovanovicTech We wouldn't be able to learn and apply new knowledge if you put all at once by omitting showing parts of the code and cutting explanations. Gradual approach is the only way for us who do not know everything already, or we just don't need to play smart. I use to watch your video one day, then implement it myself next day by checking the video while developing. This works for me. I suppose this is why you get so many new followers. First thing that I thought was the same. He must be crazy about rerecording that trivial typo 😁 Wish you all the best!
@gonzalorf
@gonzalorf Жыл бұрын
How do you handle concurrency? Is it possible to receive two requests using the same email at the same time without being aware of the other attempt to save a customer with that email?
@gonzalorf
@gonzalorf Жыл бұрын
I didn't see the part where you set an index. Thank you.
@29Aios
@29Aios Жыл бұрын
@@gonzalorf Sure, there should be used another approach - insert email into a table with unique email column index, and also insert customer/user in one transaction.
@Maxim.Shiryaev
@Maxim.Shiryaev Жыл бұрын
The idea to check uniqueness before an attempt to store new email into the database is dangerous. Either you should lock entire table on reading or you should catch a key violation exception on writing.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Unique constraint at the DB
@29Aios
@29Aios Жыл бұрын
Then you do not need to check if an email exists, just insert it, and catch key violation, first call is not needed.
@efimov90
@efimov90 Жыл бұрын
Isn't it breaking dependency indirection? I mean you define concrete implementation of validation right in application layer. Or is it a compromise?
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
A compromise of sorts, just showcasing what's possible
@degrauxmaxence8871
@degrauxmaxence8871 Жыл бұрын
What the benefit of validate the command in the API rather than in the handler ? If we use the same handler in 2 differents route, we'll duplicate the code ? (maybe too specific case ?) Anyway, thanks for sharing this !
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Just an example, you can place it in a pipeline behavior
@orange_cat_energy
@orange_cat_energy 6 ай бұрын
CreateCommand validations are almost the same for UpdateCommand validations, how to handle that?
@MilanJovanovicTech
@MilanJovanovicTech 6 ай бұрын
Write them twice 🤷‍♂️
@emmanuelpolancojimenez7807
@emmanuelpolancojimenez7807 Жыл бұрын
Why do you not use a Pipeline Behavior to add a validation layer before the handler. I think that with that the handler will be much cleaner
@pilotboba
@pilotboba Жыл бұрын
HE commented about that at the very end of the video.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Just an example + I already have a video about that
@gabrielordonez7876
@gabrielordonez7876 Жыл бұрын
Hi Milan, I would like to know what is the theme you use in Visual Studio and if you plan to publish a course in the future?
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
VS dark theme + R# syntax highlighting
@_JustBeingCasual
@_JustBeingCasual Жыл бұрын
Can't you add the command validator to the createcustomercommandhandler instead of the controller/route? That it stays together and will be explicit? That can either be together in that file or as DI. Thanks for the video :-)
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Commands don't return a value, so didn't want to bother with implementing a flow for that. It was easier to just place it in the endpoint to illustrate the point
@29Aios
@29Aios Жыл бұрын
Да ну нафиг, как-то сложно для простой валидации. ЗЫ. Работал на одном проекте, и там то-же все было сделано на командах/запросах, причем еще и в генериках, ужас - чтобы разобраться в коде, приходилось искать имплементацию за 3 шага, место одного, а там таких было тысячи. В итоге проект пришлось спасть, т.к. при разрастании он стал неподдерживаемым (not-maintainable). Есть-же принцип KISS - ну зачем усложнять на ровном месте ???
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Just an example of using async validation with FluentValidation, doesn't have to be how you do it
@29Aios
@29Aios Жыл бұрын
@@MilanJovanovicTech Понятно, что это пример как можно сделать проекту плохо - завести кучу всяких интерфейсов, абстракций, которая в будущем, казалось бы, может что-то принести, а по факту все очень усложняет - разработчики вынуждены исследовать код, скакать по реализациям интерфейсов и т.д. Хотя, чего проще, просто проверить email в сервисе юзеров при его добавлении ? KISS - Keep it simple s****d
@I_Am_Dani
@I_Am_Dani Жыл бұрын
Can u Teach File Uploader Service With Ftp Type in Cqrs pattern ?
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Unlikely
@SuperLabreu
@SuperLabreu Жыл бұрын
Hi, Just curious on how you guys use these db checks without hints that try to lock the table...for instance, with the default transaction level for sql server, how can you ensure that 2 parallel requests won't end up duplicating the records with the same email?
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
There's a unique index on the DB level, only one of them can insert the record
@SuperLabreu
@SuperLabreu Жыл бұрын
@@MilanJovanovicTech if that is the case, what's the purpose of the db check in code? It's just slowing down your app, no?
@saulolima6874
@saulolima6874 Жыл бұрын
Thx
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
No problem!
@MahmoudSaed98
@MahmoudSaed98 3 ай бұрын
why Add Customer Method Not Async ?
@MilanJovanovicTech
@MilanJovanovicTech 3 ай бұрын
Doesn't need to be 🤔
@MahmoudSaed98
@MahmoudSaed98 3 ай бұрын
@@MilanJovanovicTech Explain to me why please
@imaneldegwy1478
@imaneldegwy1478 10 ай бұрын
how can we validate with more than one parameter? can u show me sample code for that
@MilanJovanovicTech
@MilanJovanovicTech 10 ай бұрын
Just write each validation separately
@CRBarchager
@CRBarchager Жыл бұрын
12:30 What extension/setttings do you use to show all the current values to the right of your code?
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
No idea to be honest, could be R#
@hemantpanchal8087
@hemantpanchal8087 3 ай бұрын
How to pass multilingual message in fluent validation without .resx approach. I have list of language specific error messages stored in database.
@MilanJovanovicTech
@MilanJovanovicTech 3 ай бұрын
Not sure, what do the docs say?
@Zisane21
@Zisane21 5 ай бұрын
How would you convert Fluent Validation errors to ProblemDetails object?
@MilanJovanovicTech
@MilanJovanovicTech 5 ай бұрын
This + a global exception handler: www.milanjovanovic.tech/blog/cqrs-validation-with-mediatr-pipeline-and-fluentvalidation
@algsavi
@algsavi 3 ай бұрын
If its a business rule, why isn't it on domain layer?
@MilanJovanovicTech
@MilanJovanovicTech 3 ай бұрын
How would you enforce it in the Domain layer?
@synthaistudio
@synthaistudio Жыл бұрын
Yoo Milan! It's either you're too fast or I'm too slow "compiling" what you are writing there. Adjust your mediator brooo, allow the stupid me to catch up 😢
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Yeah, I kind of assume people have some idea of what I'm talking about. I'm not really "beginner" friendly
@gp390
@gp390 Жыл бұрын
Are you from Croatia? 🙂
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Serbia
@mustafahaider9115
@mustafahaider9115 5 ай бұрын
man I am new to the channel and every time I watch a video I feel like a stupid potato cuz u r always using things u already built and I just don't know where to start like what is the Error class what is a pipeline behavior I feel so lost.
@MilanJovanovicTech
@MilanJovanovicTech 5 ай бұрын
Here's the Result class: gist.github.com/m-jovanovic/aa25b1ae424c985ff8ae696a79b6fe6e But try to focus on the concepts, the implementation details can change
@harrisonwell1719
@harrisonwell1719 Жыл бұрын
You explain things way too fast and jumping from on one thing to another, I would like you to slow down a bit and explain things properly
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
I generally expect viewers to be somewhat familiar with the topics. Unless it's a beginner video - and this one isn't
@harrisonwell1719
@harrisonwell1719 Жыл бұрын
@@MilanJovanovicTech fair enough
@techpc5453
@techpc5453 Жыл бұрын
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
*pink glove*
How To Make Your API Idempotent To Stop Duplicate Requests
14:26
Milan Jovanović
Рет қаралды 24 М.
Fix Your Controllers By Refactoring To Minimal APIs
14:56
Milan Jovanović
Рет қаралды 38 М.
黑天使遇到什么了?#short #angel #clown
00:34
Super Beauty team
Рет қаралды 43 МЛН
لااا! هذه البرتقالة مزعجة جدًا #قصير
00:15
One More Arabic
Рет қаралды 51 МЛН
Doing This Instead Of Studying.. 😳
00:12
Jojo Sim
Рет қаралды 35 МЛН
Please Help Barry Choose His Real Son
00:23
Garri Creative
Рет қаралды 21 МЛН
Making A WebSocket Server With .NET 8🧑‍💻  [FULLSTACK 2024 VIDEO 1]
18:43
Alex's Dev Den 👨‍💻
Рет қаралды 9 М.
What are Business Rules? It's not this.
10:58
CodeOpinion
Рет қаралды 29 М.
Владимир Хориков - Validation and DDD
45:01
Конференция ArchDays
Рет қаралды 11 М.
I Built a Neural Network in C# From Scratch. Here’s What I Learned…
18:12
Vertical Slice Architecture Project Setup From Scratch
22:43
Milan Jovanović
Рет қаралды 56 М.
黑天使遇到什么了?#short #angel #clown
00:34
Super Beauty team
Рет қаралды 43 МЛН