不必要地将函数标记为暂停以支持通用抽象

Posted

技术标签:

【中文标题】不必要地将函数标记为暂停以支持通用抽象【英文标题】:Unnecessarily mark functions as suspending in favor of common abstraction 【发布时间】:2021-04-27 08:54:17 【问题描述】:

我正在开发一个在 JVM 中运行的 API 和一个 JS 客户端以从浏览器访问此 API 的项目。与 JSON 相互转换的那些对象的数据类位于一个多平台模块中,这样我就可以在两个平台上重用代码,并且不会意外地以不匹配的属性告终。在这一点上,在这个多平台模块中也有 API 接口会很好,然后将在 JVM 中实现和托管,并在浏览器中实现和呈现。但是,该接口的所有方法都需要在浏览器中挂起,因为请求(至少对于我正在使用的 Ktor 客户端)而它们不需要在 JVM 中挂起。

是否有充分的理由不让所有这些方法暂停,即使我没有在 JVM 中使用它?我知道方法通常应该只在实际需要时才暂停,但是我会编写所有相同的接口(除了suspend关键字)两次,这对我来说似乎是很多不必要的样板代码。不必要地标记为挂起的方法是从挂起上下文中调用的(我也在 JVM 中使用 Ktor),因此限制使用不会成为问题。

【问题讨论】:

【参考方案1】:

这似乎是一个偏好问题,真的。使用suspend和不使用都有缺点,所以你必须选择重量更轻的。

从你写的来看,使用suspend(只写一次代码)的好处似乎超过了用不必要的修饰符污染接口的坏处。我不知道这里可能的运行时开销。就个人而言,我会选择 suspend

【讨论】:

suspend函数在涉及浏览器的时候很快就需要了...【参考方案2】:

从挂起上下文中调用不必要地标记为挂起的方法(我也在 JVM 中使用 Ktor),因此限制使用不会成为问题。

这是关键点:不必要的suspend 最大的麻烦是必须启动协程。如果您已经在协程中,那么调用路径中只有一个函数不必要地suspend 的开销非常低:每次调用分配一个额外的对象。

【讨论】:

【参考方案3】:

虽然拥有一个接口确实可以避免样板文件,并且您不得不在 JVM 上启动协程,但我会考虑另一种观点:

在设计您的抽象 IMO 时,您不应该过多关注实现细节,而不是考虑 jvm 和/或 js 如何处理与 api 的通信,我会提出问题 “我想为以异步/暂停方式处理此通信的平台?"。我相信这样你会得到一个更具可扩展性的解决方案,但确实你会失去一些微优化

【讨论】:

以上是关于不必要地将函数标记为暂停以支持通用抽象的主要内容,如果未能解决你的问题,请参考以下文章

播放/暂停所有音频链接的通用功能

VBO 通用几何

Windows 通用应用程序在暂停事件时中断所有计时器

在Angular中替换innerHTML不必要地关闭标签[重复]

数组(结构类型)的 Where 是不是已优化以避免不必要地复制结构值?

Gradle 能否以一种不会不必要地触及输出文件的方式生成 POM?