2

We're using Vavr in our project to ease exception handling. I always make sure that a method that returns a Try can never throw anything, like so:

public Try<Result> someSafeMethod() {
  return Try.of(() -> someService.generateId())
           .map(someOtherService::getValueForId)
           .map(mappingService::mapToResult);
}

but some of my colleagues would implement it like this:

public Try<Result> someSafeMethod() {
  String generatedId = someService.generateId(); // <- Might throw an Exception that is not caught by the Try clause
  return Try.of(() -> someOtherService.getValueForId(generatedId))
           .map(mappingService::mapToResult);
}

Arguing that if something is wrong with the generation of the ID that they would rather the exception is thrown instead of the returned Try being a failure.

The documentation does not prohibit that a method returning a Try should not throw, but it does state that:

Try is a monadic container type which represents a computation that may either result in an exception, or return a successfully computed value.

Am I being too too strict? Imagine you would use an API where all methods return a Try, wouldn't it be bad when they still throw?

Titulum
  • 9,928
  • 11
  • 41
  • 79
  • 3
    Personally I would prefer your view that all "failure" is returned via the return value. From the perspective of a user of an interface declaring a Try as return value, I would expect that I can rely on all failure being returned that way (otherwise I would have to implement two different handlings for the failure). – Christian Fries Apr 07 '20 at 10:50
  • 2
    It _can_ according to the language spec, but it really _shouldn't_ as a matter of good practice: You're adopting a different control model and should use that consistently. – chrylis -cautiouslyoptimistic- Apr 07 '20 at 11:04

1 Answers1

3

You are not being too strict.

The whole point of using Try as a return value is the resulting benefit of programming with total functions and having a composable way of handling errors. Total functions are functions that always return a value of the declared return type for all possible argument values. If they are throwing exceptions, their functions are not total functions anymore, and—without explicit error handling—non-totality will propagate transitively through their code, 'infecting' all other functions that call them with non-totality. As a result, they will end up with code that will be much harder to reason about and it will take more effort to make sure it is correct.

Throwing exceptions while using Try would also defy the purpose of using Try in the first place and it would unnecessarily complicate the code consuming their API for no obvious benefit, because the API consumers will have to do error handling both using Try and catching exceptions.

Nándor Előd Fekete
  • 6,988
  • 1
  • 22
  • 47