Should you stop returning "null"? | Functional C#

Sdílet
Vložit
  • čas přidán 9. 08. 2020
  • Become a Patreon and get source code access: / nickchapsas
    Check out my courses: dometrain.com
    Hello everybody I'm Nick and in this video I wanna talk about how we can leverage a functional concept in C# that can potentially help up eliminate unexpected errors in our system. I am talking about null and the hundreds of issues that I have personally experienced with it over the year. Let's take a look at the problem and discuss a potential solution.
    Give Language Ext a star: github.com/louthy/language-ext
    Don't forget to comment, like and subscribe :)
    Social Media:
    Follow me on GitHub: bit.ly/ChapsasGitHub
    Follow me on Twitter: bit.ly/ChapsasTwitter
    Connect on LinkedIn: bit.ly/ChapsasLinkedIn
    #dotnet #csharp #functional

Komentáře • 280

  • @JayVal90
    @JayVal90 Před 3 lety +233

    I think it’s much easier to just use C# nullability syntax.

    • @r.c8756
      @r.c8756 Před 3 lety +9

      Well, quality of code sure has a cost...

    • @SamFerree
      @SamFerree Před 3 lety +6

      With the vast amount of the BCL that was null annotated in net5 and if you treat warnings as errors (which you should) then yeah. NRT is now the a fitting, and more idiomatic c# solution.

    • @Luturol
      @Luturol Před 3 lety +1

      even tho u have to check if has value in some cases

    • @mahmoudalsayed1138
      @mahmoudalsayed1138 Před 3 lety +4

      @@Luturol You could mark it as non Nullable reference type and throw null exception in the method, outside the method you will be 100% sure it can't be null, ergo, there is no need to check fo nulls, there is no boilerplate code.

    • @mahmoudalsayed1138
      @mahmoudalsayed1138 Před 3 lety

      Exactly! Not much easier, it's way cleaner to the code.

  • @AlanDarkworld
    @AlanDarkworld Před 3 lety +11

    An important topic right there. Null values in a langauge where the type system has no notion of "nullability", null values are a liability that you have to work around, e.g. vai Optionals. In a language which has the concept of a nullable type built right into the type system (such as Kotlin or TypeScript), null values become an asset. The compiler of such a language will actually refuse to compile a file by throwing a compile error at you if you try to do anything that *might* result in a NullPointerException. This has been revolutionary for my team and for my way of writing code. This feature alone makes Kotlin vastly superior to Java. It may seem like a small thing, but the impact it has is tremendous.

  • @olovjohansson4835
    @olovjohansson4835 Před 3 lety +13

    I like this pattern and we use it a lot. Otherwise an interface does not signal whether you should check the result for null or not - you have to read the documentation, or the implementation. Nullable referense types also solves that problem

  • @twiksify
    @twiksify Před 3 lety +6

    I remember missing an equivalent of Maybe in Haskell years ago, but have since then forgotten why. Thanks for refreshing my memory!

  • @superpcstation
    @superpcstation Před 3 lety +87

    Hi Nick, would really appreciate it if you could increase your font size a bit. Really helps out the mobile viewer.

  • @alfredoquintanalopez2265
    @alfredoquintanalopez2265 Před 3 lety +4

    Cool video, Please continue with this functional approach it's great!!!

  • @goranstefanov4531
    @goranstefanov4531 Před 3 lety +6

    I like the idea. Prevents exceptions and it feels like a proper approach. I would definitely enjoy more videos like this. Thank you!

  • @henrykkaufman1488
    @henrykkaufman1488 Před 2 lety +1

    Languages without null, like Rust, use exactly the same Opiton thingy. It does 3 things:
    - explicitly removes null from places it doesn't have to be (or would ever exist)
    - makes sure programmer is aware / handles the null case
    - makes programmer write more code
    Other than that, nothing changes. So generally it's safer code at cost of more code.
    I like these videos, they're pretty expert and unopinionated (professional). Thanks for doing this. I would love to see some material on possibilities of making sure a function won't change what you pass to it (like not passing mut in rust or using const & in c++).

  • @brianm.9451
    @brianm.9451 Před 2 lety

    I really like this approach. Wish I implemented it on a project since dealing with NULL’s was a huge pain for my app.

  • @TanigaDanae
    @TanigaDanae Před 3 lety +23

    I think this is very subjective but a neat solution.
    Personally I like to use vanilla paradigma and since you have to rewrite all the interfaces and functions to use "Option" you end up with a "Get(...)" and a "Match(...)" function instead of your "null" check.
    In this specific case I could make the code "null" aware in other ways e.g. by implementing a "bool TryGet(..., out)" instead.
    But at this point I guess it is just a matter of taste.

    • @michaelgehling6742
      @michaelgehling6742 Před 2 lety

      I prefer the try-pattern with bool TryGetSomething(out SomeType result). I n this solution the decision making is also implied and I don't need any unnecessary lambdas.

  • @davidsaunders1595
    @davidsaunders1595 Před 3 lety +3

    Good for you doing a video on this Nick, I come from a Kotlin environment where null safety is a first class citizen and I was blown away how much of a game changer it was. IMO the C# world has been slow to adopt the trick properly.
    I will say C# 9 nullability syntax with warnings as errors is what we use for this now, skipped C# 8 cause it had awful collisions with nullable struct syntax and generics. If that’s not an option something similar can be achieved with ReSharper/Rider, JetBrains Annotations and Implicit Nullability if running static analysis checks is viable.
    Short of that though this is what I’d use, good job.

    • @nickchapsas
      @nickchapsas  Před 3 lety +5

      It’s one of the reasons why I love Kotlin so much. With C# it’s obviously an afterthought and it’s up to the user to adopt which is understandable but sad if it doesn’t get adopted widely

  • @sadux
    @sadux Před 3 lety

    Great Chanel and tutorials. Thank you for sharing your knowledge. Keep going!

  • @DanteDeRuwe
    @DanteDeRuwe Před 3 lety +1

    Thanks Nick for another insightful video

  • @Luturol
    @Luturol Před 3 lety +1

    Great video! I was always wondering if C# had a similar to optional from Java

  • @bernardoherrera5217
    @bernardoherrera5217 Před 2 lety

    I love functional programming, I programmed for more than one year in Scala then when I came back to C# 4 years ago I found that there weren't so many functional features built-in the language itself. But now the language it is envolving and that's a good thing

  • @aurinator
    @aurinator Před 2 lety +1

    Full Disclosure posting before watching video, but my initial reaction is that it isn't as long as that behavior is expected from whatever's returning null, as while I completely agree that it isn't necessarily optimal or desirable per se, I've seen it used to make variables effectively ternary values when null is used, and it worked very well, but it was similarly documented well enough that the behavior was expected. I'll update this after the video if my opinion changes. Thank you so much for explicitly touching on that there *WAS* indeed a way with Unsafe code though. Burying heads in the sand around those possibilities doesn't make them go away, but many have done it from my experience.

  • @dealstunner8317
    @dealstunner8317 Před 3 lety

    Perfect! Thanks for this video

  • @frotes
    @frotes Před 3 lety +9

    Good stuff, I think functional programming patterns are great stuff that leads to cleaner and more expressive code, with less chance for bugs.
    C# is becoming more functional with every release. Would love to see more content in that direction on how to setup/utilize constructs like different monads and circuit breaker patterns.

  • @cs96ai
    @cs96ai Před 2 lety +1

    Great video! Would be great for generating object model audit trail. Keep up the awesome work!
    Any plans to do Kubernetes, Swarm, rancher?

  • @BonBaisers
    @BonBaisers Před 3 lety +2

    I use it on UI layer and Features layers (CQRS). Nulls and Exceptions are reserved to Infrastructure layer. Everything up must use Option like class type of response to force my devs to handle all cases on the application domain and the UI.

  • @wordonice4457
    @wordonice4457 Před 3 lety +2

    Null for life!!! lol but this is quite nice. I'll check it out. Looks like the optional interface in Java, which I've used a lot

  • @bradenb
    @bradenb Před 2 lety +2

    I love options, but I've had a hell of a time convincing my coworkers of their value. Occasionally I'll have some beautiful, elegant piece of code as a result of using them and they'll appreciate it, but never enough to try them for themselves. I've started sneaking options into common libraries to force it though :)

  • @RicardoValero95
    @RicardoValero95 Před 3 lety +1

    Hi Nick, about your api route I've been having issues using guid type as a parameter (invalid guids return oks), but as I saw in your example you parse it in the controller.
    Is this the best way to do this?

  • @TheExiledMeriler
    @TheExiledMeriler Před 3 lety +10

    I prefer nullability. And I love how null safety implemented in kotlin

    • @nickchapsas
      @nickchapsas  Před 3 lety +2

      Yeah C# was basically trying to get to Kotlin's implementation with C# 8 but the problem is that null worked like this for so many years that it's been engraved to anyone's muscle memory and it's so hard to change your mind on something that you've been doing for years.

  • @jacobstamm
    @jacobstamm Před 9 měsíci +1

    It would be so cool to see a round table discussion between you, Zoran Horvat, and someone like Eric Lippert or Anders Hejlsberg discuss the merits of nullable types vs the Optional pattern in C#. There seems to be some degree of dogmatism around it and it would be nice to see that stripped away.

  • @the-matrix-has-you
    @the-matrix-has-you Před 3 lety +2

    Tony Hoare has said "null was my billion dollar mistake" but I don't think he was right about that sentiment.The Programming World needed a Universal Type that reflects empty, has no members words in a simple way so we came Up with Nullable so that way any Type can be nullable the class looks for if the passed object is initialized or not and if initialized does it have a value set to it if yes then it is not null. So it was the Best way to do it really. Besides the whole .Net Framework Technologies depends on the Nullable Type there is no easy way of changing things now. I don't even mention the zillion of programs all around the World that is on production heavily depends on Nullable Type...

    • @SeanJMay
      @SeanJMay Před 3 lety +2

      There are no safe operations on null, though. That is the difference. The world does need some Empty or Bottom type. That should not be a type whose default behaviour is to go kaboom, though. It's a type whose default behaviour should be a no-op, with a reminder to deal with the no-op, *without* encouraging people to just swallow catches, or return null to the next poor sap who needs to do the exact same things you just did... possibly without the same level of concern for soundness of the logical flow of the application.

  • @fuzzylilpeach6591
    @fuzzylilpeach6591 Před 3 lety +49

    "not null, just the idea of no value." Pretty sure that's what null is.

    • @icebird76
      @icebird76 Před 3 lety

      @Ishaan Jaxtyn Insane! It took me 5 minutes to say it worked!

    • @tofraley
      @tofraley Před 2 lety

      You'd be incorrect. That's not what null is. The type system does not give us a way of representing "nothing" or "no value". So we use null to do that, even though it's problematic. And since everybody has treated it that way for so long, the compiler team had to create work-arounds so people would stop hurting themselves with it.

  • @recepdmr_
    @recepdmr_ Před 3 lety

    Thanks for video. Integrasiting.

  • @filipecotrimmelo7714
    @filipecotrimmelo7714 Před 3 lety +9

    I really like the idea. It prevents exceptions in the code, also leting new programmers doing less errors;

    • @amuuuinjured
      @amuuuinjured Před 3 lety +16

      In that case - better way to prevent new programmers from doing errors is not allow them to code. :D

    • @filipecotrimmelo7714
      @filipecotrimmelo7714 Před 3 lety

      @@amuuuinjured LoL

    • @MoMadNU
      @MoMadNU Před 3 lety

      Spend twice as much time testing than you do coding and it won't matter. Either you coded for null or you didn't and if you didn't it's a bug that you must fix.

    • @berylliosis5250
      @berylliosis5250 Před 2 lety

      @@MoMadNU Why waste time testing things the compiler can trivially verify for you? Test time is better than runtime, but compile time is better still. (Not to mention the more explicit/correct API)

    • @MoMadNU
      @MoMadNU Před 2 lety

      @@berylliosis5250 The compiler cannot detect a null reference exception which represents 90% of the exceptions you will encounter because of bugs in your code.

  • @MartinMaat
    @MartinMaat Před 2 lety

    You need to see some code for this to make sense. I have had discussions about this on SESE and they went nowhere. It only gets meaningful at 9:45. Before that one can just go "So it won't blow up at the same point, it will continue to run in an undetermined state which is worse! You will have to check at some point, whether it be for null or None...". Obviously for fluent interfaces null is literally a show stopper, I got that. Now I also see the returned wrapper object forces you to obtain the (encapsulated) value in a safe way. This is the real boon that often gets lost in a focus on null itself.

  • @WarrenLeggatt
    @WarrenLeggatt Před 3 lety +1

    Null is not an issue, it is the lack of self documentation in the function signature
    public MyClass GetTheThing();
    This function can return an instance, a null or throw an exception but you have no idea looking at the sig. This can mean people do not handle the possible outcomes.
    This is actually the correct signature such that just looking you can determine what can come back.
    public Either GetTheThing();
    C# 8 with nullable reference rates part of the pain out as you know if its nullable. The more info devs have on what can come back the less risk of blow up when in production :)

  • @coso2
    @coso2 Před 3 lety +3

    I still love use and return null :)
    But, from an execution perspective, which method is better on memory and execution speed?

  • @bruceleggett7500
    @bruceleggett7500 Před 3 lety +1

    I agree that nulls are a multibillion dollar mistake due to finding null reference exceptions in the Production environment sometimes for edge case scenarios and other times deep within a property chain which takes some extra time to debug and resolve. The use of the generic Option class isn't the elegant solution I was expecting. I was expecting Options to be built into the language and complier itself and include extra option functions and syntax

    • @sonicbhoc
      @sonicbhoc Před 2 lety

      That was one of the first things I noticed when I played around with F#. Option is built-in.

  • @argiziont
    @argiziont Před 3 lety

    Wow, that's awsome solution.

  • @fullmoonyeah1180
    @fullmoonyeah1180 Před 2 lety

    at the end of the day, it depends on how the value is treated. it also has some benefits that developers can use with it.

  • @CANEHURRICANE
    @CANEHURRICANE Před 3 lety

    Cool stuff dude thanks

  • @JohnEBoldt
    @JohnEBoldt Před 2 lety

    Update: I discovered the IfSome method which is exactly what I need for my use case. So no unsafe!
    I like this approach! I do have a use case question though. In my repository layer which uses EntityFramework, some columns are nullable and so if a property is null, I need to return a null value. I can do this using MatchUnsafe, but I'd prefer not to use it unless I have no other choice. Is there a better way to do this?
    Example:
    ExternalUserId is a string property in an EF table that is nullable in the database.
    ExternalUserId = user.ExternalUserId.Match(e => e, (string)null);
    This throws an exception when returning null.
    ExternalUserId = user.ExternalUserId.MatchUnsafe(e => e, (string)null);
    This works, but I'd prefer not to use it.
    Thoughts?

  • @diegogarcia6518
    @diegogarcia6518 Před 2 lety

    I like this video, and it's a cool package; but my two cents are that NRT's were enough for most scenarios back when the video was released, and with the upcoming .NET 7, auto-implemented null checks will make it even more so. This further adds to boilerplate in recent versions, but if you're stuck with legacy, this package could be a god-sent

  • @errrzarrr
    @errrzarrr Před 3 lety

    I like the approach

  • @amuuuinjured
    @amuuuinjured Před 3 lety +4

    1. What that code will look like when there will be two separate repository calls? Let's say get two different customers and return Ok only when both exists.
    2. That library seems are over complicating things. If you need that Match method - write simple extensions method and check if value is not null call ok otherwise fail.

  • @zubairkhakwani8772
    @zubairkhakwani8772 Před rokem

    If we have to operate on an object we're getting from DB, we still have to check for null before using it (In service or in the controller). So how does it benefit? I will still try it and see If it helps.

  • @Kokujou5
    @Kokujou5 Před 2 lety

    wow... someone never saw C# colesce operators... outch... guess that hurts now^^
    return customer ?? Notfound();
    and this can be valid syntax because if your method is an ActionResult you can directly return T and it will be converted into an OK

  • @alexanderhugestrand
    @alexanderhugestrand Před 3 lety +9

    The only difference between returning null or to use "maybe", is that the latter gives you compiler assistance to enforce you to write that if/else statement that you would otherwise forget. Personally I think it's overengineering to use such a construct. If/else works just fine if you are disciplined enough and test your code before deployment.

  • @javiermadueno
    @javiermadueno Před 3 lety +1

    It would be nice to see a video using Option with async method

    • @nickchapsas
      @nickchapsas  Před 3 lety +3

      It would work in the exact same way. You'd just have to return Task.

  • @GregWilliamBryant
    @GregWilliamBryant Před 2 lety

    @Nick Chapsas - I would be curious to how you feel about this style in 2022. I've unconsciously implemented something very simular in my codebase and really like this style personally.

  • @aleksanderw5536
    @aleksanderw5536 Před 3 lety

    Hi, considering that C# has nullable types which if used can lead to eliminating null pointer exceptions as well, do you think that Option still has a place in there?

    • @nickchapsas
      @nickchapsas  Před 3 lety +2

      I do actually and I see them as a different thing. Nullable types and the compiler can lie and Jon Skeet has a great talk about that. It’s also to the library author’s discretion to use them. Option beats all that with a clean forced matching scenario

  • @vssrikanthgarnepudi5952
    @vssrikanthgarnepudi5952 Před 3 lety +1

    Hey nick can you please make a video on web api concurrency issues with an example .

  • @arunbm123
    @arunbm123 Před rokem

    brilliant, its clean way to return from Action Method

  • @rolandtennapel5058
    @rolandtennapel5058 Před 3 lety +4

    Not for me, but I get it and I appreciate it 😏 I guess I'm just too comfortable with assuming anything / everything can be NULL and check for it (or pass by reference which helps a lot).

    • @masterdju1
      @masterdju1 Před 3 lety +1

      And its simpler to check if null... In thus case we need to use additional library and still write some checking code

    • @rolandtennapel5058
      @rolandtennapel5058 Před 3 lety +1

      @@willembeltman Checking inside the function means you don't have to remember to check outside the function. 😉

  • @JSDudeca
    @JSDudeca Před 3 lety +1

    I would say yes but I don't code in C#. I always return some sort of "None" type reference. Does not matter what language I code in. For a strong typed returns like Java, I would subclass the return type to identify value like NullMap for returning a Map that is "None". Never done C# though.

  • @kyoai
    @kyoai Před 3 lety +30

    But if you try to actually access the returned optional object, you sooner or later still have to do a check whether the object is valid or "none", so essentially it did not solve the null check problem, you just shoved the validity check to another place and did it in a more fancy way.

    • @SamFerree
      @SamFerree Před 3 lety +13

      If the only way to access the object is by "Match" then effectively you've compiler enforced the check, since you can't call Match for the Some only case, you MUST provide a None case or it will fail compilation.
      It moves the error from runtime to compile time. you can also do this post C# 8 by enabling Nullable reference types and treating all warnings as errors.

    • @r.c8756
      @r.c8756 Před 3 lety +9

      The point is not to remove the necessity of checking null values but to force the caller of a function to acknowledge the fact that it can return an empty value. This is mostly a safety/readability feature.

    • @rolandtennapel5058
      @rolandtennapel5058 Před 3 lety

      @@r.c8756 I read what you're saying but all I hear in my head is 'People are lazy in reading and writing documentation and have very dangerous assumptions.' 🤣 But seriously, developers that want to use this have had ways of doing this since day 1 of C# (me in part). Developers that don't want to use this won't (me in another part, bit of internally (protected) split on this issue). 😉

    • @atrumamantus
      @atrumamantus Před 3 lety +5

      @@rolandtennapel5058 it's not about being lazy, missing a null check is a common bug even for seasoned developers. Having tools to help you keep your code sound is never a bad thing, and the possibility of trading a runtime error for a compile time error is always a plus. Java has Optional types as well and they are very useful.

    • @r.c8756
      @r.c8756 Před 3 lety +4

      @@rolandtennapel5058 Documentation will never replace code quality and yes, people are lazy. They sometimes make mistakes and sometimes, they even plainly suck. This is kind of a negative way of looking at things but on the other hand, making things safe is thinking of the worse that can happen and then think of a way to prevent it to happen. As a programmer, you should always assume that the next guys who’s gonna use your code will mess up in the worse possible way. (and if you have a bit of experience in the field, you know that this happen more often than you’d hope...). So an important part of our job is to write code in a way that they can’t.

  • @albe8479
    @albe8479 Před 3 lety

    mindblown from the elegance of this syntax. Will try to implement it at work.

  • @JonathanPeel
    @JonathanPeel Před 2 lety

    I do like this (and I use F# a lot, so this makes a lot of sense), however, I think with the newer C# nullable `Customer?` I don't think it is needed.
    The language will force us to handle the case where the value is null.
    If we are handling a nullable, or we are handling an Option we are still handling it.
    I also like the idea of `map` and `bind` functions but we can also create those for Nullables just as easily as we can create them for Options.

    • @nickchapsas
      @nickchapsas  Před 2 lety

      It will only force you if you enable nullable reference types as errors in your project and even then you can ignore if you if think you know better than the compiler with the ! operator

    • @JonathanPeel
      @JonathanPeel Před 2 lety

      @@nickchapsas Yes, that ! is true. I do that 😝
      But usually, only in cases I know would have had an error a long time ago if what I am accessing is null.
      Maybe it proves your point.
      I have never seen the language extension library you talk about.
      I might check it out, although like I had said I use a lot of F#, so I might have a method returning FSharpOption or FSharpResult.
      This library probably wouldn't work on those.

  • @leonardogoens9771
    @leonardogoens9771 Před 3 lety

    Nice one!

  • @fishzebra
    @fishzebra Před 3 lety +6

    Thanks nice simple demo. I really like Option, however now C#8 has Nullable Reference Types there is less of a need for it. And as brilliant and extensive as the LanguageExt library is, it encourages C# developers to go deeper into using other Functional concepts which could easily confuse other team members and create unreadable code.
    Hopefully one day Option is built into C# and then we can freely use it, otherwise there is an argument that if you want to do real functional programming then you should stick to a Functional language like F#. I think this is valid, but it also frustrates me as there are not many F# jobs out there.

  • @archstanton9182
    @archstanton9182 Před 2 lety

    My coding standard insisted that a function only has one return path. Multiple return paths can be confusing, especially if it is code you inherited from someone else who has left the company.

  • @ChrisWalshZX
    @ChrisWalshZX Před 26 dny

    Is there any inefficiencies introduced to using Option? You say it's a struct but there must be somewhere where a reference or a no-reference is indicated that doesn't occur with null and not null. The code is also more verbose than traditional use of null and compiler helping with Object? vs Object helps identify and remove bugs during dev. Not convienced yet but interested in your further forays into Functional Programming. Thanks Nick.

  • @samuelgrahame3617
    @samuelgrahame3617 Před 3 lety +1

    Use null if needed. Check for null. Or use not null option.

  • @ronnyek4242
    @ronnyek4242 Před 2 lety

    Reminds me of rust and result types

  • @morlock2200
    @morlock2200 Před 2 lety

    the only way i use null atm is if i got an method that i want too have 3 values where 1 might be null cause i only wanna use two, i prefer makeing an class where i can return a bool and a message(string) back and do stuff with that. so even if the return is null it means the bool check for if it´s true so if it returns as null it would run the "Failed" code and just say " it failed".

  • @fourZerglings
    @fourZerglings Před 3 lety

    Should you stop returning null? Yes. Replace them with Optional.

  • @sidfjames1076
    @sidfjames1076 Před 10 měsíci

    Since new null checking feature in dotnet, which can be set to an error, I think the issue with returning null is (pun intended) "null and void".

  • @jasalvador
    @jasalvador Před 3 lety +4

    Great video! But it's not almost the same on using c#8 Nullable reference types? I don't know how c#8 nullable exactly works, I think only throws a warning when compiling but actually it compiles. In that case, I agree with the use of Option. If we could make that the code does not compile, It would be right to use the nullable type right?

    • @nickchapsas
      @nickchapsas  Před 3 lety +9

      The thing with Nullable reference types is that it doesn't really prevent you from handling them. You can still use the bang operator (!) to suppress it and it's not an error until you explicitly mark it as one. It's basically an afterthought and realistically, people won't instantly jump into using it because they can get away without using it. Option is something that you need to acknowledge no matter what, which i prefer.

    • @mariacobretti
      @mariacobretti Před 3 lety

      @@nickchapsas this is a very interesting discussion and maybe worth picking up in another video showing the approaches side by side with a more complex example. I'm currently leaning towards nullable reference types because I have seen code with pretty big classes and handling the matches made it quite difficult to read and understand. And with a good culture where you try to eliminate all the warnings I think its nice for a lot of cases. Also I just remembered that you can install the FxCop nuget package and have the null reference warnings pop up as errors instead so the project does not compile.. I probably should try that

    • @carlinhos10002
      @carlinhos10002 Před 3 lety +2

      You can configure the code to not compile if there are such warnings, and if one use ! forging operator, well, what he's saying is that "ok, I know it can be null but I don't care" which doesn't mean he forgot about null-check, pretty much the opposite.
      I think using yet another library to handle a case that's already done by the language is just too much. It was useful before c#8 but now it's just more complexity

  • @OldShoolGames
    @OldShoolGames Před rokem

    What about throwing a custom exception and catching it at an upper level ?

  • @daneru
    @daneru Před 2 lety

    For an API i would never use null return value. I'd return and object with some kind of warning message with 400 or 500 status code. So the recipient understands what happened. Also, the response is going to be handled differently because the status code is not OK. Inside assembly i think it is okay to use null. The key is to be consistent which is harder to reach working as a team.

  • @gleamofcolor
    @gleamofcolor Před 3 lety +2

    Thanks for the video . why don't we add that option just before the return statement where we needed as I don't like the idea of changing the return type everywhere. If I want to share the logic between the module , how that works as it don't expose the object as it is.i need use some method in the option struct to get the retuning object value .it's unnecessary overload and performance issue as well.

    • @nickchapsas
      @nickchapsas  Před 3 lety +4

      Maybe this example doesn’t illustrate the point as well as I’d like it to because it’s a very simple example. Realistically you would have different return types on each layer and you wouldn’t just be able to return option itself. The whole point of option is that you cannot get the value without handling the None scenario and that needs to happen across your application. Also, like I said in a different comment, performance impact is negligible.

    • @gleamofcolor
      @gleamofcolor Před 3 lety +1

      @@nickchapsas thanks, it would be great if you have another video which covers the said point.

    • @airjuri
      @airjuri Před 3 lety

      @@nickchapsas "performance impact is negligible." Famous last words before performance issues commmence ;)

    • @nickchapsas
      @nickchapsas  Před 3 lety

      @@airjuri I can guarantee with 100% confidence that this will be the last thing that you will need to optimize in your application

  • @UzairAli001
    @UzairAli001 Před 3 lety

    I appreciate the tutorial.
    I don't like the syntax that much, I prefer C# nullable over this.
    Of course this is my own opinion.

    • @nickchapsas
      @nickchapsas  Před 3 lety +3

      Hey Uzair, I really appreciate the comment. This is exactly why I make these videos. It doesn't need to be something that you will use but it's good to know that there is also this thing here that might be of use.

    • @UzairAli001
      @UzairAli001 Před 3 lety

      @@nickchapsas indeed exploring different options are definitely worth the time you never know when you might need that different approach.
      Keep it up 👍

    • @rhicanrong2494
      @rhicanrong2494 Před 3 lety

      I am looking for this too. I personally prefer using c# nullable between repository and services layers. But I think that option may serve better between services and controllers layers.
      It is great, Thanks for sharing.

  • @marsovac
    @marsovac Před rokem

    I don't like this if I have it in the interfaces, because it makes the nuget a requirement for implementing them, and sometimes that is not allowed.
    So yeah, nice to remove "if (x!=null)" and convert it into something more explicit, as long as it does not have repercussions down the chain.

  • @Rokannon
    @Rokannon Před 3 lety +5

    2:35
    Flag 'found' is redundant. You can just:
    _customers.TryGetValue(customerId, out var customer);
    return customer;

  • @masterdju1
    @masterdju1 Před 3 lety +1

    But whats wrong with null check? Why do we need to complicate code for a simple thing?
    In any case we should check if null or if match

    • @user-tk2jy8xr8b
      @user-tk2jy8xr8b Před 2 lety +1

      You can avoid null check, but cannot avoid match

  • @gardian06_85
    @gardian06_85 Před 3 lety +1

    I just get the feeling that if it is "none" then it has the form of the object, but could be uninitialized, and could kind of be more dangerous. if the code attempts to access an uninitialized field then it could lead to bad results, but if it tries to access null then it throws an exception.
    is it possible for a none to be modified into a real version of the struct/object. I just get the feeling that if it can be modified at any point then bad out of bounds data could cause bigger problems and maybe volnerabilities rather then the program hitting an Exception.nullReferenceException

    • @SeanJMay
      @SeanJMay Před 3 lety

      These containers aren't for low-level operations, and aren't for async values (that last part isn't exactly true... *this* container isn't for async values... async/await itself hides the concept of containerizing requests), they're for code composition.
      At any point in your example, some programmer could have your instance mutated by 8 different threads at the same time, with no thread locks; how is null going to help you in that case? If that's how your team writes code, then nothing can save you. The class is already there and uninitialized, or poorly reconfigured. If my code needs to return an A, but in order to make an A, I need an x which I have, and a y which I don't, I can solve that in ways better than passing around uninitialized instances.
      async GetA () {
      x = GetLocalX();
      potentialY = await GetY();
      potentialA = potentialY.Map(y => new A(x, y), None);
      return potentialA;
      }
      I am only going to make an A in the case that I know I can correctly construct that instance. And what the next user gets is something that they can operate on (through Mapping from A -> B), Filtering from (A -> None) in the case they aren't interested in that instance, handling the case where they got nothing, or just passing it on to the next person down the line, who will do any or all of the above, before themselves passing it on. It benefits the system in general, to write it in such a way that you have no incomplete or ill-configured objects/structs/sets/etc floating around, regardless of what architecture you're using for code composition.

    • @tofraley
      @tofraley Před 2 lety +1

      "None" does not have the form of the class you are trying to access.
      Lets say you have a method that returns an object of type Option. If you call that method, and it happens to return Some, you can think of that as wrapping a Person object. If you want to use that object, you kinda have to reach in and get it. In other words, you can't just treat the Option object like it's a Person object.
      On the other hand, if you call that method and it happens to return None, there is no Person object to access. In reality, that Option is probably wrapping a null Person object. But that's just an implementation detail, you have no way of accessing it. You can't accidentally access it.
      People in these comments seem to think the point is to have a clever way around null checking. That's not it.
      The point is to have a real representation of "no value" without bringing null into the equation at all.

  •  Před 2 lety +1

    I prefer not to return null when possible. I also try to avoid nullable value types.

  • @11r3start11
    @11r3start11 Před 3 lety +16

    I prefer to use functional syntax, its a lot more readable, though its harder to understand what's going on inside.
    But I'm wondering, how much overhead does Option usage have? especially .Match call with lambda-parameters

    • @nickchapsas
      @nickchapsas  Před 3 lety +16

      Very good question. It's my bad that I didn't cover it during the video.
      On this specific example:
      The Non-Option approach will execute at a mean time of 146 nanoseconds and will allocate 168 bytes of memory (it's probably the Guid object allocation).
      The Option approach will execute at a mean time of 222 nanoseconds and will allocate 296 bytes of memory (it's the Guid plus the Option object, even though this is stack memory allocation due to Option being a struct)

    • @WarrenLeggatt
      @WarrenLeggatt Před 3 lety +3

      With the latest C#, if enabled, there is nullable reference types similar to int?. With this all reference types by default are not nullable which can mitigate much of this out and the time implications will be reduced.
      When you use nullable reference types you have the same .HasValue and .Value properties along with operators like ?? and .?
      Personally I have come around to null is evil. I have lost count of the null exception errors I have chased down over the decades I have done at the code face. It is far better to use this sort of technique to force devs to have to deal with the full types of the return value instead of mask it. If you get an Option or MyClass? returned you know you have the chance you have no value and are forced to handle it. If you just get MyClass returned without that protection you have no idea. It makes the function more explicit.
      Take the following
      public Result DoTheThing();
      You can instantly see you might get a "good response" that might have a value or you get an error. No need to dig into the code to see if it can throw etc

  • @ckjdinnj
    @ckjdinnj Před 3 lety

    The options semantics is a bit obtuse.
    The exact same behavior is achievable in a clearer manner.
    The interface method should be changed from:
    Option Get(GUID id) ;
    To:
    bool TryGet(GUID id, out Customer customer);
    The first one has obfuscation that hurts more than it helps. TryGet signatures are clear and automatically enforced by proxy of out parameters requiring assignment by the compiler.

  • @iwan954
    @iwan954 Před 3 lety

    Rider has an option in refactoring to change signature automatically after changing implementation so you don't have to edit it manually. Very useful one, especially when you do some big refactoring.

    • @codex4046
      @codex4046 Před 3 lety +3

      Which is probably what he uses regularly, but for such a video other people might not get what is happening, doing it manually is better for explaining.

  • @zondaken
    @zondaken Před 2 lety

    Whats so different between null awareness or none awareness?

    • @nickchapsas
      @nickchapsas  Před 2 lety

      null awareness is optional and can be skipped. Option is a discriminated union and it has to be handled no matter what. It's safer

    • @zondaken
      @zondaken Před 2 lety

      @@nickchapsas you're referring to the second delegate? Uhh true i guess. Although you can pass null to that one as well but then you did it intentionally while null awareness can be forgotten. Yeah good point, got it.

  • @pateegutee7960
    @pateegutee7960 Před 2 lety

    How about using Null Object Pattern to avoid returning null?

  • @AlfredoPinto
    @AlfredoPinto Před 3 lety

    I also don't like to return nulls, but I take more like an envelope approach using this github.com/proteo5/Gali/blob/master/Gali/HL/Result.cs
    see the code to get the idea. You will actually communicate with the consumer method of what it happens, let me know if you want to discuss this.

  • @Ownage4lif31
    @Ownage4lif31 Před 3 lety +3

    Thought this was a joke, turns out you got a point. Thanks

  • @aborisov20
    @aborisov20 Před 3 lety +6

    I prefer always return IEnumerable even when just one object is expected. That solves the "returning null" issue. When no object found you will get empty collection.

    • @SamFerree
      @SamFerree Před 3 lety +3

      Option is basically just a list of 0 or 1. Some implementations of option actually just extend IEnumerable and essentially just provide convenience methods for returning a list of 1 or 0

    • @r.c8756
      @r.c8756 Před 3 lety +1

      It works but it’s a (dirty) hack which damages the readability of your code. The very point of typing is to add meaning to otherwise completely abstract and decontextualized algorithms.

    • @aborisov20
      @aborisov20 Před 3 lety

      @@r.c8756 Disagree with the first sentence and agree with second sentence. :)

    • @r.c8756
      @r.c8756 Před 3 lety +2

      @@aborisov20 Returning an IEnumerable tells whoever read your code that they should expect several elements. This is deceitful and therefore, bad practice.
      Correct use of types, variable and method name should describe as accurately as possible their behavior... What do you disagree with exactly ?

    • @aborisov20
      @aborisov20 Před 3 lety

      @@r.c8756 Nothing related to term "dirty hack". Just expected behaviour. By design.

  • @dcuccia
    @dcuccia Před 3 lety +2

    C# 9 switch expressions are a nice built-in implementation of Match.

    • @logank.70
      @logank.70 Před 3 lety

      I use switch expressions all the time now. C# 9 makes writing functional code in C# much easier.

  • @feelingeverfine
    @feelingeverfine Před 3 lety

    If you are already using LanguageExt you should use github.com/louthy/language-ext#the-awful-out-parameter

  • @ericfelipe2011
    @ericfelipe2011 Před 3 lety +1

    You do a simple IF in first code...
    But now, you generate a struct that consume memory and it's not a reference type, so, the object is copied in all return, plus you need two lambdas that's generate a lot of process and context keep process....
    Why this is good ???
    You need more memory, more process, more processor stack, and so on....

    • @nickchapsas
      @nickchapsas  Před 3 lety +1

      Because your code is safer. The benchmarks show a performance degradation in the class of a few nanoseconds for the benefit of NRE elimination and for predictable code. Ofc it’s something you can ship if you commit to using null reference types properly but again that’s up to the dev

    • @ericfelipe2011
      @ericfelipe2011 Před 3 lety

      @@nickchapsas if you put a check for null. Where the dangerous path of that ?
      Plus this nanosecond with a Friday, science software, bi software, financial software...
      And of course, change all your code...
      It's the basic of a language null treatment....
      It's like... We are using a stable old fashion jeans... Let's create a radical new one.

    • @nickchapsas
      @nickchapsas  Před 3 lety

      @@ericfelipe2011 The dangerous part is that it's up to the developer to put the null check in. What you're assuming is that every nullable thing will be null checked at the right place, which is simply not true.

    • @ericfelipe2011
      @ericfelipe2011 Před 3 lety

      @@nickchapsas with new coalesce it's even simpler
      Return object?.property ?? New list()
      With so many code analítics, it's can be configured yo show a warning of a null reference or something.

    • @nickchapsas
      @nickchapsas  Před 3 lety

      @@ericfelipe2011 Coalesce is a completely different feature and has nothing to do with this. I agree that Null reference types can be configured to give a similar experience but it's still up to the developers and the team to enable it and make it mandatory (error instead of warning)

  • @ilove2learn783
    @ilove2learn783 Před 2 lety

    The best way to handle it is using exceptions. If you expect a value and you get null -> that's an exception to handle. Trying to work around it is just not worth it. Exception is explicit, caught in the code, easy to test, you can write your own and make it easy to find, you can return as many different exceptions as you wish at any time and add more as codebase grows. It's just too good to use anything else.

    • @nickchapsas
      @nickchapsas  Před 2 lety

      Exceptions should be exceptional. I am not a fan of taking a performance hit just to have an easy way out of the application's flow. It's convinient, sure, but it's by no means good.

  • @eclecticx
    @eclecticx Před 3 lety +16

    'Should you stop returning "null"? ' Hell no. The mere question signifies overthinking. In regards to objects, trying to avoid null, which is there for a legitimate and useful reason, usually leads to over-programming if not bad programming. Lists are another matter. Those should always be initialized and have a count of 0 if empty.

    • @GreenGodDiary
      @GreenGodDiary Před 3 lety +4

      I agree, the code is much less readable in this case. I’m all for optional values (like std::optional) but I wouldn’t use it for nullables because a nullable already has the functionality built in, ergo the ability to check for a null reference.

    • @r.c8756
      @r.c8756 Před 3 lety +4

      I really don’t understand this disposition of mind. Questioning practices is the most elementary step of learning and improving and you never stop doing that in a career. With that mindset you can never improve... In only looks less readable because it challenges your habits.

    • @eclecticx
      @eclecticx Před 3 lety +1

      @@r.c8756 It's good to question things and consider new approaches, but you're stepping backwards if you add unneeded complexity. Less readable is less readable; that has nothing to do with habits being challenged. A software engineer, especially a contractor, can't be successful for any considerable number of years without challenging their habits, getting outside their comfort zones, and expanding their knowledge on a consistent basis. Not returning null and engineering a work around to avoid it is none of those.

    • @logank.70
      @logank.70 Před 3 lety +4

      The thing I like about the approach, personally, is that the design tells you that you have to account for "none." Nullable reference types are good for that too.

    • @eclecticx
      @eclecticx Před 3 lety

      @@logank.70 Exactly re nullable ref types, so why go to the trouble of the design? Just seems to be a case of overthinking and recreating the wheel simply because the programmer doesn't want to use nullable refs already included in the framework. Besides, nullables are something every programmer should already know how to handle, even a junior one.

  • @phyberoptyk5619
    @phyberoptyk5619 Před 3 lety

    Good vid. This is the library we use: github.com/nlkl/Optional
    Same thing, different repo.

  • @AngusMcIntyre
    @AngusMcIntyre Před 3 lety

    We should really all be writing f# for our application and web tiers.

  • @fat-freeoliveoil6553
    @fat-freeoliveoil6553 Před 2 lety +1

    I think it is a nice feature but I don't think I'll use anything like this unless it is part of .NET. I think having dependencies like this is a bit problematic.
    Doesn't nullable reference types basically solve the same problem anyways? You are telling the developer and the compiler that this can be null and thus should be checked (fortunately, Rider and VS also tell you this).
    (I get that some developers aren't comfortable with moving to a nullable project since it is a bit difficult to transition to but it is there).

  • @Gastell0
    @Gastell0 Před 2 lety

    While it seems like generally a good idea, it's simply too late?
    C# has null so deeply rooted that it has ridiculous amount of internal null checks where even if something is not supposed to have nulls (like this Option structure),
    it will be still internally routed through dozen of null checks for half of the actions...

  • @Bossti
    @Bossti Před 3 lety

    Uses Rider, gets a like :)

  • @ravikumarmistry
    @ravikumarmistry Před 3 lety

    I am ok with null, it make the code less readable because not every body uses the library. I like to stick to language features as close as I can it make my code simple.

    • @r.c8756
      @r.c8756 Před 3 lety

      Well, that’s the downside of using that kind of functionality. This kind of decision should probably be best taken and enforced as a team and not just as a personal initiative

  • @mortenbork6249
    @mortenbork6249 Před 3 lety

    Why not use the nullobject pattern? forcing you to create a "null" workflow for the object? That is much more inline with SOLID.

  • @ScorpiaChasis
    @ScorpiaChasis Před 3 lety

    Not sure I like this too much. I get the idea but let's say it's for newer developers. This is the kind of hack that may make their life easier but doesn't teach them good basis, it actually hides their flaws. Most 3rd party libraries still heavily rely on null. For example, the quite common newtonsoft JSON.
    Also if you don't learn the good practices around object manipulation and have to learn let's say JS. If you do not have the good habit of checking objects before using them, it's not going to be a fun day.
    In the end, I don't think this is helpful as it won't help developers improve and will just hide their lack of good practices.
    The value I do see in using Option is maybe proof of concept? So your demo doesn't crash?
    But then, what is the benefit vs a TryGet method with a nullable?
    It seems like a bool TryGetCustomer(Guid id, out Customer? customer) achieves a similar result?

    • @Yummeh
      @Yummeh Před 3 lety

      The thing is, you can't expect someone to have good habits. Option enforces good habits. Users (new or experienced) using an API you may have witten will know the value might be null.

    • @Coburah
      @Coburah Před 3 lety

      The TryGet method you propose DOES achieve a very similar result. The question is, would you prefer that over Option? If so, go ahead and use the TryGet! But according to your own logic (since the TryGet and the Option are so similar), the TryGet doesn't enforce good habits and hinders developers' improvement.

  • @iamansinghrajpoot
    @iamansinghrajpoot Před 10 měsíci

    My colleague refactored my code which returns Optional to return null 😢 My heart was broken

  • @MoMadNU
    @MoMadNU Před 3 lety

    I prefer to never return null and always provide a default value. In this case the default value is a real instance of a customer with the name "Not Found".

  • @user-tk2jy8xr8b
    @user-tk2jy8xr8b Před 2 lety

    The only issue with Option is it's not well-behaving: given `string F(bool b) => b ? "" : null; bool G(string s) => s == "";`, `false.ToSome().Map(F).Map(G)` must be equal to `false.ToSome().Map(v => F(G(v)))`, but it's not

  • @samancos
    @samancos Před 2 lety

    Hi, what's the IDE?

  • @user-ro3go4fm7k
    @user-ro3go4fm7k Před 3 lety

    I don't see the need to complicate the code with these fancy thing.
    In the service layer, it is still necessary to check whether the object was found. And this library will not provide any benefits. And even more, if you received NRE, then something is wrong with your code, anyway you need to fix that (with or without NRE) and you will notice it obviously.
    Perhaps this library will make the code a little "prettier" in the controllers, but if you haven't found the entity, you may need additional logic and "Option" construction will only disfigure your code

  • @FavioLeyva
    @FavioLeyva Před 2 lety

    you have a library for any :D hahaha

  • @Tekay37
    @Tekay37 Před 3 lety

    Doesn't this pattern fail as soon as you're trying to call methods of the customer object when you actually got none?
    I'd always prefer the NullObject pattern: Create an Interface ICustomer, that's implemented by both Customer and a NoCustomer class, the latter implementing the expected behaviour for when you don't have a customer. This way all your other code doesn't need to care anymore whether they actually found a Customer or not.

    • @zenitkov
      @zenitkov Před 3 lety

      If you want to use it on another class you'd have to again create an interface for it and the null class, which would force you to use the interface everywhere. That might not be possible without some big refactoring. Additionally, it won't work if it's a class from a library.

    • @Tekay37
      @Tekay37 Před 3 lety

      @@zenitkov Yes, I would always do that: Wherever I can have "zero or more" of, I would use the NullObject Pattern. It saves me from checking for null everywhere and have other code actually know, that there could be none of something.
      For a library: I would always create a Wrapper for the use of a library anyways. Within that wrapper I could translate null into my own NullObject.

    • @Coburah
      @Coburah Před 3 lety +1

      The Option doesn't have a customer in the "None" case, just a marker struct meaning "No value was found". There is only a customer object in the "Some" case. Which makes it 100 % safe to access the None part. It's much like a checked exception or an out parameter. But unlike checked Exceptions, Option has the semantic meaning of "this method can return None, and it's not very unexpected." The null object pattern is good too, but the Option approach is more explicit and requires far less work than implementing a null object.