Want to master Clean Architecture? Go here: bit.ly/3PupkOJ Want to unlock Modular Monoliths? Go here: bit.ly/3SXlzSt
@ajirahman52892 жыл бұрын
Already subscribed...
@MilanJovanovicTech2 жыл бұрын
@@ajirahman5289 Because you are awesome 🔥
@diegodelafuente1739 Жыл бұрын
¡Gracias!
@MilanJovanovicTech Жыл бұрын
Thank you very much, Diego, I really appreciate it! :)
@soverain2 жыл бұрын
Functional programming, yes! Very excited to see more on this topic!
@MilanJovanovicTech2 жыл бұрын
I'm loving the community response, definitely going to make more videos 😁
@vijayarajan-bt5fk4 ай бұрын
I am beginning learner what are the use of this ('@').
@HENRYMEGWAI3 ай бұрын
Yes Milian, more functional programming videos.
@aToa52412 жыл бұрын
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!
@AboutCleanCode2 жыл бұрын
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
@aToa52412 жыл бұрын
@@AboutCleanCode Nice video, thank you for sharing. Looking forward to seeing your videos on Uncle's Bob Clean Architecture as well.
@MilanJovanovicTech2 жыл бұрын
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.
@devjonie2 жыл бұрын
Wow! Interesting concept. Thanks Milan
@MilanJovanovicTech2 жыл бұрын
It's even more interesting when you add side effects (database calls) and branching on the Result value 😁
@janovrom Жыл бұрын
I was trying to wrap my head around monads and some actually useful example 👍 Thank you.
@MilanJovanovicTech Жыл бұрын
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
@tonycaesar79342 жыл бұрын
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!
@MilanJovanovicTech2 жыл бұрын
I left a few questions unanswered, such as returning multiple errors or handling async calls. Going to cover that in a future video.
@krccmsitp28842 жыл бұрын
Interesting and straightforward as always, keep going! 👍🏼
@MilanJovanovicTech2 жыл бұрын
Thanks a lot!
@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 😎
@manuelknorle14572 жыл бұрын
A benchmark on this approach would also be very interesting. Which of the two implementations has the greater impact on performance?
@MilanJovanovicTech2 жыл бұрын
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.
@branislavpetrovic74862 жыл бұрын
Great intro to ROP! Thanks!
@MilanJovanovicTech2 жыл бұрын
Thanks a lot, Bane :)
@branislavpetrovic74862 жыл бұрын
@@MilanJovanovicTech Haha, I got a new nickname
@kevinaubuchon59792 жыл бұрын
Good video. These functional programming concepts are difficult to get other team members to embrace though. Some appreciate them, others simply don't understand.
@MilanJovanovicTech2 жыл бұрын
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.
@JochenZeischka2 жыл бұрын
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.
@MilanJovanovicTech2 жыл бұрын
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.
@reinhardlackner19252 жыл бұрын
@@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 Жыл бұрын
@MilanJovanovicTech indeed, Language.Ext library offers all the Monad you are dreaming of :)
@marklord76142 жыл бұрын
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).
@MilanJovanovicTech2 жыл бұрын
I only wish we had real discriminated unions...
@MaximilienNoal2 жыл бұрын
@@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.
@kevinaubuchon59792 жыл бұрын
Great video.
@MilanJovanovicTech2 жыл бұрын
Glad you enjoyed it
@AboutCleanCode2 жыл бұрын
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 ...
@MilanJovanovicTech2 жыл бұрын
All of these methods can be easily coded, and there are libraries out there with rich features for ROP
@calblui2 жыл бұрын
Good class,tks!
@MilanJovanovicTech2 жыл бұрын
Thank you, glad you liked it 😁
@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
@ajirahman52892 жыл бұрын
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.
@MilanJovanovicTech2 жыл бұрын
Sure, I can make a short video about writing tests for this. All of the videos are C# 11 / .NET 7 going forward.
@duongphuhiep8 ай бұрын
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?
@MilanJovanovicTech8 ай бұрын
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)
@nicholaspreston9586 Жыл бұрын
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 Жыл бұрын
Ideally, the Value of a Result will never be null so no issues there
@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.
@mohammedalbosifi39752 жыл бұрын
Niiiiiiiiooccccccccccccce.... Thank you
@MilanJovanovicTech2 жыл бұрын
Most welcome 😊
@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 😅
@amitconnect2 жыл бұрын
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 👍
@MilanJovanovicTech2 жыл бұрын
Definitely making more videos
@friedrichhayek48622 жыл бұрын
This feels like what you must do in a common Haskell program.
@MilanJovanovicTech2 жыл бұрын
Never tried Haskell 🤷♂️
@tore287 ай бұрын
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?
@MilanJovanovicTech7 ай бұрын
Could you share the link? Watched many of his talks, but not sure what you're referring to
@tore287 ай бұрын
@@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.
@pilotboba2 жыл бұрын
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.
@MilanJovanovicTech2 жыл бұрын
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.
@autograf892 жыл бұрын
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?
@MilanJovanovicTech2 жыл бұрын
Absolutely, there are solutions for that also!
@maynardpaye2 жыл бұрын
seems similar to fluent validation?
@MilanJovanovicTech2 жыл бұрын
It's all functional programming in some form
@krccmsitp28842 жыл бұрын
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.
@mahmoudalaskalany2 жыл бұрын
Great One Milan Keep It Up and can we use something like this to create automated workflows
@MilanJovanovicTech2 жыл бұрын
What do you mean by automated workflows?
@mahmoudalaskalany2 жыл бұрын
@@MilanJovanovicTech I mean something like (Elsa workflow framework) Can we use this way to create something like this or it is different aproach
@JustMe-gp4so2 жыл бұрын
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?
@MilanJovanovicTech2 жыл бұрын
Yes, it's possible. I'll record a video soon talking about that!
@BlazorPlate2 жыл бұрын
Is it thread-safe?
@MilanJovanovicTech2 жыл бұрын
Yes
@krccmsitp28842 жыл бұрын
Since the shown implementation uses pure functions, absolutely.
@majormartintibor2 жыл бұрын
Good stuff. Have you ever used the FluentResult library?
@MilanJovanovicTech2 жыл бұрын
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 😅
@majormartintibor2 жыл бұрын
@@MilanJovanovicTech your approach def has the advantage that you get a deeper understanding of the concept instead of just blindly using something.
@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? 🤔
@OrgesKreka Жыл бұрын
What keyboard are you using ?
@MilanJovanovicTech Жыл бұрын
Logitech G413 Carbon
@OrgesKreka Жыл бұрын
Thank You
@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!
@prabhpahul2 жыл бұрын
Hi, nice video, do we have github repository? To follow your videos, specifically interested in Result class, and Domain Error implementations, thank you again.
@MilanJovanovicTech2 жыл бұрын
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 :)
@reinhardlackner19252 жыл бұрын
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
@relhimp Жыл бұрын
Two chars: Rx
@MilanJovanovicTech Жыл бұрын
There's Rx.NET
@UristMcFarmer2 жыл бұрын
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#
@MilanJovanovicTech2 жыл бұрын
That's fine, we don't all have to agree 😁 I'd stick with C# for other reasons than functional programming though
@saifeddinebenromdhane75532 жыл бұрын
Amazing, any idea on whether the code will be published on Github or not, i would love to dig into it. Thank you
@MilanJovanovicTech2 жыл бұрын
Patreons only, as usual 😁 But in the spirit of giving, let me see if I have any open source examples
@MilanJovanovicTech2 жыл бұрын
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 😅
@saifeddinebenromdhane75532 жыл бұрын
I do appreciate both, your good work and giving spirit, Thank you.
@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 :)
@andiwijayas2 ай бұрын
This is like a chain of responsibility pattern
@MilanJovanovicTech2 ай бұрын
A bit simpler - no objects, just functions
@JeffChentingwei6282 жыл бұрын
Is it possible to do with async/await in ROP ?
@MilanJovanovicTech2 жыл бұрын
Yes, I'll show that in of the videos!
@JeffChentingwei6282 жыл бұрын
@@MilanJovanovicTech amazing! Thanks !
@friedrichhayek48622 жыл бұрын
Why don't just use Haskell. Where all of this is mandatory.
@MilanJovanovicTech2 жыл бұрын
Because I'm good at C#
@debtpeon Жыл бұрын
A switch would be easier to write and debug.
@MilanJovanovicTech Жыл бұрын
Easier to debug, probably. Functional vode is easier to write
@cocoscacao61022 жыл бұрын
F# video?
@MilanJovanovicTech2 жыл бұрын
Unlikely, I don't develop with F#
@minnedanhieux10404 ай бұрын
While I like the 'functional' approach, I don't see how this would solve code complexity. Sure the railway concept is simple but this implementation is not simple at all. Probably the complexity arises from the problem itself rather then the code in this case. There is a potential 'minimum code complexity' to every problem and an implementation should search for this bottom. It looks like you are approaching it and I like your insights and methods here, but I'll bet there are other implementation even simpler than this one... :)
@MilanJovanovicTech4 ай бұрын
The biggest hurdle here is familiarity with ROP and FP