It's right there in the name: exception. Raising one should be an exceptional case. But this is quite commonly not followed.
Pattern 2 is a good pattern. Get a user which does not exist, then you get nothing. There is no error condition here. Returning an optional is just as fine, I don't really see the point of using optionals in most cases and it does not remove the null check. Optional.isPresent() is a null check. The only difference is that Optional is more explicit that a value might be missing. I much more prefer annotating a method that a null check is required, because static code analysis can verify this. Where getUser().get().getName() will produce a null deferences and is more difficult to check in static analysis.
But, if getUser() does a database call, and for some reason the connection gets broken. This is exceptional. You would not return null in this case, or an Optional with no value. You need to propagate the exceptional case. Pattern 4 can be horrible, because that means that you need to add that construction everywhere and constantly deal with it. Much like having to deal with checked exceptions. (I prefer checked exceptions, because it make you have to deal with exception cases.)
What would be awesome if exception handling and return type (and optionals) could be part of the language:
functionUsergetUser(id){// ...}// Returns a user or null. Can throw exceptions.Useruser=getUser(x);// Returns an optional with a possible value. Can still throw exceptions.Optional<User>optUser=getUser(x);// Returns a result type, with a possible value. Or a result with an error. // Does not throw exceptions, they would be in the result's error.Result<User>resUser=getUser(x);
All the same method. But the language will take care of wrapping it nicely in the format you want to deal with. Sort of, auto boxing for return values.
And if you extend this with pattern matching:
match(getUser(x)){Ok(User):// got an userMissing:// got nullError(E):// got an exception}
I love static site generators, Elm, JavaScript and building things for the web.
In my previous life I was a working classical pianist. I try to combine music and programming when I can.
I suppose if static analysis can check that your function might return null it's not too evil. I would just rather have the return type be explicit and have the compiler force me to deal with the uncertainty. So I prefer pattern 4 even if you have to deal with it more. I have discovered that when refactoring out exceptions there were a lot of boundary cases I hadn't considered that I am now forced to deal with.
I have discovered that when refactoring out exceptions there were a lot of boundary cases I hadn't considered that I am now forced to deal with.
And that's why I prefer to use checked exceptions. It forces you to deal with it. There are cases where unchecked exceptions are alright, like constraint violations on inputs. (e.g. null even though I said it should not be null.)
But parsing functions, e.g. string to X, should always throw checked exceptions. But this is quite often not the case, so I need to lookup the documentation on what to expect when it's garbage.
Or various utility functions which are not forgiving, and throw exceptions even though a safe response is just as valid. For example "foo".substring(1,10) could have simply returned "oo" instead of throwing an out of bounds exception. Basically try to avoid creating cases where people have to deal with errors.
For further actions, you may consider blocking this person and/or reporting abuse
We're a place where coders share, stay up-to-date and grow their careers.
It's right there in the name: exception. Raising one should be an exceptional case. But this is quite commonly not followed.
Pattern 2 is a good pattern. Get a user which does not exist, then you get nothing. There is no error condition here. Returning an optional is just as fine, I don't really see the point of using optionals in most cases and it does not remove the null check. Optional.isPresent() is a null check. The only difference is that Optional is more explicit that a value might be missing. I much more prefer annotating a method that a null check is required, because static code analysis can verify this. Where
getUser().get().getName()will produce a null deferences and is more difficult to check in static analysis.But, if getUser() does a database call, and for some reason the connection gets broken. This is exceptional. You would not return null in this case, or an Optional with no value. You need to propagate the exceptional case. Pattern 4 can be horrible, because that means that you need to add that construction everywhere and constantly deal with it. Much like having to deal with checked exceptions. (I prefer checked exceptions, because it make you have to deal with exception cases.)
What would be awesome if exception handling and return type (and optionals) could be part of the language:
All the same method. But the language will take care of wrapping it nicely in the format you want to deal with. Sort of, auto boxing for return values.
And if you extend this with pattern matching:
I suppose if static analysis can check that your function might return null it's not too evil. I would just rather have the return type be explicit and have the compiler force me to deal with the uncertainty. So I prefer pattern 4 even if you have to deal with it more. I have discovered that when refactoring out exceptions there were a lot of boundary cases I hadn't considered that I am now forced to deal with.
And that's why I prefer to use checked exceptions. It forces you to deal with it. There are cases where unchecked exceptions are alright, like constraint violations on inputs. (e.g. null even though I said it should not be null.)
But parsing functions, e.g. string to X, should always throw checked exceptions. But this is quite often not the case, so I need to lookup the documentation on what to expect when it's garbage.
Or various utility functions which are not forgiving, and throw exceptions even though a safe response is just as valid. For example
"foo".substring(1,10)could have simply returned"oo"instead of throwing an out of bounds exception. Basically try to avoid creating cases where people have to deal with errors.