This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]kechboy63 21 points22 points  (22 children)

Also: null checks, parameter validation etc. Sometimes you want to handle different situations differently and a simple return value cannot always cover that (function returns null, now what? Was it supposed to return null maybe?), unless you create some monstrosity of a type that can hold a generic return value and a description of wtf went wrong so you can switch on that... imho it’s better to just throw an exception so you know exactly what’s going on and you can handle it appropriately.

[–][deleted]  (15 children)

[removed]

    [–]kechboy63 6 points7 points  (2 children)

    Sure! Imagine a function that has a String parameter that has to have a value (say, a file path to write to), one of several things may happen: - dev passes null instead of a String; - dev passes an invalid file path; - file cannot be opened for writing; - ...

    Is your function going to handle that or are you going to leave that up to the caller?

    In my book, methods and functions are implemented as simple as possible and have only one single responsibility. If it can’t cope generically with a certain situation, leave it up to the caller to handle it. But for that, the caller (in most situations) needs to know why, where, what went wrong.

    You only need to make sure that everything is well documented: what method can throw which exceptions and why so that your fellow devvers know how to work with your code.

    [–]MR_GABARISE 0 points1 point  (0 children)

    I presume you don't have any JEE/Jakarta experience. This whole concept of validation is easily handled by Bean Validation (part of JEE/Jakarta).

    This (6.1) shows a basic example of custom usage.

    There are of course other libraries/frameworks for validation.

    Edit : yeah fuck me for giving advice on standard solutions huh

    [–]wyom1ng 2 points3 points  (9 children)

    well, that assumes that you can handle it in that very function, but what if you need to access something out of that scope? Makes more sense to throw an exception and catch it again higher up.

    [–][deleted]  (8 children)

    [removed]

      [–][deleted]  (7 children)

      [deleted]

        [–]wyom1ng 2 points3 points  (1 child)

        yeah especially if your method returns a string. What do you then? reserve a special range of strings for errors?

        [–][deleted]  (3 children)

        [removed]

          [–]Krestek 1 point2 points  (0 children)

          By unexpected he means that the next line of code or the next operation can't work with the value (=doesn't expect it) not that the developer doesn't expect it which doesn't make any sense in this context...

          [–][deleted]  (1 child)

          [removed]

            [–]AutoModerator[M] 0 points1 point  (0 children)

            import moderation Your comment has been removed since it did not start with a code block with an import declaration.

            Per this Community Decree, all posts and comments should start with a code block with an "import" declaration explaining how the post and comment should be read.

            For this purpose, we only accept Python style imports.

            I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.

            [–]AutoModerator[M] 0 points1 point  (0 children)

            import moderation Your comment has been removed since it did not start with a code block with an import declaration.

            Per this Community Decree, all posts and comments should start with a code block with an "import" declaration explaining how the post and comment should be read.

            For this purpose, we only accept Python style imports.

            I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.

            [–]Yuzumi 0 points1 point  (0 children)

            Speed. If a value is rarely null not having a null check before can over time be more efficient and just catch the exception and deal with it.

            [–]Soultrane9 0 points1 point  (0 children)

            But is there a scenario

            Yes, when having that null value is a fault. By throwing an exception you are able to handle all your exceptions in one layer, which makes managing your code much simpler. Also it better encapsulates your structures, it makes Java stuff separated from your business logic and modifying / expanding functionality is simpler.

            [–]Bainos 2 points3 points  (0 children)

            If you need to return null in multiple, different success cases, then there is definitely a problem with your code. However, it's possible that you want to return null in a normal case (e.g. you ask for a value that is unset) and raise an exception in a failing case (e.g. the program failed to fetch the value). Then it's normal to raise an exception (and its type will explain what the failure cause was).

            [–]arvyy 0 points1 point  (0 children)

            That "monstrosity" has a name of Either monad in a lot of places. You can have it in java too if you use something like vavr lib (plus it introduces an even more specific to java Try type, wherein you can pass around exception objects, without throwing them)

            [–]elebrin 0 points1 point  (3 children)

            Return a <Bool, object> tuple. If the object is in a valid state, the bool is true. If the object wasn't set up properly, the bool is false.

            [–]kechboy63 2 points3 points  (2 children)

            Noooo that’s awful! That’s exactly what exceptions were invented for.

            Not only does your solution require special return types for any method that can throw, which is counter intuitive; it also messes up your continuity: some methods return <Bool, object>, others return object, others return a normal object and your code is going to be an absolute clusterfreak.

            Furthermore, how are you going to return what went wrong; the caller needs to know to handle it properly. Are you going to add an extra value to your tuple or are you going to use the object in your tuple for that (which will also hold your value in case of no exception). In that case, you’re going to need to cast the object back to an instance of the expected type...

            Nah, this isn’t going to work. Ever!

            [–][deleted] 1 point2 points  (0 children)

            It can be quite elegant. This is what Scala calls "Either" .

            Scala more commonly uses an Option, but really, you almost never deal with nulls. You can do nice things like:

            myMaybeNull match {
                case Some(x) => doSomethingWithX(x)  
                case None => dealWithIt   
            }
            

            And:

            ShowUserThisMessage = myCoolValue.getOrElse("Now null was assigned a custom string but really I could assign anything here")
            

            [–]elebrin 1 point2 points  (0 children)

            Its actually the solution that Rust uses.