效果系统(例如ZIO)的好处是什么



我很难理解什么是价值效应系统,比如ZIO或Cats effect。

  • 它不会使代码可读,例如:
val wrappedB = for {
a <- getA()  // : ZIO[R, E, A]
b <- getB(a) // : ZIO[R, E, B]
} yield b

对我来说可读性不比:

val a = getA()  // : A
val b = getB(a) // : B

我甚至可以说,后者更直接,因为调用函数会执行它,而不仅仅是创建一个效果或执行管道。

  • 延迟执行听起来并不令人信服,因为到目前为止我遇到的所有示例都只是立即执行管道。能够并行或多次执行效果可以通过更简单的方式实现IMHO,例如C#具有parallel.ForEach
  • 可组合性。函数可以在不使用效果的情况下合成,例如通过简单合成
  • 纯函数方法。最终,纯指令将被执行,所以它似乎只是假装DB访问是纯的。推理并没有帮助,因为尽管指令的构造是纯粹的,但执行它们却不是

我可能遗漏了一些东西,或者只是淡化了上面的好处,或者在某些情况下(例如,复杂领域),好处可能更大。使用特效系统的最大卖点是什么?

因为它可以很容易地处理副作用。从你的例子来看:

a <- getA()  // ZIO[R, E, A] (doesn't have to be ZIO btw)
val a = getA(): A

第一个getA说明了效果和返回错误的可能性,这是一个副作用。这就像从某个数据库中获取一个A,其中所述A可能不存在,或者您没有访问它的权限。第二个getA就像一个简单的def getA = "A"
我们如何将这些方法组合在一起?如果有人出错怎么办?我们应该继续下一个方法,还是直接退出它?如果有人挡住了你的线怎么办?

希望这能解决你关于可组合性的第二点。要快速解决其余问题:

  • 执行延迟。这可能有两个原因。首先,你实际上不想意外地启动一个执行。或者仅仅因为你写了它,它就马上开始了。这打破了酷炫们所说的参照透明度。第二种是并发执行需要线程池或执行上下文。通常,我们希望有一个集中的地方,在那里我们可以对整个应用程序进行微调。当我们建造一个图书馆时,我们不能自己提供。是用户提供的。事实上,我们也可以推迟效果。你所做的就是定义效果应该如何表现,用户可以使用ZIO、Monix等,这完全取决于他们
  • 纯度。从技术上讲,以纯粹的效果包装流程并不一定意味着底层流程真的使用了它。只有实现才知道它是否真的被使用了。我们能做的就是把它举起来,使它与构图相适应

使用ZIO或Cats进行编程的好处在于并发编程。它们也是其他原因,但这是IMHO;啊啊!现在我明白了"。

尝试编写一个程序来监控多个文件夹的内容,并为添加到文件夹中的每个文件解析其内容,但同时不超过4个文件。(就像youtube上Adam Fraser的视频《Java开发人员可以从ZIO中学到什么》中的例子https://www.youtube.com/watch?v=wxpkMojvz24。

我的意思是,在ZIO中写这个真的很容易:)

将数据结构(ZIO是一种数据结构)结合起来以形成更大的数据结构,这一事实背后的所有想法都很容易理解,我不想在没有它的情况下编写复杂问题的代码:)

这两个例子是不可比较的,因为第一个语句中的错误会在第一个形式中将等于对象化序列的值标记为错误,而在第二个形式中将停止整个程序。第二种形式应该是一个函数定义,以正确地封装这两个语句,然后是对其调用结果的修饰。

但更重要的是,为了完全模仿第一种形式,必须编写一些额外的代码,以捕捉异常并构建真正的错误结果,而所有这些都是ZIO免费提供的。。。

我认为,在连续语句之间干净地传播错误状态的能力是ZIO方法的真正价值。然后,任何复合ZIO程序片段本身都是完全可组合的。无论如何,这是任何基于工作流的方法的主要好处。

正是这种模块性赋予了实际处理的真正价值。由于效果是一种在结构上可能产生错误的行为,因此处理这样的效果是以可组合的方式处理错误的极好方法。事实上,处理效果在于处理错误!

最新更新