一个返回“Try”的方法允许抛出吗?

huangapple go评论80阅读模式
英文:

Is a method that returns a Try allowed to throw?

问题

我们在项目中使用Vavr来简化异常处理。我总是确保一个返回 Try的方法不会抛出任何异常,就像这样:

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

但是我的一些同事可能会这样实现:

public Try<Result> someSafeMethod() {
  String generatedId = someService.generateId(); // <- 可能会抛出未在 Try 语句中捕获的异常
  return Try.of(() -> someOtherService.getValueForId(generatedId))
           .map(mappingService::mapToResult);
}

他们认为,如果生成ID出现问题,他们宁愿抛出异常,而不是返回的 Try 失败。

文档没有禁止返回 Try 的方法抛出异常,但它确实声明了:

> Try 是一种单子容器类型,表示可能会导致异常或返回成功计算值的计算。

我是否过于严格?想象一下,如果您使用的 API 中的所有方法都返回 Try,当它们仍然抛出异常时,这是否会很糟糕?

英文:

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&lt;Result&gt; someSafeMethod() {
  return Try.of(() -&gt; someService.generateId())
           .map(someOtherService::getValueForId)
           .map(mappingService::mapToResult);
}

but some of my colleagues would implement it like this:

public Try&lt;Result&gt; someSafeMethod() {
  String generatedId = someService.generateId(); // &lt;- Might throw an Exception that is not caught by the Try clause
  return Try.of(() -&gt; 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?

答案1

得分: 3

你没有太过严格。

Try用作返回值的整个要点在于使用总函数进行编程的结果好处,并以可组合的方式处理错误。总函数是指对于所有可能的参数值,始终返回声明的返回类型值的函数。如果它们抛出异常,它们的函数就不再是总函数,而且在没有明确的错误处理的情况下,非全性将通过它们的代码传递,'感染'所有调用它们的其他函数,使得这些函数也变得不全。结果就是,他们最终会得到一段更难以推理的代码,并且需要更多的工作来确保其正确性。

在使用Try的同时抛出异常也将违背首次使用Try的目的,无端地使消费其API的代码变得更加复杂,因为API使用者将不得不同时使用Try进行错误处理和捕获异常。

英文:

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.

huangapple
  • 本文由 发表于 2020年4月7日 18:45:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/61078239.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定