scala - 什么是 ZIO 错误通道以及如何了解其中的内容?
问题描述
ZIO
( https://zio.dev/ ) 是一个 scala 框架,其核心是ZIO[R, E, A]
数据结构,其站点为三个参数提供以下信息:
齐奥
数据类型具有
ZIO[R, E, A]
三个类型参数:
R
- 环境类型。效果需要 type 的环境R
。如果此类型参数为Any
,则表示效果没有要求,因为您可以使用任何值(例如,单位值()
)运行效果。E
- 故障类型。效果可能会因 type 的值而失败E
。一些应用程序将使用Throwable
. 如果此类型参数为Nothing
,则表示效果不会失败,因为没有 Nothing 类型的值。A
- 成功类型。效果可能会以 type 的值成功A
。如果此类型参数为Unit
,则表示效果不会产生有用的信息,如果是Nothing
,则表示效果将永远运行(或直到失败)。
很容易得到什么A
是:它是函数在名义情况下返回的值,即我们编写函数的原因。
R
是一种依赖注入 - 一个有趣的话题,但我们可以忽略它,始终ZIO
将其设置为Any
(实际上IO[E, A] = ZIO[Any, E, A]
在 lib 中有一个别名)。
因此,它仍然E
是用于错误的类型(著名的错误通道)。我大概明白这IO[E, A]
是一种Either[E, A]
,但处理效果(这很棒)。
我的问题是:为什么我应该在我的应用程序中到处使用错误通道,我如何决定错误通道中应该包含什么?
解决方案
1/ 为什么用错误通道影响管理?
作为开发人员,您最艰巨的任务之一是确定您的应用程序中哪些是错误,哪些不是 - 或者更准确地说,是发现故障模式:标称路径(即代码的目标)是什么,预期是什么应用程序可以稍后以某种方式处理的错误,以及应用程序无法处理的意外错误。这个问题没有明确的答案,它取决于应用程序和上下文,所以你,开发者,需要决定。
但最困难的任务是构建一个信守承诺的应用程序(你的承诺,因为你选择了什么是错误,什么是名义路径),这并不奇怪,因此用户、管理员和开发人员——包括你的未来两周 - 知道代码在大多数情况下会做什么,而无需猜测并有机构来适应该行为,包括响应错误。
这很难,您需要一个系统的流程来处理所有可能的情况,而无需进行。
bi-monad中的错误通道IO
(因此ZIO
)可以帮助您完成该任务:IO
monad 可以帮助您跟踪效果,这是大多数错误的来源,错误通道明确说明了可能的错误情况,等等如果可以的话,应用程序的某些部分有代理来处理它们。您将能够通过明确的故障模式以纯粹、一致、可组合的方式管理您的效果。此外,在 的情况下ZIO
,您可以非常轻松地轻松导入遗留 java 之类的非纯代码:
val pure = ZIO.effect(someJavaCodeThrowingException)
2/我如何选择什么是错误?
因此,错误通道提供了一种将问题的答案编码到what if?
处理该代码的未来开发人员的方法。“如果数据库宕机了怎么办?” “有一个DatabaseConnectionError
”。但是what if
对于您的用例,对于当前应用程序级别,所有这些都不相同。“如果找不到用户怎么办?” - 啊,这可能是低“存储库”级别的完全预期的答案(就像没有找到任何东西的“查找”),或者它可能是其他级别的错误(比如当你在这个过程中时)验证用户,它应该真的在那里)。在第一种情况下,您可能不会使用错误通道:它是标称路径,有时您找不到任何东西。在第二种情况下,您可能会使用错误通道 ( UserNotFoundError
)。
正如我们所说,错误通道中的错误通常what if
是您可能想要在应用程序中处理的问题,而不是在该功能级别。第一个示例DatabaseConnectionError
可能是在应用程序中捕捉到更高的位置,并导致用户消息(如“请重试”)和系统管理员的通知电子邮件(“快,看看,如果这里有问题”)。这UserNotFoundError
可能会在登录表单中作为用户的错误消息进行管理,例如“错误的登录名或密码,重试或使用该过程恢复凭据”。
所以这些情况(名义上的和预期的错误)是容易的部分。但是有一些what if
问题是你的应用程序,无论级别如何,都不知道如何回答。“如果我在尝试分配该对象时遇到内存异常怎么办?” 我没有任何线索,实际上,即使我有线索,这也超出了我要为该应用程序处理的事情的范围。所以这些错误不会进入错误通道。我们称它们为失败,并在它们发生时使应用程序崩溃,因为应用程序现在很可能处于未知、危险、僵尸状态。
同样,该选择(标称路径/错误通道/故障)是您的选择:两个应用程序可以做出不同的选择。例如,一次性数据处理应用程序然后丢弃它很可能会将所有非标称路径视为失败。有一个开发人员可以实时捕获案例并确定它是否重要(请参阅:Shell、Python 以及任何大量使用该策略的脚本 - 好的,有时即使没有开发人员来捕获错误:)。在幽灵的另一端,NASA 开发人员将所有内容都放入了错误通道 (+),甚至是内存损坏。因为这是一个预期错误,所以应用程序需要知道如何处理并继续。
(+)注意:AFAIK他们不使用zio(现在),但是关于什么是错误的决策过程是相同的,即使在C中也是如此。
更进一步,我 (@fanf42) 在Scala.io会议上发表了演讲。演讲“应用程序中的系统错误管理”在此处提供法语 版本。是的,法语,我知道 - 但是这里有英文版的幻灯片!您可以 ping 我(请参阅幻灯片末尾附近的联系信息)。
推荐阅读
- php - 可以从 CakePHP 2.8 迁移到 4.x
- bash - 为什么“test -e”在我的 bash 脚本中不能正常工作?
- python - 除数时Python计算器错误
- c++ - 在 C++ 中连接内存块
- angular - 如何在角度 8 中为 viewchild 元素引用编写点击事件
- go - Golang http 客户端被重定向到登录 bitbucket 私有 URL,而不是提供身份验证失败
- python - 使用 igraph 和 leidenalg 在 Python 中查找具有数百万个顶点的大型图中的社区
- vue.js - 我的事件没有从我的父组件发出
- javascript - 在客户端分配带有不受信任数据的 JavaScript 变量是否是 XSS 漏洞?
- flutter - 如何在 FutureBuilder 小部件的 builder 方法中获取未来的结果?