I have a deceptively simple scenario, and I want a simple solution, but it\'s not obvious which is \"most correct\" or \"most Java\".
Let\'s say I have a small authe
Avoid returning a "sentinel value", especially null. You will end up with a codebase where methods cannot be understood by the caller without reading the implementation. In the case of null, callers may end up with NullPointerExceptions if they forget (or don't know) that your method may return null.
The tuple suggestion from Bas Leijdekkers is a good one that I use all the time if I want to return more than one value from a method. The one we use is P2<A, B> from the Functional Java library. This kind of type is a joint union of two other types (it contains one value of each type).
Throwing Exceptions for control flow is a bit of a code smell, but checked exceptions are one way of getting more than one type of value from a method. Other, cleaner possibilities exist though.
You can have an Option<T> abstract class with two subclasses Some<T>
and None<T>
. This is a bit like a type-safe alternative to null, and a good way to implement partial functions (functions whose return value isn't defined for some arguments). The Functional Java library has a full-featured Option
class that implements Iterable<T>
, so you can do something like this:
public Option<String> authenticate(String arg) {
if (success(arg))
return Option.some("Just an example");
else
return Option.none();
}
...
for(String s : authenticate(secret)) {
privilegedMethod();
}
Alternatively, you can use a disjoint union of two types, as an Either<L, R> class. It contains one value which is either of type L
or R
. This class implements Iterable<T>
for both L
and R
, so you can do something like this:
public Either<Fail, String> authenticate(String arg) {
if (success(arg))
return Either.right("Just an example");
else
return Either.left(Fail.authenticationFailure());
}
...
Either<Fail, String> auth = authenticate(secret);
for(String s : auth.rightProjection()) {
privilegedMethod();
}
for(Fail f : auth.leftProjection()) {
System.out.println("FAIL");
}
All of these classes, P2
, Option
, and Either
are useful in a wide variety of situations.
This seems like a common idiom in other programming languages, but I cannot figure out which one ( C I guess as I read in the question ) .
Almost the same question is posted here and here
Attempting to return two values from a single function, may be misleading. But as it has been proved by the attempts of doing so, it may be very useful too.
Definitely creating and small class with the results should be the correct way to proceed if that is a common flow in the app as posted before.
Here's a quote about returning two values from a function:
As a matter of programming style, this idea is not appealing in a object oriented programming language. Returning objects to represent computation results is the idiom for returning multiple values. Some suggest that you should not have to declare classes for unrelated values, but neither should unrelated values be returned from a single method.
I've found it in a feature request for java to allow multiple return values
look at the "evaluation" section dated: 2005-05-06 09:40:08
Just because failed authentication is commonplace doesn't mean it isn't exceptional.
In my opinion, authentication failures are the poster-child use case for checked exceptions. (Well... maybe file non-existence is the canonical use case, but authentication failure is a close #2.)
Some more options:
simple tuple example, actual implementation may need more:
class Tuple<L, R> {
public final L left;
public final R right;
public Tuple( L left, R right) {
this.left = left;
this.right = right;
}
}
I use the "tiny class" myself, usually with an inner class. I don't like using arguments to collect messages.
Also, if the method that might fail is "low level" - like coming from an app server or the database layer, I'd prefer to return an Enum with the return status, and then translate that into a string at the GUI level. Don't pass around user strings at the low level if you're ever going to internationalize your code, because then your app server can only respond in one language at a time, rather than having different clients working in different languages.
How about returning a string. Empty or Null for success. Error Message in case of failure. Simplest that would work. However not sure if it reads well.