Related
Im trying to implement validation module used for handling events. The validation module is based on simple interface:
public interface Validator {
Optional<ValidationException> validate(Event event);
}
Existing code base in my team relies on the wrapping exception mechanism - I cannot really play with it.
I have encountered problems when implementing new validator, that is responsible for validating single event, in two terms.
Assume the event is PlayWithDogEvent, and it contains Toys a dog can play with.
Flow of validation of such event:
For each toy,
Check if its a ball
If its a ball, it should be not too large.
If any of the toys is either not a ball/too big ball, my validate(Event event) method should return Optional.of(new ValidationException("some msg")).
I have implemented my validator the following way:
public class ValidBallsOnlyValidator implements Validator {
#Override
public Optional<ValidationException> validate(Event event) {
try {
event.getToys().forEach(this::validateSingleToy);
return Optional.empty();
} catch (InvalidToyException ex) {
return Optional.of(new ValidationException(ex.getMessage()));
}
}
private void validateSingleToy(Toy toy) {
// In real code the optional here is kinda mandatory
Optional<Toy> potentialBall = castToyToBall(toy);
// Im using Java 8
if(potentiallBall.isPresent()) {
checkIfBallIsOfValidSize(potentialBall.get(), "exampleSize");
} else {
throw new InvalidToyException("The toy is not a ball!")
}
}
private void checkIfBallIsOfValidSize(Toy toy, String size) {
if(toyTooLarge(toy, size)) throw new InvalidToyException("The ball is too big!")
}
}
The piece seems to work just fine, but im uncomfortable with the way it looks. My biggest concern is whether it is a good practice to place whole stream processing inside single try. Moreover, I don't think such mixing of exception-catching + returning optionals is elegant.
I could use some advice and/or best practices for such scenarios.
but im uncomfortable with the way it looks.
The API you're working against is crazy design. The approach to dealing with silly APIs is generally the same:
Try to fix it 'upstream': Make a pull request, talk to the team that made it, etc.
If and only if that option has been exhausted, then [A] write whatever ugly hackery you have to, to make it work, [B] restrict the ugliness to as small a snippet of code as you can; this may involve writing a wrapper that 'contains' the ugly, and finally [C] do not worry about code elegance within the restricted 'ugly is okay here' area.
The reason the API is bizarre is that it is both getting validation wrong, and not capitalizing on the benefits of their mistake (as in, if I'm wrong about their approach being wrong, then at least they aren't doing the best job at their approach).
Specifically, an exception is a return value, in the sense that it is a way to return from a method. Why isn't that interface:
public interface Validator {
void validate(Event event) throws ValidationException;
}
More generally, validation is not a 'there is at most one thing wrong' situation, and that goes towards your problem with 'it feels weird to write a try/catch around the whole thing'.
Multiple things can be wrong. There could be 5 toys, one of which is a ball but too large, and one of which is a squeaky toy. It is weird to report only one error (and presumably, an arbitrarily chosen one).
If you're going to go with the route of not throwing validation exceptions but returning validation issues, then the issues should presumably not be exceptions in the first place, but some other object, and, you should be working with a List<ValidationIssue> and not with an Optional<ValidationIssue>. You've gotten rid of an optional, which is always a win, and you now can handle multiple issues in one go. If the 'end point' that processes all this is fundamentally incapable of dealing with more than one problem at the time, that's okay: They can just treat that list as an effective optional, with list.isEmpty() serving as the 'all is well' indicator, and list.get(0) otherwise used to get the first problem (that being the only problem this one-error-at-a-time system can deal with).
This goes to code elegance, the only meaningful way to define that word 'elegance': It's code that is easier to test, easier to understand, and more flexible. It's more flexible: If later on the endpoint code that deals with validation errors is updated to be capable of dealing with more than one, you can now do that without touching the code that makes validation issue objects.
Thus, rewrite it all. Either:
Make the API design such that the point is to THROW that exception, not to shove it into an optional, -or-
Make the API list-based, also get rid of optional (yay!) and probably don't work with a validation issue object that extends SomeException. If you're not gonna throw it, don't make it a throwable.
If that's not okay, mostly just don't worry about elegance so much - elegance is off the table once you're forced to work with badly designed APIs.
However, there's of course almost always some style notes to provide for any code.
return Optional.of(new ValidationException(ex.getMessage()));
Ordinarily, this is extremely bad exception handling and your linter tool SHOULD be flagging this down as unacceptable. If wrapping exceptions, you want the cause to remain to preserve both the stack trace and any exception-type-specific information. You're getting rid of all that by ignoring everything about ex, except for its message. Ordinarily, this should be new ValidationException("Some string that adds appropriate context", ex) - thus preserving the chain. If there is no context to add / it is hard to imagine what this might be, then you shouldn't be wrapping at all, and instead throwing the original exception onwards.
However, given that exceptions are being abused here, perhaps this code is okay - this again goes to the central point: Once you're committed to working with a badly designed API, rules of thumb on proper code style go right out the window.
private void checkIfBallIsOfValidSize(Toy toy, String size) {
if(toyTooLarge(toy, size)) throw new InvalidToyException("The ball is too big!")
}
Yes, this is a good idea - whilst the API expects you not to throw exceptions but to wrap them in optionals, that part is bad, and you should usually not perpetuate a mistake even if that means your code starts differing in style.
event.getToys().forEach(this::validateSingleToy);
Generally speaking, using the forEach method directly, or .stream().forEach(), is a code smell. forEach should be used in only two cases:
It's the terminal on a bunch of stream ops (.stream().filter().flatMap().map()....forEach - that'd be fine).
You already have a Consumer<T> object and want it to run for each element in a list.
You have neither. This code is best written as:
for (var toy : event.getToys()) validateSingleToy(toy);
Lambdas have 3 downsides (which turn into upsides if using lambdas as they were fully intended, namely as code that may run in some different context):
Not control flow transparent.
Not mutable local var transparent.
Not checked exception type transparent.
3 things you lose, and you gain nothing in return. When there are 2 equally succint and clear ways to do the same thing, but one of the two is applicable in a strict superset of scenarios, always write it in the superset style, because code consistency is a worthwhile goal, and that leads to more consistency (it's worthwhile in that it reduces style friction and lowers learning curves).
That rule applies here.
Returning exceptions instead of returning them is weird, but whatever. (Why not return a ValidationResult object instead? Exceptions are usually intended to be thrown and caught).
But you could change your private methods to also return Optional instances which would make it easier to combine them. It would also avoid mixing throwing and returning and streams. Not sure if that is what you are looking for?
public class ValidBallsOnlyValidator implements Validator {
#Override
public Optional<ValidationException> validate(Event event)
return event.getToys()
.stream()
.filter(Optional::isPresent)
.findFirst()
.map(ex -> new ValidationException(ex.getMessage()));
}
private Optional<InvalidToyException> validateSingleToy(Toy toy) {
// In real code the optional here is kinda mandatory
Optional<Toy> potentialBall = castToyToBall(toy);
if(potentiallBall.isPresent()) {
return checkIfBallIsOfValidSize(potentialBall.get(), "exampleSize");
} else {
return Optional.of(new InvalidToyException("The toy is not a ball!"));
}
}
private Optional<InvalidToyException> checkIfBallIsOfValidSize(Toy toy, String size) {
if(toyTooLarge(toy, size)) return Optional.of(new InvalidToyException("The ball is too big!"));
return Optional.empty();
}
}
I am implementing a clean architecture in an application. I have a layer where the application/usecase classes which does the business logic and interacts with mutliple outgoing ports (interfaces to adapters for database calls, http api calls etc). The usecase returns a value/model to a web controller (Which renders the output to the user of the app).
Due to the complexity of the business logic there are many sad paths and a happy path (which are different types of objects with different state), as well as exceptions which can bubble up to the web controller. Exceptions are handled by an error handler with a generic http response and logged.
To return the happy and sad paths, I have wrapped it in an object of two fields. But I feel this is a code smell, as I will always have one field returning null. So in the web controller/servlet there are checks on the populated field to determine the correct http response. Is this a good way of doing this?
I have seen usecases, return the happy path, and all sad paths are given a specific business exception. This exception is caught at the web controller/servlet, and creates the http response using the exception message. I feel this is a code smell too, as we are using exceptions as control flow in the web controller/servlet.
I have seen other ways of returning multiple values such as
using a tuple
Having one object returned, but each field is a list, thus removing the need for a null as an empty field, and using an empty list
Using a map
Are there any other ways of returning multiple values, without having null fields or using exceptions (as explained above)?
Are there any other ways of returning multiple values, without having
null fields or using exceptions (as explained above)?
In Java (and POO languages) the usual way to do it is inheritance.
Probably sooner rather than later you'll fall into the Expression problem, that is, you must be careful when to include a process in your class hierarchy, and when to define that process in isolation.
If your process makes sense in the hierarchy, define it in it:
abstract class Response {
abstract boolean isSuccess();
abstract String getMessage();
}
class ErrorResponse extends Response {
boolean isSucess() { return false; }
String getMessage() { return "Something went wrong."; }
}
class SuccessResponse extends Response {
boolean isSucess() { return true; }
String getMessage() { return "Everything went well."; }
}
But you can't expect your hierarchy to contain the logic for any situation, so you can use introspection. Eg. in some view controller:
Color getResponseColor(Response rs) {
if(rs instanceof NetworkErrorResponse || rs instanceof ServerErrorResponse) {
return Colors.WITHOUT_SERVICE_COLOR;
}
return rs.isSuccess() ? Colors.SUCCESS_COLOR: Colors.ERROR_COLOR;
}
As you can see, including color decision making in the class hierarchy wouldn't make much sense.
Finally, since you are going to serialize your messages, you must make sure that the transport protocol supports inheritance.
There are methods in classes like "addSomething()". This can be successful or not successful. The status of the success can therefore be displayed with a boolean return value. But sometimes a method invocation can fail because of several reasons. "false" displays that, but only in a general manner. Sometimes the programmer wants to know the reason, why something failed. Is it, for this purpose, useful to provide an own report class that offers functionality like that?
public class Report {
private final boolean success;
private final String message;
public Report(boolean success) {
this.success = success;
this.message = "empty message";
}
public Report(boolean success, String message) {
this(success);
this.message = message;
}
public boolean wasSuccessful() {
return success;
}
public String getMessage() {
return message;
}
}
Then you can decide if you want to get a general success report with "wasSuccessful()" or if you also want to log the exact reason with "getMessage()".
Is it, for this purpose, useful to provide an own report class that offers functionality like that?
"Usefulness" is subjective. If the above is what nicely solves your specific problem, then of course it is useful, and might be a good approach.
But in general, failure in Java is typically modelled by using exceptions of some wort.
Therefore, in many situations you simply go with void methods. As: the method just returning means: "all fine". Otherwise, if there was some problem, the method throws an exception at you.
Now, if on the other hand, you have situations where a method might pass or fail, and both outcomes are fully okay (for example if some method checks whether an optional parameter is present), then sure: your approach can be useful. You simply allow to add new Report objects for each method invocation that matters to you. And then whoever calls the method can create Report objects and add them to some context-specific ReportCollector.
But note: the real issue in my eyes: when you think about programmatically collecting (and using) such "progress" information, then message strings quickly turn into a problem. There is a good reason why people sometimes use numerical error ids: to enable programmatic handling of such situations. Strings only carry meaning for humans who read them.
Your code can't do much with strings. Remember: doing a contains("this") or contains("that") to determine how to react to error (messages) later on, that is a real anti pattern!
You can try to use smth like Either pattern.
It's used like Either<Report,Error> in each moment you will have either a valid report or an object with errors.
In my understanding, code testing is to test whether results are right, like a calculator, I need to write a test case to verify if the result of 1+1 is 2.
But I have read many test cases about verifying the number of times a method is called. I'm very confused about that. The best example is what I just saw in Spring in Action:
public class BraveKnight implements Knight {
private Quest quest;
public BraveKnight(Quest quest) {
this.quest = quest;
}
public void embarkOnQuest() {
quest.embark();
}
}
public class BraveKnightTest {
#Test
public void knightShouldEmbarkOnQuest() {
Quest mockQuest = mock(Quest.class);
BraveKnight knight = new BraveKnight(mockQuest);
knight.embarkOnQuest();
verify(mockQuest, times(1)).embark();
}
}
I really have no idea about why they need to verify the embark() function is called one time. Don't you think that embark() will certainly be invoked after embarkOnQuest() is called? Or some errors will occur, and I will notice error messages in the logs, which show the error line number, that can help me quickly locate the wrong code.
So what's the point of verifying like above?
The need is simple: to verify that the correct number of invocations were made. There are scenarios in which method calls should not happen, and others in which they should happen more or less than the default.
Consider the following modified version of embarkOnQuest:
public void embarkOnQuest() {
quest.embark();
quest.embarkAgain();
}
And suppose you are testing error cases for quest.embark():
#Test
public void knightShouldEmbarkOnQuest() {
Quest mockQuest = mock(Quest.class);
Mockito.doThrow(RuntimeException.class).when(mockQuest).embark();
...
}
In this case you want to make sure that quest.embarkAgain is NOT invoked (or is invoked 0 times):
verify(mockQuest, times(0)).embarkAgain(); //or verifyZeroInteractions
Of course this is one other simple example. There are many other examples that could be added:
A database connector that should cache entries on first fetch, one can make multiple calls and verify that the connection to the database was called just once (per test query)
A singleton object that does initialization on load (or lazily), one can test that initialization-related calls are made just once.
Consider the following code:
public void saveFooIfFlagTrue(Foo foo, boolean flag) {
if (flag) {
fooRepository.save(foo);
}
}
If you don't check the number of times that fooRepository.save() is invoked , then how can you know whether this method is doing what you want it to?
This applies to other void methods. If there is no return to a method, and therefore no response to validate, checking which other methods are called is a good way of validating that the method is behaving correctly.
Good question. You raise a good point that mocking can be overly circuitous when you can just check the results. However, there are contexts where this does lead to more robust tests.
For example, if a method needs to make a call to an external API, there are several problems with simply testing the result:
Network I/O is slow. If you have many checks like this, it will slow down your test case
Any round-trip like this would have to rely on the code making the request, the API, and the code interpreting the API's response all to work correctly. This is a lot of failure points for a single test.
If something stupid happens and you accidentally make multiple requests, this could cause performance issues with your program.
To address your sub-questions:
Don't you think that embark() will certainly be invoked after embarkOnQuest() called?
Tests also have value in letting you refactor without worry about breaking things. This is obvious now, yes. Will it be obvious in 6 months?
I really have no idea about why they need to verify the embark()
function is called one time
Verifying an invocation on a mock for a specific number of times is the standard way how Mockito works as you invoke Mockito.verify().
In fact this :
verify(mockQuest, times(1)).embark();
is just a verbose way to write :
verify(mockQuest).embark();
In a general way, the verification for a single call on the mock is what you need.
In some uncommon scenarios you may want to verify that a method was invoked a specific number of times (more than one).
But you want to avoid using so specific verifications.
In fact you even want to use verifying as few as possible.
If you need to use verifying and besides the number of invocation on the mock, it generally means two things : the mocked dependency is too much coupled to the class under
test and or the method under test performs too many unitary tasks that produce only side effects.
The test is so not necessary straight readable and maintainable. It is like if you coded the mock flow in the verifying invocations.
And as a consequence it also makes the tests more brittle as it checks invocation details not the overall logic and states.
In most of cases, a refactoring is the remedy and cancel the requirement to specify a number of invocation.
I don't tell that it is never required but use it only as it happens to be the single decent choice for the class under test.
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 authenticate(Client client) method in some class. The authentication could fail for a number of reasons, and I want to return a simple boolean for control flow, but also return a String message for the user. These are the possibilities I can think of:
Return a boolean, and pass in a StringBuilder to collect the message. This is the closest to a C-style way of doing it.
Throw an exception instead of returning false, and include the message. I don't like this since failure is not exceptional.
Create a new class called AuthenticationStatus with the boolean and the String. This seems like overkill for one small method.
Store the message in a member variable. This would introduce a potential race condition, and I don't like that it implies some state that isn't really there.
Any other suggestions?
Edit Missed this option off
Return null for success - Is this unsafe?
Edit Solution:
I went for the most OO solution and created a small AuthenticationResult class. I wouldn't do this in any other language, but I like it in Java. I also liked the suggestion
of returning an String[] since it's like the null return but safer. One advantage of the Result class is that you can have a success message with further details if required.
Returning a small object with both the boolean flag and the String inside is probably the most OO-like way of doing it, although I agree that it seems overkill for a simple case like this.
Another alternative is to always return a String, and have null (or an empty String - you choose which) indicate success. As long as the return values are clearly explained in the javadocs there shouldn't be any confusion.
You could use exceptions....
try {
AuthenticateMethod();
} catch (AuthenticateError ae) {
// Display ae.getMessage() to user..
System.out.println(ae.getMessage());
//ae.printStackTrace();
}
and then if an error occurs in your AuthenticateMethod you send a new AuthenticateError (extends Exception)
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.
Some more options:
Return an separate enum value for each type of failure. The enum object could contain the message
Return an int and have a separate method that looks up the appropriate message from an array
create a generic utility tuple class that can contains two values. Such a class can be useful in many more places.
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;
}
}
You could return a Collection of error messages, empty indicating that there were no problems. This is a refinement of your third suggestion.
I personally think creating a new class called AuthenticationStatus with the boolean and the String is the most Java like way. And while it seems like overkill (which it may well be) it seems cleaner to me and easier to understand.
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.)
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.
Is this the only method where you have such a requirement? If not, just generate a general Response class with an isSuccessful flag and a message string, and use that everywhere.
Or you could just have the method return null to show success (not pretty, and does not allow returning a success AND a message).
I would most probably go for something like :
class SomeClass {
public int authenticate (Client client) {
//returns 0 if success otherwise one value per possible failure
}
public String getAuthenticationResultMessage (int authenticateResult) {}
//returns message associated to authenticateResult
}
With this "design", you can ask for a message only when authentication fails (which I hope is the scenario that occurs 99,99% of time ;))
It may also be of good practice to delegate message resolution to another Class. But it depends of your application needs (mostly, does it need i18n ?)
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
Successful authentication should be the "normal" case, so an authentication failure is the exceptional case.
What are the different status strings for the user anyway. I can see only two, success or failure. Any further information is a potential security issue.
Another advantage of the solution with exceptions is that it cannot be called in the wrong way and the failure case is more obvious. Without exceptions, you write:
if (authenticate()) {
// normal behaviour...
}
else {
// error case...
}
You can accidently call the method ignoring the return value. The "normal behaviour" code is then executed without successful authentication:
authenticate();
// normal behaviour...
If you use exceptions, that cannot happen. If you decide to not use exceptions, at least name the method so that it is clear that it returns a state, e. g.:
if (isAuthenticated()) {
//...
}
There are a lot of good answers here so I will keep it short.
I think failure of a user to authenticate can be considered a valid case for a checked exception. If your style of programming favoured handling exceptions then there would be no reason not to do this. It also removes the "How to return multiple values from a method, my method does one thing It authenticates a user"
If you are going to return multiple values then spend 10 minutes creating a generic PairTuple (can also be more than a pair TripleTuple, I won't repeat the example listed above) and return your values that way.
I hate having small dto style objects to return various multiple values they just clutter the place.
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.
Return the Object. It allows you to put additional functionality into the Class if you need it. Short lived objects in Java are quick to create and collect.
I would choose the Exception option in first place.
But, in second place, I would prefer the C-style technique:
public boolean authenticate(Client client, final StringBuilder sb) {
if (sb == null)
throw new IllegalArgumentException();
if (isOK()) {
sb.append("info message");
return true;
} else {
sb.append("error message");
return false;
}
}
This is not so strange and it's done in many places in the framework.
Instead of creating a special object for return type, I usually just return an array where all the returned information is stored. The benefit is that you can extend this array with new elements without creating new types and mess. The downside you have to know exactly what elements should present when array is returned from particular method to parse it correctly. Usually I agree on certain structure, like first element is always Boolean indication success, second is String with description, the rest is optional.
Example:
public static void main(String[] args)
{
Object[] result = methodReturningStatus();
if(!(Boolean)result[0])
System.out.println("Method return: "+ result[1]);
}
static Object[] methodReturningStatus()
{
Object[] result = new Object[2];
result[0] = false;
result[1] = "Error happened";
return result;
}