我想知道我的方法的签名应该如何,以便优雅地处理不同类型的故障。尝试[结果],IO [结果],应该使用[错误,结果],我应该在最后使用
这个问题在某种程度上是我已经有很多关于Scala错误处理的问题的总结。你可以在这里找到一些问题:
- Throwing exceptions in Scala, what is the "official rule"
- Either, Options and for comprehensions
- Either monadic operations
现在,我的理解如下:
- 要么可以作为结果包装的方法调用,失败
- 尝试是biaised无论是权上的失败是一个非致命的异常
- IO(scalaz)有助于建立一个处理IO操作的纯方法
- 所有3容易在为理解
- 的全部可用3不容易混合的一个,因为不兼容flatMap方法
- 在功能性语言研究,我们通常不会抛出异常,除非他们是致命的
- 我们应该抛出异常的真正特殊的理解条件。我想这是尝试
- 创建将Throwable先后为JVM性能为代价的做法,它不打算用于业务流程CONTROLE
库层现在
请考虑我有一个UserRepository
。 UserRepository
存储用户并定义findById
方法。以下故障可能发生:
- 致命故障(
OutOfMemoryError
) - 一个IO失败,因为数据库不存取/可读
此外,用户可能会丢失,从而导致Option[User]
结果
使用存储库的JDBC实现,可以抛出SQL,非致命异常(约束违规或其他),因此使用Try可能有意义。
当我们正在处理IO操作时,如果我们需要纯函数,IO monad也是有意义的。
所以结果类型可能是:
Try[Option[User]]
IO[Option[User]]
- 别的东西吗?
服务层
现在介绍一个业务层,UserService
,它提供了一些方法updateUserName(id,newUserName)
使用先前定义的存储库findById
。
以下故障可能发生:
- 传播到服务层的所有库失败
- 业务错误:无法更新的用户不存在
- 业务错误的用户名:新用户名太短
那么结果类型可能是:
Try[Either[BusinessError,User]]
IO[Either[BusinessError,User]]
- 别的东西吗?
这里的BusinessError不是Throwable,因为它不是一个特殊的失败。
使用换内涵
我想使用-推导方法调用相结合,以保持。
我们不能轻易地将不同的monads混合在一个for-comprehension中,所以我想我应该对我所有的操作都有某种统一的返回类型吗?
我只是想知道,在现实世界的Scala应用程序中,如何在不同种类的故障可能发生时继续使用for-comprehensions,取得成功。
现在,换修真我工作得很好,用服务和信息库,所有返回Either[Error,Result]
但所有不同类型的故障被熔化在一起,成为一种哈克来处理这些故障。
您是否定义了不同种类的monads之间的隐式转换以便能够使用for-comprehensions?
您是否定义了自己的monads来处理故障?
顺便说一下,也许我会尽快使用异步IO驱动程序。 所以我想我的返回类型可能是更加复杂:IO[Future[Either[BusinessError,User]]]
任何意见将是受欢迎的,因为我真的不知道干什么用的,而我的应用程序并不花哨:它只是一个API,其中我应该能够区分可以向客户端显示的业务错误和技术错误。我试图找到一个优雅和纯粹的解决方案。
能否请你发表一些代码,你最终如何写这个?我非常感兴趣,因为我有一个类似的模式。我的斯卡拉技能并不是我希望他们成为的......我很难理解这些课程。 – costa 2017-08-21 08:11:10