为什么在 LiftWeb/Scala 中使用 Box/Option 而不是 Exception?
case "user" :: "info" :: _ XmlGet _ =>
for {
id <- S.param("id") ?~ "id param missing" ~> 401
u <- User.find(id) ?~ "User not found"
} yield u.toXml
不是为什么
case "user" :: "info" :: _ XmlGet _ => User.find(S.param("id").openOrThrow(
new IllegalArgumentException("idParamMissing"))).toXml
不让 User.find
抛出类似 NotFoundException
的内容
So, I've been reading this article about Box usage in LiftWeb which seems so be part of the official documentation as it's linked through the source code comments.
My question is why is Box/Failure preferable to actually coding without null and throwing an Exception that would be caught at top level and transformed into an appropriate error code/message. So instead of
case "user" :: "info" :: _ XmlGet _ =>
for {
id <- S.param("id") ?~ "id param missing" ~> 401
u <- User.find(id) ?~ "User not found"
} yield u.toXml
why not
case "user" :: "info" :: _ XmlGet _ => User.find(S.param("id").openOrThrow(
new IllegalArgumentException("idParamMissing"))).toXml
and have User.find
throw something like NotFoundException
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
想象一下,您有一个方法执行某些可能会失败的操作,例如获取网页。
如果你想使用它,你需要
根据情况做或类似的事情。不过,这样做看起来还是可以的。但现在假设您想要对 URL 集合执行此操作。
好的,只要无法加载其中一页,就会返回一个空序列。如果我们希望收到尽可能多的信息怎么办?
现在我们的逻辑与错误处理代码混合在一起。
将此与以下内容进行比较:
使用
Option
或Box
(或Either
或 scalaz'Validation
)可以为您带来更多好处比抛出异常更有能力决定何时处理问题。除了例外情况,您只能遍历堆栈并捕获它作为那里的某个点。如果您将故障编码在类型中,您可以随身携带它,只要您愿意,并在您认为最合适的情况下处理它。
Imagine you have a method which does some operation which may potentially fail, for example fetching a web page.
If you want to use it, you need to do
or similar depending on the situation. Still, it looks somewhat okay to do so. But now imagine you want to do this for a collection of URLs.
Okay so this return an empty sequence whenever one of the pages could not be loaded. What if we’d like to receive as many as possible?
Now our logic is intermingled with error handling code.
Compare this to the following:
Using
Option
orBox
(orEither
or scalaz’Validation
) gives you way more power over deciding when to deal with a problem than throwing exceptions ever could.With exceptions you may only traverse the stack and catch it as some point there. If you encode the failure inside a type, you may carry it around with you as long as you like and deal with it in the situation you think is most appropriate.
如果抛出异常,唯一能做的就是捕获它。因此,如果页面的两个部分抛出异常,您将永远无法到达第二个部分。如果页面的一部分返回一个
Box
,而该部分恰好是Failure
,而第二部分不需要第一部分的返回值,那么您可以同时看到这两个部分。更一般地说,Box
有一个Exception
所缺乏的有用 API。If you throw an exception, the only thing you can do is catch it. So, if two parts of your page throw an exception, you won't ever get to the second one. If one part of your page returns a
Box
which happens to be aFailure
, and the second part doesn't need the return value of the first one, you can see both. More generally,Box
has a useful API whichException
lacks.