Functional Programming With C# Using Railway-Oriented Programming

แชร์
ฝัง
  • เผยแพร่เมื่อ 20 ก.ย. 2024

ความคิดเห็น • 119

  • @MilanJovanovicTech
    @MilanJovanovicTech  ปีที่แล้ว +7

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

  • @soverain
    @soverain ปีที่แล้ว +5

    Functional programming, yes! Very excited to see more on this topic!

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว

      I'm loving the community response, definitely going to make more videos 😁

  • @aToa5241
    @aToa5241 ปีที่แล้ว +13

    Fantastic video in such an interesting topic.
    Looking forward to your advanced videos on this - there is not a lot of content out there (even paid content) on functional programming in C#, and I think the benefits of using it are huge. There is the amazing book Functional Programming in C# by Enrico Buonanno (now with a 2nd edition), and a nice blog from Mark Seemann.
    However, at the end of the day, C# is not a functional-first programming language, and I have realised that either I move to another language, or I acept those imperative if statements.
    Your video shows a practical and clean way to turn an imperative method to a declarative one. Railway-oriented programming looks very interesting and practical. Thank you for sharing, Milan - another excellent video!

    • @AboutCleanCode
      @AboutCleanCode ปีที่แล้ว +4

      I know what you mean - on the other hand more and more functional concepts get introduced in C# (e.g. pattern matching, record types). In the mean time you may check out this video th-cam.com/video/IoUsyEyWW0k/w-d-xo.html which closely related to what Milan just presented

    • @aToa5241
      @aToa5241 ปีที่แล้ว +2

      ​@@AboutCleanCode Nice video, thank you for sharing. Looking forward to seeing your videos on Uncle's Bob Clean Architecture as well.

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว +4

      Thank you so much, I'm glad you enjoyed the video! 😁
      I think we need to preach functional programming more as a community, because it will improve our OO design even.

  • @JochenZeischka
    @JochenZeischka ปีที่แล้ว +5

    Hi Milan, thanks for your efforts on this. It would have been nice however to give credit to Scott Wlaschin (F# for fun and profit). He invented the ROP term for this kind of functional composition. Also, it would have been better to take a different example than validation. Chaining functions which can fail would have been a good example.
    Validation however, requires a different composition, because you don't want to stop validating after the first failure, but instead return info on all failures.
    As you indicate, it indeed complicates the consuming code and this should not be underestimated. You did not touch the topic of composing the results, which is pretty important. Especially if some results arrive asynchronously ;-)
    But my main remark is that Scott really should have been given credit in this video. Thanks.

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว +4

      Although I have watched Scott's video, I wasn't at all aware he invented the term, so it was an honest miss on my end.
      As far as coming up with examples, I definitely want to make more videos on ROP so those will surely be covered at some point.

    • @reinhardlackner1925
      @reinhardlackner1925 ปีที่แล้ว +2

      ​@@MilanJovanovicTech watch some more of Scott's videos or maybe Simon Painter's, then you would have known Scott coined the term. Anyways, If you want to go down the rabbit hole of functional C#, watch out for Simon's NDC talks and Enrico Buonnano's book Funktional Programming in C# (Simon's book is still in the making)
      Ah, and I nearly forgot to mention Paul Louth's library Language.Ext which were the goto functional library (if you didn't want to write everyting yourself) before Microsoft started to introduce more and more functional stuff into C#

    • @yohm31
      @yohm31 9 หลายเดือนก่อน

      @MilanJovanovicTech indeed, Language.Ext library offers all the Monad you are dreaming of :)

  • @janovrom
    @janovrom 11 หลายเดือนก่อน +1

    I was trying to wrap my head around monads and some actually useful example 👍 Thank you.

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 หลายเดือนก่อน +1

      Thanks :) Here are a few more videos in the series:
      - th-cam.com/video/zuy2j8vxgYc/w-d-xo.html
      - th-cam.com/video/AVA2mKG4WOc/w-d-xo.html
      - th-cam.com/video/vGkgsduwnc4/w-d-xo.html

  • @christianmarpert3844
    @christianmarpert3844 ปีที่แล้ว +1

    Hey Milan, fantastic introduction to FP. I started watching your DDD serious and then stumbled upon this one. To be honest, I am not yet deeply into C#, am rather programming in Dart for mobile. However, I use FP there to stream line exception handling. There is a well documented package called fpdart, accompanied by some blogs on functional programming. Looks like the Result type in your project corrresponds to the Either type in fpdart, where Left is by convention the Failure, and Right is the Success, whereby only one state is possible. Method chaining can also be done easily.
    Really enjoy your videos, as you explain the topic in a great way!

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว

      Yeah, the Result class is very similar to the Either monad!

    • @christianmarpert3844
      @christianmarpert3844 ปีที่แล้ว

      monad? Scare us all! A monad is a monoid in the category of endofunctors! I got scared by that definition 😁, however its usecases made me calm down 😎

  • @devjonie
    @devjonie ปีที่แล้ว +2

    Wow! Interesting concept. Thanks Milan

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว +2

      It's even more interesting when you add side effects (database calls) and branching on the Result value 😁

  • @kevinaubuchon5979
    @kevinaubuchon5979 ปีที่แล้ว +1

    Good video. These functional programming concepts are difficult to get other team members to embrace though. Some appreciate them, others simply don't understand.

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว +1

      I know, I've had to fight with this myself. Some people will just never embrace FP and that's fine. But what you can do is slowly introduce some functional concepts to your code base that are helpful in general.

    • @tinytownsoftware3837
      @tinytownsoftware3837 ปีที่แล้ว

      This is what I am doing as an architect. Simply introducing Maybe/Option and Result concepts into the codebase are huge improvements and they are not that hard to use.

  • @manuelknorle1457
    @manuelknorle1457 ปีที่แล้ว +4

    A benchmark on this approach would also be very interesting. Which of the two implementations has the greater impact on performance?

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว +6

      Certainly the ROP approach has more allocations, but another benefit is that since ROP is stateless (FP is stateless by design) it's completely parallelizable. In any case, I don't worry to much about this. It's unlikely coding in a functional manner will be your performance bottleneck. That would be on the nanosecond level, which is insignificant compared to a cost of a network round trip.

    • @svorskemattias
      @svorskemattias ปีที่แล้ว

      You can probably make the result class a struct if it's not already.

  • @tonycaesar7934
    @tonycaesar7934 ปีที่แล้ว +1

    Great video. I like the approach. It looks much cleaner and self-documenting. This is especially true when coupled with the Result and static Error approach. Thanks for sharing!

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว

      I left a few questions unanswered, such as returning multiple errors or handling async calls. Going to cover that in a future video.

  • @marklord7614
    @marklord7614 ปีที่แล้ว +1

    Enrico Buonanno makes the best case for functional programming in C# that I've seen. Hopefully the language will support it in a way that makes code more readable when it comes to handing multiple return types (discriminated unions).

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว

      I only wish we had real discriminated unions...

    • @MaximilienNoal
      @MaximilienNoal ปีที่แล้ว

      @@MilanJovanovicTech There's a nuget package that uses a source generator to add the full functionality of discriminated unions to C#. You just have to write [Union] on top of a record declaration.

  • @krccmsitp2884
    @krccmsitp2884 ปีที่แล้ว +1

    Interesting and straightforward as always, keep going! 👍🏼

  • @nicholaspreston9586
    @nicholaspreston9586 9 หลายเดือนก่อน

    I like your Map function. IMO, it's better to have an even more generic extension method that performs a mapping after a null, rather than having to learn Automapper and have to write and manage a bunch of mappers. Been there, done that, and your Func is much better!
    src:
    ///
    /// Map a Source class to a Target
    ///
    public static TResult Map(
    this TSource source,
    Func map
    ) => map(source);

    • @MilanJovanovicTech
      @MilanJovanovicTech  9 หลายเดือนก่อน

      Ideally, the Value of a Result will never be null so no issues there

  • @AboutCleanCode
    @AboutCleanCode ปีที่แล้ว +2

    That reminds me of the Option module from F# which is just a bit more enhanced as it applies full set of "filter-map-reduce" (LinQ style) functions to the Option type which is modeling existence and absence of values ...

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว +2

      All of these methods can be easily coded, and there are libraries out there with rich features for ROP

  • @branislavpetrovic7486
    @branislavpetrovic7486 ปีที่แล้ว +1

    Great intro to ROP!
    Thanks!

  • @DanimoDev
    @DanimoDev ปีที่แล้ว +1

    I actually have a similar solution to this in my own projects, although I didn't know it actually had a name already, I just dubbed it chain validation.
    I quite like this approach personally as you can just chain call validations and it is neater. I also like the result wrapper and will definitely include this, mine doesn't have this and instead throws an exception when a condition fails (I suppose in this context you would say it gets derailed), but your solution is better.

  • @ajirahman5289
    @ajirahman5289 ปีที่แล้ว +2

    Thanks for the demo. Waiting for new videos. Could you share how can do xunit for this railway programming please. Could you please share an intro about what version of c# and the core.

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว +3

      Sure, I can make a short video about writing tests for this.
      All of the videos are C# 11 / .NET 7 going forward.

  • @amitconnect
    @amitconnect ปีที่แล้ว +1

    Good one...liked to learn more about c# functional programming...will you please share some more insight into this?....liked your work....love to learn more from you....thanks 👍

  • @pilotboba
    @pilotboba ปีที่แล้ว +3

    It's clever code but I'm not sure it's less code always. Depends on where you apply it. Also, as you said, it quite reduces the understanding of the code.
    You could probably have written the original code with pattern matching, made it a single expression and it would be just as readable and understandable as well as made into an expression.
    Also, small niggle.
    Linq is not pronounced 'Lin Queue' with two syllables it is pronounced with one syllable like the word LINK. Like the character's name in Legend of Zelda. :)
    Keep up the fun videos.

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว

      I don't think it reduces understanding once you understand the concept - which is simple. I would argue it even improves the ability to reason about a piece of code.

  • @autograf89
    @autograf89 ปีที่แล้ว +1

    Thank you for the video Milan! ROP looks great with linear workflows. Could you elaborate on more complex cases where an object requires to validate multiple parameters on creation?

  • @hugotachoires1721
    @hugotachoires1721 ปีที่แล้ว +1

    Nice video, like every time ! Keep up

  • @chrisbaker5284
    @chrisbaker5284 ปีที่แล้ว +2

    Hi Milan, I've watched many of your videos and I do enjoy them. I would like to point out that you said you finished with less lines of code when in fact, you finished using more than 3 times as much code. (The original method had, effectively, 7 lines of code if you removed the blank lines and the superfluous braces). I am not a fan of using functional styles in an OO language (I don't include LINQ as it is effectively a separate language within a language). I admit that your code is more resuable though, but it's arguable as to how much reuse you will achieve. Reuse could be achieved in an imperative style too.
    I worked for a company where they had taken this style of programming to the nth degree and it was a mess of functions the all did similar things but were meant to be used in differnt situations, everything had similar names wrote bucket loads of code to effectively do null checks and turned the whole thing into a framework. It was difficult to follow and there was no documentation. I know what you may be thinking, that was an example of bad coding style functional or not, well maybe, but these things tend to get abused.
    IMHO if one wants to use a functional style of programming, then I would recommend F# not force an OO language to be Functional. Just my opinion Milan, please do keep up the great work that you are doing.

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว

      This is the same argument as trashy OOP code. 😅
      It's not the paradigm, it's the engineers, in my opinion. There's nothing inherently wrong with doing FP in C#, except you need to write some helper methods in the background to make it work.

    • @chrisbaker5284
      @chrisbaker5284 ปีที่แล้ว

      @@MilanJovanovicTech It is true, bad code is bad code. I just think that one could inherently end up with convoluted and more complex code when forcing an OO language to a Functional paradigm. That's all.

  • @duongphuhiep
    @duongphuhiep 4 หลายเดือนก่อน

    when you (developers) have to write a "forest" of "if" statements (for example an Authorization service which would have to check a lot of different rules and conditions).
    With time, we will add more rules (so more "if") in the forest and our code will become harder to maintain and to "unit test".
    I think that the "Railway programming" pattern might solve this problem. What do you think?

    • @MilanJovanovicTech
      @MilanJovanovicTech  4 หลายเดือนก่อน

      I see ROP as a way to get rid of exceptions - or express failure in a functional way
      The if statements are still "there", they're just abstracted behind the Either monad (Result)

  • @friedrichhayek4862
    @friedrichhayek4862 ปีที่แล้ว +1

    This feels like what you must do in a common Haskell program.

  • @relhimp
    @relhimp ปีที่แล้ว +2

    Two chars: Rx

  • @JustMe-gp4so
    @JustMe-gp4so ปีที่แล้ว +2

    Hello, Milan. Great example, i like it. But i have some thoughts:
    That example works with primitive conditions. So what if we need to process some async assertions that works with db(for example)? I heard about fluent validation, it allows you to inject you service in ctor, write your rule and call MustAsync or CustomAsync.
    What you need to do (or change)in that scenario with extensions to archive that goals?

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว +3

      Yes, it's possible. I'll record a video soon talking about that!

  • @kevinaubuchon5979
    @kevinaubuchon5979 ปีที่แล้ว +1

    Great video.

  • @tore28
    @tore28 2 หลายเดือนก่อน

    You can capture each step into a variable of Ensure and see the state clearly while debugging. Simon Painter shows this in one of his talks, was it in Ndc London?

    • @MilanJovanovicTech
      @MilanJovanovicTech  2 หลายเดือนก่อน

      Could you share the link? Watched many of his talks, but not sure what you're referring to

    • @tore28
      @tore28 2 หลายเดือนก่อน +1

      ​@@MilanJovanovicTech Sorry, I cannot recall. There is some tips on page 152 of "Functional programming with C#" Simon Painter wrote in 2023.
      I see that each step is stored into a local variable instead of chaining. An alternative would be "Tap" or "Tee" method that can output information of the intermediate state.
      For example outputting state to the console. I am still learning FP, it is so elegant pattern in C# and such a joy to learn more of.

  • @calblui
    @calblui ปีที่แล้ว +1

    Good class,tks!

  • @scott98390
    @scott98390 ปีที่แล้ว +1

    Still waiting for more videos in this series

  • @Brendan2Alexander
    @Brendan2Alexander ปีที่แล้ว +1

    Love the railway approach here. Tho I find these fluent statements hard to debug. Is there a way to step thru each step?

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว +1

      Debugging is a bit tricky, yeah. But you can step into each function just fine. The bigger issue is you don't have local variables to check intermediate values 😅

  • @mahmoudalaskalany
    @mahmoudalaskalany ปีที่แล้ว +1

    Great One Milan Keep It Up
    and can we use something like this to create automated workflows

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว

      What do you mean by automated workflows?

    • @mahmoudalaskalany
      @mahmoudalaskalany ปีที่แล้ว

      @@MilanJovanovicTech
      I mean something like (Elsa workflow framework)
      Can we use this way to create something like this or it is different aproach

  • @UristMcFarmer
    @UristMcFarmer ปีที่แล้ว +1

    Well, other than the cons you listed, I disagree with everything you've said. However, I don't have the wherewhithall to discuss the finer points right now. I just want to say that if one is truely committed to writing Functional code in .NET, one should probably switch to using F# so they don't have to constantly write the boiler plate backing needed in C#

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว

      That's fine, we don't all have to agree 😁
      I'd stick with C# for other reasons than functional programming though

  • @alexalexander3252
    @alexalexander3252 ปีที่แล้ว

    Milan, I would appreciate if you clear one point for me. As far as I understand, we write extension methods for classes we can not change. And here you write an extension method for Email class and then edit this class. What about O from SOLID? Isn't it easier to write the method inside this Email class? I am a newbie if anything :)

  • @mohammedalbosifi3975
    @mohammedalbosifi3975 ปีที่แล้ว +1

    Niiiiiiiiooccccccccccccce.... Thank you

  • @diegodelafuente1739
    @diegodelafuente1739 ปีที่แล้ว +1

    ¡Gracias!

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว

      Thank you very much, Diego, I really appreciate it! :)

  • @majormartintibor
    @majormartintibor ปีที่แล้ว +1

    Good stuff. Have you ever used the FluentResult library?

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว +1

      Heard about it, didn't try it. I like coding some stuff on my own. Maybe I should consider creating my Nuget package for ROP 😅

    • @majormartintibor
      @majormartintibor ปีที่แล้ว

      @@MilanJovanovicTech your approach def has the advantage that you get a deeper understanding of the concept instead of just blindly using something.

  • @prabhpahul
    @prabhpahul ปีที่แล้ว +1

    Hi, nice video, do we have github repository? To follow your videos, specifically interested in Result class, and Domain Error implementations, thank you again.

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว

      I only share the code with my Patreon supporters, but I have a lot of similar examples on my GitHub that you can take a look at :)

    • @reinhardlackner1925
      @reinhardlackner1925 ปีที่แล้ว

      watch some of Simon Painters NDC talks - he's utilizing functional C# quite a bit and currently writing an O'Reily Book on this topic

  • @maynardpaye
    @maynardpaye ปีที่แล้ว +2

    seems similar to fluent validation?

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว

      It's all functional programming in some form

    • @krccmsitp2884
      @krccmsitp2884 ปีที่แล้ว +1

      At least both use the concept of method chaining, but ROP in special or method-chaining in general don't need to stop there. You can apply either on various problem areas.

  • @saifeddinebenromdhane7553
    @saifeddinebenromdhane7553 ปีที่แล้ว +1

    Amazing, any idea on whether the code will be published on Github or not, i would love to dig into it. Thank you

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว +1

      Patreons only, as usual 😁
      But in the spirit of giving, let me see if I have any open source examples

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว +1

      I think you can get started here, the Controllers follow ROP:
      github.com/m-jovanovic/event-reminder/tree/main/EventReminder.Services.Api/Controllers
      The MediatR handlers don't unfortunately, you'll have to figure it out 😅

    • @saifeddinebenromdhane7553
      @saifeddinebenromdhane7553 ปีที่แล้ว

      I do appreciate both, your good work and giving spirit, Thank you.

  • @debtpeon
    @debtpeon ปีที่แล้ว +1

    A switch would be easier to write and debug.

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว

      Easier to debug, probably. Functional vode is easier to write

  • @BlazorPlate
    @BlazorPlate ปีที่แล้ว +2

    Is it thread-safe?

  • @svorskemattias
    @svorskemattias ปีที่แล้ว +1

    For anyone who would like to dig deeper into this I highly recommend scott wlaschins content. His book "domain modeling made functional" and site Fsharpforfunandprofit contains a huge amount on the topic. He also has very nice talks on youtube. Ive succssfully implemented many of the patterns he describe in my C#-projects.

  • @OrgesKreka
    @OrgesKreka ปีที่แล้ว +1

    What keyboard are you using ?

  • @friedrichhayek4862
    @friedrichhayek4862 ปีที่แล้ว +1

    Why don't just use Haskell. Where all of this is mandatory.

  • @JeffChentingwei628
    @JeffChentingwei628 ปีที่แล้ว +1

    Is it possible to do with async/await in ROP ?

  • @cocoscacao6102
    @cocoscacao6102 ปีที่แล้ว +2

    F# video?

  • @angelldark6426
    @angelldark6426 ปีที่แล้ว

    Mr.Milan, do you have this project on Gidhab?