Want to master Clean Architecture? Go here: bit.ly/3PupkOJ Want to unlock Modular Monoliths? Go here: bit.ly/3SXlzSt
@ajirahman5289 Жыл бұрын
Already subscribed...
@MilanJovanovicTech Жыл бұрын
@@ajirahman5289 Because you are awesome 🔥
@soverain Жыл бұрын
Functional programming, yes! Very excited to see more on this topic!
@MilanJovanovicTech Жыл бұрын
I'm loving the community response, definitely going to make more videos 😁
@aToa5241 Жыл бұрын
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 Жыл бұрын
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 kzbin.info/www/bejne/f6C4pKx7rryKZs0 which closely related to what Milan just presented
@aToa5241 Жыл бұрын
@@AboutCleanCode Nice video, thank you for sharing. Looking forward to seeing your videos on Uncle's Bob Clean Architecture as well.
@MilanJovanovicTech Жыл бұрын
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.
@devjonie Жыл бұрын
Wow! Interesting concept. Thanks Milan
@MilanJovanovicTech Жыл бұрын
It's even more interesting when you add side effects (database calls) and branching on the Result value 😁
@JochenZeischka Жыл бұрын
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 Жыл бұрын
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 Жыл бұрын
@@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#
@yohm318 ай бұрын
@MilanJovanovicTech indeed, Language.Ext library offers all the Monad you are dreaming of :)
@christianmarpert3844 Жыл бұрын
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 Жыл бұрын
Yeah, the Result class is very similar to the Either monad!
@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 😎
@janovrom10 ай бұрын
I was trying to wrap my head around monads and some actually useful example 👍 Thank you.
@MilanJovanovicTech10 ай бұрын
Thanks :) Here are a few more videos in the series: - kzbin.info/www/bejne/sKbcY51uq92aj8U - kzbin.info/www/bejne/d4ekY6CBfJmKhcU - kzbin.info/www/bejne/rHjOmKaaqtyhmZY
@kevinaubuchon5979 Жыл бұрын
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 Жыл бұрын
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 Жыл бұрын
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.
@marklord7614 Жыл бұрын
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 Жыл бұрын
I only wish we had real discriminated unions...
@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 Жыл бұрын
Interesting and straightforward as always, keep going! 👍🏼
@MilanJovanovicTech Жыл бұрын
Thanks a lot!
@tonycaesar7934 Жыл бұрын
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 Жыл бұрын
I left a few questions unanswered, such as returning multiple errors or handling async calls. Going to cover that in a future video.
@manuelknorle1457 Жыл бұрын
A benchmark on this approach would also be very interesting. Which of the two implementations has the greater impact on performance?
@MilanJovanovicTech Жыл бұрын
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 Жыл бұрын
You can probably make the result class a struct if it's not already.
@nicholaspreston95868 ай бұрын
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);
@MilanJovanovicTech8 ай бұрын
Ideally, the Value of a Result will never be null so no issues there
@branislavpetrovic7486 Жыл бұрын
Great intro to ROP! Thanks!
@MilanJovanovicTech Жыл бұрын
Thanks a lot, Bane :)
@branislavpetrovic7486 Жыл бұрын
@@MilanJovanovicTech Haha, I got a new nickname
@AboutCleanCode Жыл бұрын
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 Жыл бұрын
All of these methods can be easily coded, and there are libraries out there with rich features for ROP
@pilotboba Жыл бұрын
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 Жыл бұрын
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.
@DanimoDev Жыл бұрын
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.
@MilanJovanovicTech Жыл бұрын
Check out FluentResults for a nice library
@friedrichhayek4862 Жыл бұрын
This feels like what you must do in a common Haskell program.
@MilanJovanovicTech Жыл бұрын
Never tried Haskell 🤷♂️
@chrisbaker5284 Жыл бұрын
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 Жыл бұрын
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 Жыл бұрын
@@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.
@hugotachoires1721 Жыл бұрын
Nice video, like every time ! Keep up
@MilanJovanovicTech Жыл бұрын
Thanks, will do!
@ajirahman5289 Жыл бұрын
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 Жыл бұрын
Sure, I can make a short video about writing tests for this. All of the videos are C# 11 / .NET 7 going forward.
@UristMcFarmer Жыл бұрын
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 Жыл бұрын
That's fine, we don't all have to agree 😁 I'd stick with C# for other reasons than functional programming though
@amitconnect Жыл бұрын
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 👍
@MilanJovanovicTech Жыл бұрын
Definitely making more videos
@relhimp Жыл бұрын
Two chars: Rx
@MilanJovanovicTech Жыл бұрын
There's Rx.NET
@duongphuhiep3 ай бұрын
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?
@MilanJovanovicTech3 ай бұрын
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)
@kevinaubuchon5979 Жыл бұрын
Great video.
@MilanJovanovicTech Жыл бұрын
Glad you enjoyed it
@autograf89 Жыл бұрын
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?
@MilanJovanovicTech Жыл бұрын
Absolutely, there are solutions for that also!
@diegodelafuente173911 ай бұрын
¡Gracias!
@MilanJovanovicTech11 ай бұрын
Thank you very much, Diego, I really appreciate it! :)
@mohammedalbosifi3975 Жыл бұрын
Niiiiiiiiooccccccccccccce.... Thank you
@MilanJovanovicTech Жыл бұрын
Most welcome 😊
@calblui Жыл бұрын
Good class,tks!
@MilanJovanovicTech Жыл бұрын
Thank you, glad you liked it 😁
@JustMe-gp4so Жыл бұрын
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 Жыл бұрын
Yes, it's possible. I'll record a video soon talking about that!
@mahmoudalaskalany Жыл бұрын
Great One Milan Keep It Up and can we use something like this to create automated workflows
@MilanJovanovicTech Жыл бұрын
What do you mean by automated workflows?
@mahmoudalaskalany Жыл бұрын
@@MilanJovanovicTech I mean something like (Elsa workflow framework) Can we use this way to create something like this or it is different aproach
@scott98390 Жыл бұрын
Still waiting for more videos in this series
@MilanJovanovicTech Жыл бұрын
Check out Function Composition video
@MilanJovanovicTech Жыл бұрын
And one more is coming in a week
@scott98390 Жыл бұрын
@@MilanJovanovicTech will do!
@majormartintibor Жыл бұрын
Good stuff. Have you ever used the FluentResult library?
@MilanJovanovicTech Жыл бұрын
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 Жыл бұрын
@@MilanJovanovicTech your approach def has the advantage that you get a deeper understanding of the concept instead of just blindly using something.
@Brendan2Alexander Жыл бұрын
Love the railway approach here. Tho I find these fluent statements hard to debug. Is there a way to step thru each step?
@MilanJovanovicTech Жыл бұрын
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 😅
@tore28Ай бұрын
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Ай бұрын
Could you share the link? Watched many of his talks, but not sure what you're referring to
@tore28Ай бұрын
@@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.
@svorskemattias Жыл бұрын
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.
@MilanJovanovicTech Жыл бұрын
Scott is the man :)
@prabhpahul Жыл бұрын
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 Жыл бұрын
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 Жыл бұрын
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 Жыл бұрын
seems similar to fluent validation?
@MilanJovanovicTech Жыл бұрын
It's all functional programming in some form
@krccmsitp2884 Жыл бұрын
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.
@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 :)
@MilanJovanovicTech Жыл бұрын
Where is the Email extension method? 🤔
@saifeddinebenromdhane7553 Жыл бұрын
Amazing, any idea on whether the code will be published on Github or not, i would love to dig into it. Thank you
@MilanJovanovicTech Жыл бұрын
Patreons only, as usual 😁 But in the spirit of giving, let me see if I have any open source examples
@MilanJovanovicTech Жыл бұрын
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 Жыл бұрын
I do appreciate both, your good work and giving spirit, Thank you.
@debtpeon Жыл бұрын
A switch would be easier to write and debug.
@MilanJovanovicTech Жыл бұрын
Easier to debug, probably. Functional vode is easier to write
@BlazorPlate Жыл бұрын
Is it thread-safe?
@MilanJovanovicTech Жыл бұрын
Yes
@krccmsitp2884 Жыл бұрын
Since the shown implementation uses pure functions, absolutely.
@friedrichhayek4862 Жыл бұрын
Why don't just use Haskell. Where all of this is mandatory.