Let's suppose we have an if statement like this:
public A save(A a) {
if (isValid.test(a)) {
return aRepository.save(a);
}
throw new ANotValidException("A is not valid");
}
isValid is a Predicate and it may look like:
private Predicate<A> isValid = (a) -> (a != null);
What do you think? Can I make it cleaner somehow?
I mean, for example using an Optional to reduce it in 1 line with an .orElseThrow();
A more precise version using Optional and throwing a custom Exception shall be :
public A save(A a) throws ANotValidException { // throws the custom exception
return Optional.ofNullable(a) // since your predicate is to check for not null
.map(aRepository::save)
.orElseThrow(() -> new ANotValidException(a + "A is not valid"));
}
An Optional can make the code more readable, particularly around the use of your predicate object:
public A save(A a) {
return Optional.ofNullable(a)
.filter(isValid)
.map(aRepository::save)
.orElseThrow(() -> new ANotValidException("A is not valid"));
}
You can also get rid of the predicate altogether as it's simple enough to use Objects::nonNull (unless your real predicate's test is more complex). And in that case, keeping your current condition checks would probably make more sense (in my opinion).
One could argue that it would be more natural to read it in the opposite order, that is first handle the validation and the result of it and then move on to saving the object.
public A save(A a) {
if (!isValid.test(a)) {
throw new ANotValidException("A is not valid");
}
return aRepository.save(a);
}
Related
I have a lot of this kind of code in my project:
if (entityRepository.saveEntity(new RemoteEntityBuilder()
.appId(appId)
.nameSpace(nameSpace)
.entityType(entityType)
.entityId(entityId)
.blobs(Lists.list(new RemoteBlobBuilder()
.blobName(blobName)
.blobStream(new SimpleRemoteInputStream(inputStream))
.build()))
.build()) != null) {
// Meaning entity was saved
} else {
// Meaning entity was not saved
}
The saveEntity method returns either NULL (if operation failed) or the object/entity that was saved if the operation was successful. My question is, is there a better way to represent this code with the use of != null for instance:
if(entityRepository.saveEntity(...)) {
}
Or something else.
UPDATE:
The saveEntity method is this
#Override public RemoteEntity saveEntity(RemoteEntity entity)
throws NotBoundException, RemoteException {
RemoteEntities remoteEntities = saveEntities(new RemoteEntity[] {entity});
return remoteEntities != null ? remoteEntities.entities().stream().findFirst().get() : null;
}
Here's how it looks now thanks to YCF_L:
entityRepository.saveEntity(new RemoteEntityBuilder()
.appId(appId)
.nameSpace(nameSpace)
.entityType(entityType)
.entityId(entityId)
.blobs(Lists.list(new RemoteBlobBuilder()
.blobName(blobName)
.blobStream(new SimpleRemoteInputStream(inputStream))
.build()))
.build()).ifPresentOrElse(remoteEntity -> {
pubSubService.updated(remoteEntity.appId(), remoteEntity.nameSpace(),
remoteEntity.entityType(), remoteEntity.entityId());
setStatus(Status.SUCCESS_CREATED);
}, () -> {
setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
});
Here's how the code looks in the IDE (looks pretty clean to me):
I would use Optional in your case :
public Optional<RemoteEntity> saveEntity(RemoteEntity entity) throws NotBoundException, RemoteException {
RemoteEntities remoteEntities = saveEntities(new RemoteEntity[]{entity});
return remoteEntities.entities().stream()
.findFirst();
}
and then :
if(entityRepository.saveEntity(...).isPresent()) {
...
}
In fact you have many choices with Optional, you can use ifPresent also :
entityRepository.saveEntity(...)
.ifPresent(r -> ..)
Or throw an exception:
entityRepository.saveEntity(...)
.orElseThrow(() -> ..)
What is "better" may be a matter of opinion.
Given your example, the way to achieve that would be to create another method that calls saveEntity() and returns true or false. (I do wonder why saveEntity() doesn't throw an exception if its operations fails -- that would be more normal in my experience.)
If you simply don't like that the comparison is hard to spot, you might reverse the order:
if (null != entityRepository.saveEntity(...))
I would probably move the call outside of the if entirely, as I find side effects in conditionals potentially confusing.
RemoteEntity myEntity = entityRepository.saveEntity(...)
if (myEntity != null) ...
I was just wondering when do we need to choose Optional over if else or nested null check. say for example is there any advantage of one another below or do you think the Optional could be an overkill
String.valueOf(Optional.ofNullable(itemKey).map(ItemKey::getId).orElse(null));
vs
String.valueOf(itemKey == null ? null : itemKey.getId());
I always keen to use the Optional.of or Optional.ofNullable when I had to pick nested item of a given object like below,
private String formatCurrency(String symbol, BigDecimal value) {
return Optional.ofNullable(value)
.map(BigDecimal::doubleValue)
.map(Object::toString)
.map(val -> symbol + val.replaceAll(REGEX_REMOVE_TRAILING_ZEROS, "$2"))
.orElse("");
}
Can I please know where in the code the Optional is absolutely unnecessary.
If you already have itemKey in your code, there is no meaning of transforming it to an Optional, it just makes the code more complex. However, if you want to use optionals, I think it'd be more appropriate to do something like this:
public Optional<ItemKey> getItemKey() {
if (...) {
return Optional.of(new ItemKey());
}
return Optional.empty()
}
public void mainCode() {
String id = getItemKey().map(ItemKey::getId).orElse(null);
}
I have an Try<Option<Foo>>. I want to flatMap Foo into a Bar, using it using an operation that can fail. It's not a failure if my Option<Foo> is an Option.none(), (and the Try was a success) and in this case there's nothing to do.
So I have code like this, which does work:
Try<Option<Bar>> myFlatMappingFunc(Option<Foo> fooOpt) {
return fooOpt.map(foo -> mappingFunc(foo).map(Option::of) /* ew */)
.getOrElse(Try.success(Option.none()); // double ew
}
Try<Bar> mappingFunc(Foo foo) throws IOException {
// do some mapping schtuff
// Note that I can never return null, and a failure here is a legitimate problem.
// FWIW it's Jackson's readValue(String, Class<?>)
}
I then call it like:
fooOptionTry.flatMap(this::myFlatMappingFunc);
This does work, but it looks really ugly.
Is there a better way to flip the Try and Option around?
Note 1: I actively do not want to call Option.get() and catch that within the Try as it's not semantically correct. I suppose I could recover the NoSuchElementException but that seems even worse, code-wise.
Note 2 (to explain the title): Naively, the obvious thing to do is:
Option<Try<Bar>> myFlatMappingFunc(Option<Foo> fooOpt) {
return fooOpt.map(foo -> mappingFunc(foo));
}
except this has the wrong signature and doesn't let me map with the previous operation that could have failed and also returned a successful lack of value.
When you are working with monads, each monad type combine only with monads of same type. This is usually a problem because the code will come very unreadable.
In the Scala world, there are some solutions, like the OptionT or EitherT transformers, but do this kind of abstractions in Java could be difficult.
The simple solution is to use only one monad type.
For this case, I can think in two alternatives:
transform fooOpt to Try<Foo> using .toTry()
transform both to Either using .toEither()
Functional programmers are usually more comfortable with Either because exceptions will have weird behaviors, instead Either usually not, and both works when you just want to know why and where something failed.
Your example using Either will look like this:
Either<String, Bar> myFlatMappingFunc(Option<Foo> fooOpt) {
Either<String, Foo> fooE = fooOpt.toEither("Foo not found.");
return fooE.flatMap(foo -> mappingFunc(foo));
}
// Look mom!, not "throws IOException" or any unexpected thing!
Either<String, Bar> mappingFunc(Foo foo) {
return Try.of(() -> /*do something dangerous with Foo and return Bar*/)
.toEither().mapLeft(Throwable::getLocalizedMessage);
}
I believe this is simply a sequence function (https://static.javadoc.io/io.vavr/vavr/0.9.2/io/vavr/control/Try.html#sequence-java.lang.Iterable-) that you are looking for:
Try.sequence(optionalTry)
You can combine Try.sequence and headOption functions and create a new transform function with a little better look, in my opinion, also you can use generic types to get a more reusable function :) :
private static <T> Try<Option<T>> transform(Option<Try<T>> optT) {
return Try.sequence(optT.toArray()).map(Traversable::headOption);
}
If I understand correctly, you want to :
keep the first failure if happens
swap the second when mapping to json for an empty option.
Isn t it simpler if you decompose your function in such a way:
public void keepOriginalFailureAndSwapSecondOneToEmpty() {
Try<Option<Foo>> tryOptFoo = null;
Try<Option<Bar>> tryOptBar = tryOptFoo
.flatMap(optFoo ->
tryOptionBar(optFoo)
);
}
private Try<Option<Bar>> tryOptionBar(Option<Foo> optFoo) {
return Try.of(() -> optFoo
.map(foo -> toBar(foo)))
.orElse(success(none())
);
}
Bar toBar(Foo foo) throws RuntimeException {
return null;
}
static class Bar {
}
static class Foo {
}
The solution of throughnothing and durron597 helped me there. This is my groovy test case:
def "checkSomeTry"() {
given:
def ex = new RuntimeException("failure")
Option<Try<String>> test1 = Option.none()
Option<Try<String>> test2 = Option.some(Try.success("success"))
Option<Try<String>> test3 = Option.some(Try.failure(ex))
when:
def actual1 = Try.sequence(test1).map({ t -> t.toOption() })
def actual2 = Try.sequence(test2).map({ t -> t.toOption() })
def actual3 = Try.sequence(test3).map({ t -> t.toOption() })
then:
actual1 == Try.success(Option.none())
actual2 == Try.success(Option.some("success"))
actual3 == Try.failure(ex)
}
I have not doubt that there is a solution posted for this, but I can't find the search term retrieve it, so if it does exist please point me to the duplicate and mark this as such.
I have a chain of methods performing various validation checks on a button click event, I display a message if the validation has failed, currently my solution is to then pass back a boolean so that if the method failed the remaining methods will not run.
I don't like this, when I have several methods all passing back booleans my code starts to smell.
is there a better solution to this? (I'd don't want to use a instance variable)
Example of the code as it currently stands:
private void SUBMIT_BUTTON_CLICK(){
if(validate()){
//Do Stuff
}
}
private boolean validate(){
return checkOne() && checkTow() && checkThree() && checkFour();
}
private boolean checkOne(){
if (someCheckFails) {
print(warning);
return false;
} else {
return true;
}
}
private boolean checkTow(){
if (someCheckFails) {
print(warning);
return false;
} else {
return true;
}
}
private boolean checkThree(){
if (someCheckFails) {
print(warning);
return false;
} else {
return true;
}
}
private boolean checkFour(){
if (someCheckFails) {
print(warning);
return false;
} else {
return true;
}
}
Convenionally you would use exceptions:
void check1(Foo value) {
if(some test on value) {
throw new ValidationException(...);
}
}
try {
check1(value);
check2(value);
} catch (ValidationException e) {
// deal with validation failure
}
A bonus here is that the exception can carry information about the failure. Your boolean false just says "it failed", with no explanation.
Another bonus, of course, is that you're free to pass the exception higher up the call stack, where some other code can deal with it.
Some people worry about the cost of building exceptions (or more accurately, collecting that stack trace contained within). I'd advise not worrying about it unless you get performance problems and profiling points the finger at exceptions.
There are alternatives though. For example your validation could return Optional<ValidationError>:
Optional<ValidationError> check1(Foo value) {
if(some test on value) {
return Optional.of(new ValidationError(...));
} else {
return Optional.empty();
}
}
Then...
Optional<ValidationError> validationResult =
check1(value)
.orElseGet( () -> check2(value))
.orElseGet( () -> check3(value));
You could, of course, loop through a list of validators, rather than hard-code like this.
Some of the functional programming libraries (e.g. vavr) include an Either class, which can be used in a similar way, where instead of being either an error or empty(), it's an error or a success value.
Or you could stick with methods returning boolean, but use them as Predicates:
List<Predicate<Foo>> checks = Arrays.asList(
f -> check1(f),
f -> check2(f),
f -> check3(f)
);
(Or the equivalent with method references e.g. this::check1)
checks.stream().allMatch(check -> check.test(value));
As you can see, there are tons of possibilities. But think about whether you're over-complicating. There's mostly nothing inherently wrong with the simple approach you already have -- although it is better, and more testable, to return a failure reason, rather than print it as a side-effect.
Chaining like you are currently doing is generally the best solution. It is easy to understand, efficient and (relatively) concise.
A couple of other ideas would be:
build an array of predicates and then iterate and call them, or
use exceptions and exception handling
but both of these have performance implications, and they will only give "cleaner" code if you have a vast number of predicates to evaluate.
Sometimes an inelegant solution is more elegant than looking for a clever solution.
Consider this: if I use exceptions, I can rewrite the validate() method
private boolean validate(){
return checkOne() && checkTow() && checkThree() && checkFour();
}
as
private void validate() throws ValidationException {
checkOne(); checkTow(); checkThree(); checkFour();
}
But how much have I actually gained here? It is still two lines of code. And if I were to follow Java's style rules it would be:
private void validate() throws ValidationException {
checkOne();
checkTow();
checkThree();
checkFour();
}
which is more lines than we started with. And we haven't considered the predicates themselves or the code that handles the validation exception.
Based on my comment: you're probably after exceptions.
Example (pseudo code):
void checkOne() {
if( check_fails ) {
throw new CheckOneException();
}
}
void checkTwo() {
if( check_fails ) {
throw new CheckTwoException();
}
}
void validate() {
checkOne();
checkTwo();
}
void SUBMIT_BUTTON_CLICK() {
try {
validate();
//Do Stuff
} catch( CheckOneException | CheckTwoException ) {
//handle the exceptions
}
}
Note that you might have to either declare the exceptions to be thrown or make them runtime exceptions.
Additionally you might want to use multiple catch-blocks if the handling depends on the type of exception. Alternatively you could also throw the same type of exception if that fits your needs.
Let's say I have a method which throws a runtime exception. I'm using a Stream to call this method on items in a list.
class ABC {
public void doStuff(MyObject myObj) {
if (...) {
throw new IllegalStateException("Fire! Fear! Foes! Awake!");
}
// do stuff...
}
public void doStuffOnList(List<MyObject> myObjs) {
try {
myObjs.stream().forEach(ABC:doStuff);
} catch(AggregateRuntimeException??? are) {
...
}
}
}
Now I want all items in the list to be processed, and any runtime exceptions on individual items to be collected into an "aggregate" runtime exception which will be thrown at the end.
In my real code, I am making 3rd party API calls which may throw runtime exceptions. I want to make sure that all items are processed and any errors reported at the end.
I can think of a few ways to hack this out, such as a map() function which catches and returns the exception (..shudder..). But is there a native way to do this? If not, is there another way to implement it cleanly?
In this simple case where the doStuff method is void and you only care about the exceptions, you can keep things simple:
myObjs.stream()
.flatMap(o -> {
try {
ABC.doStuff(o);
return null;
} catch (RuntimeException ex) {
return Stream.of(ex);
}
})
// now a stream of thrown exceptions.
// can collect them to list or reduce into one exception
.reduce((ex1, ex2) -> {
ex1.addSuppressed(ex2);
return ex1;
}).ifPresent(ex -> {
throw ex;
});
However, if your requirements are more complicated and you prefer to stick with the standard library, CompletableFuture can serve to represent "either success or failure" (albeit with some warts):
public static void doStuffOnList(List<MyObject> myObjs) {
myObjs.stream()
.flatMap(o -> completedFuture(o)
.thenAccept(ABC::doStuff)
.handle((x, ex) -> ex != null ? Stream.of(ex) : null)
.join()
).reduce((ex1, ex2) -> {
ex1.addSuppressed(ex2);
return ex1;
}).ifPresent(ex -> {
throw new RuntimeException(ex);
});
}
There are already some implementations of Try monad for Java. I found better-java8-monads library, for example. Using it, you can write in the following style.
Suppose you want to map your values and track all the exceptions:
public String doStuff(String s) {
if(s.startsWith("a")) {
throw new IllegalArgumentException("Incorrect string: "+s);
}
return s.trim();
}
Let's have some input:
List<String> input = Arrays.asList("aaa", "b", "abc ", " qqq ");
Now we can map them to successful tries and pass to your method, then collect successfully handled data and failures separately:
Map<Boolean, List<Try<String>>> result = input.stream()
.map(Try::successful).map(t -> t.map(this::doStuff))
.collect(Collectors.partitioningBy(Try::isSuccess));
After that you can process successful entries:
System.out.println(result.get(true).stream()
.map(t -> t.orElse(null)).collect(Collectors.joining(",")));
And do something with all the exceptions:
result.get(false).stream().forEach(t -> t.onFailure(System.out::println));
The output is:
b,qqq
java.lang.IllegalArgumentException: Incorrect string: aaa
java.lang.IllegalArgumentException: Incorrect string: abc
I personally don't like how this library is designed, but probably it will be suitable for you.
Here's a gist with complete example.
Here's a variation on the theme of mapping-to-exceptions.
Start with your existing doStuff method. Note that this conforms to the functional interface Consumer<MyObject>.
public void doStuff(MyObject myObj) {
if (...) {
throw new IllegalStateException("Fire! Fear! Foes! Awake!");
}
// do stuff...
}
Now write a higher-order function that wraps this and turns this into a function that might or might not return an exception. We want to call this from flatMap, so the way "might or might not" is expressed is by returning a stream containing the exception or an empty stream. I'll use RuntimeException as the exception type here, but of course it could be anything. (In fact it might be useful to use this technique with checked exceptions.)
<T> Function<T,Stream<RuntimeException>> ex(Consumer<T> cons) {
return t -> {
try {
cons.accept(t);
return Stream.empty();
} catch (RuntimeException re) {
return Stream.of(re);
}
};
}
Now rewrite doStuffOnList to use this within a stream:
void doStuffOnList(List<MyObject> myObjs) {
List<RuntimeException> exs =
myObjs.stream()
.flatMap(ex(this::doStuff))
.collect(Collectors.toList());
System.out.println("Exceptions: " + exs);
}
The only possible way I can imagine is to map values in a list to a monad, that will represent the result of your processing execution (either success with value or failure with throwable). And then fold your stream into single result with aggregated list of values or one exception with list of suppressed ones from the previous steps.
public Result<?> doStuff(List<?> list) {
return list.stream().map(this::process).reduce(RESULT_MERGER)
}
public Result<SomeType> process(Object listItem) {
try {
Object result = /* Do the processing */ listItem;
return Result.success(result);
} catch (Exception e) {
return Result.failure(e);
}
}
public static final BinaryOperator<Result<?>> RESULT_MERGER = (left, right) -> left.merge(right)
Result implementation may vary but I think you get the idea.