Make Your Business Rules Cleaner With Fluent Validation

Поделиться
HTML-код
  • Опубликовано: 22 авг 2024

Комментарии • 93

  • @MilanJovanovicTech
    @MilanJovanovicTech  Год назад +4

    Want to master Clean Architecture? Go here: bit.ly/3PupkOJ
    Want to unlock Modular Monoliths? Go here: bit.ly/3SXlzSt

  • @djoka4203
    @djoka4203 Год назад +3

    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!

  • @GiovanniCostagliola
    @GiovanniCostagliola Год назад +5

    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 Год назад +1

    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 :)

  • @Andy01010
    @Andy01010 Год назад +3

    Would be nice to have these rules in the domain layer, to really encapsulate the domain logic where it belongs

  • @gianlucalocri
    @gianlucalocri Год назад +4

    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 Год назад +1

      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  Год назад +1

      It's the everlasting debate of domain purity vs completeness vs performance
      You can't have all three.

  • @fredericmerouze4876
    @fredericmerouze4876 Год назад +3

    great video milan ! for my projects, i use the pipeline behavior with mediatr to doesn't have redundancy in my handle method :).

  • @christianmorales3496
    @christianmorales3496 Год назад +4

    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 Год назад +1

      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

  • @CodeWithAnup
    @CodeWithAnup Год назад +2

    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

  • @javiermayorga9857
    @javiermayorga9857 11 месяцев назад +1

    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

  • @orange_cat_energy
    @orange_cat_energy 6 месяцев назад +1

    CreateCommand validations are almost the same for UpdateCommand validations, how to handle that?

  • @gonzalorf
    @gonzalorf Год назад +3

    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 Год назад +1

      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 Год назад +1

      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.

  • @dragannikolic568
    @dragannikolic568 Год назад +1

    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  Год назад +2

      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!

  • @abdelrahmananwar885
    @abdelrahmananwar885 7 месяцев назад

    keep up the great content

  • @29Aios
    @29Aios Год назад +2

    И вообще, что это за подход - проверять уникальность email перед вставкой юзера ? Нужно иметь уникальный ключ в БД по email, попробовать вставить в транзакции, и затем добавлять юзера, а если такой email уже есть, то все откатить - хотя email просто частный случай, а более общий - валидация на уровне БД, вставляем, не получается по уникальному индексу, откатываем что сделали до этого. Т.е. в нагруженных системах, между проверкой уникальности и вставкой проходит время, хоть и миллисекунды, но это надо учитывать - и единственный вариант, индекс, транзакции - это если еще что-то связанное вставляем.

    • @Maxim.Shiryaev
      @Maxim.Shiryaev Год назад +1

      Или блокировка всей таблицы с момента чтения до момента записи нового email. Что в высоконагруженной системе невозможно.

    • @MilanJovanovicTech
      @MilanJovanovicTech  Год назад

      Pessimistic vs optimistic approach

    • @29Aios
      @29Aios Год назад

      @@MilanJovanovicTech Верно. Но сам подход должен быть пессимистичным, и все должно быть решено на уровне БД, а не клиента БД.
      С email, оптимистичный подход может сработать, и за 10 лет никогда в такую ошибку можно не попасть, даже в высоконагруженных системах, но в других случаях это невалидно, и если уж взялись учить, то учите правильно.

  • @Paul-uo9sv
    @Paul-uo9sv 8 месяцев назад

    thanks buddy. Good stuff right here.

  • @efimov90
    @efimov90 Год назад +1

    Isn't it breaking dependency indirection? I mean you define concrete implementation of validation right in application layer. Or is it a compromise?

  • @MahmoudSaed98
    @MahmoudSaed98 3 месяца назад +1

    why Add Customer Method Not Async ?

  • @emmanuelpolancojimenez7807
    @emmanuelpolancojimenez7807 Год назад +1

    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  Год назад +1

      Just an example + I already have a video about that

  • @gabrielordonez7876
    @gabrielordonez7876 Год назад +1

    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?

  • @degrauxmaxence8871
    @degrauxmaxence8871 Год назад +1

    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 !

  • @imaneldegwy1478
    @imaneldegwy1478 10 месяцев назад +1

    how can we validate with more than one parameter?
    can u show me sample code for that

  • @I_Am_Dani
    @I_Am_Dani Год назад +2

    Can u Teach File Uploader Service With Ftp Type in Cqrs pattern ?

  • @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.

  • @29Aios
    @29Aios Год назад +1

    Да ну нафиг, как-то сложно для простой валидации.
    ЗЫ. Работал на одном проекте, и там то-же все было сделано на командах/запросах, причем еще и в генериках, ужас - чтобы разобраться в коде, приходилось искать имплементацию за 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

  • @SuperLabreu
    @SuperLabreu Год назад +1

    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  Год назад +1

      There's a unique index on the DB level, only one of them can insert the record

    • @SuperLabreu
      @SuperLabreu Год назад +1

      @@MilanJovanovicTech if that is the case, what's the purpose of the db check in code?
      It's just slowing down your app, no?

  • @Zisane21
    @Zisane21 5 месяцев назад

    How would you convert Fluent Validation errors to ProblemDetails object?

    • @MilanJovanovicTech
      @MilanJovanovicTech  5 месяцев назад +1

      This + a global exception handler: www.milanjovanovic.tech/blog/cqrs-validation-with-mediatr-pipeline-and-fluentvalidation

  • @_JustBeingCasual
    @_JustBeingCasual Год назад +3

    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  Год назад +1

      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

  • @algsavi
    @algsavi 3 месяца назад

    If its a business rule, why isn't it on domain layer?

  • @saulolima6874
    @saulolima6874 Год назад +1

    Thx

  • @synthaistudio
    @synthaistudio Год назад +1

    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

  • @CRBarchager
    @CRBarchager Год назад

    12:30 What extension/setttings do you use to show all the current values to the right of your code?

  • @gp390
    @gp390 Год назад +1

    Are you from Croatia? 🙂

  • @mustafahaider9115
    @mustafahaider9115 6 месяцев назад +1

    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  6 месяцев назад

      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 Год назад +1

    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 Год назад +1