首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >异步组件的设计

异步组件的设计
EN

Software Engineering用户
提问于 2017-03-15 05:28:43
回答 2查看 263关注 0票数 5

我正在尝试设计一个异步组件。这一构成部分的所需资源如下:

  • 组件可以在任何时间点接收事件。
  • 组件可能会启动长期运行的操作并等待其结果。此操作由外部系统执行。
  • 长时间运行的操作可能被取消,无论是组件还是外部操作。
  • 在长时间运行操作时可能会发生事件,这可能会再次启动长时间运行的操作,可能会取消以前的调用。
  • 组件需要决定如何处理在长期运行操作期间出现的事件,如果要忽略它,则将其排队或进行其他操作。
  • 组件可能会针对不同的事件启动不同的操作。
  • 组件可以有多个“支持值”,其中每个值都有当前值,并且其更改请求是需要响应的事件组件。
  • 必须能够隔离地对组件进行单元测试(这很重要!)
  • 将有多个不同的组件,一些可能共享行为。例如,打开/关闭组件的能力。

到目前为止,我已经试过/想过:

  • 反应性可观测性
    • 这是现在使用的
    • 我真的很喜欢在虚拟时间里进行测试的方法。
    • 长时间运行的操作表示为将“请求”转换为可观察的“响应”的函数。
    • 但是团队的其他成员认为这个解决方案太复杂了。

  • 带有事件处理程序方法的普通对象
    • 总体来说很简单,但有些结构可能很复杂。
    • 不需要额外的库
    • 测试并不简单,因为它需要显式地编写对事件的每个响应,而不是像在反应性中那样说“对于每个请求,以5个滴答来响应”。

  • 具有异步/等待的任务
    • 我不知道如何实现在长时间运行过程中发生的事件时发生的情况,以及如何测试这种情况,因此我选择了反应性。

  • Actor框架(Akka)
    • 这似乎最适合我的要求。
    • 但是我不喜欢测试的方式,因为它使用的是实时的。
    • 而且我认为Akka对这个用例来说太过分了,因为我们不需要每个组件线程和整个工具来创建参与者并在它们之间进行通信。
    • 恐怕我的团队也会觉得太复杂了

我正在寻找的是可能的其他解决方案的建议,我可能没有想到。或建议的解决方案的其他优点/缺点。

EN

回答 2

Software Engineering用户

发布于 2017-03-15 10:48:28

我认为可观察是正确的模式。

使用async/await推断的诺言/任务/未来/延迟最适合于需要跟踪的单个事件(或分支逻辑链事件)。你将需要很多额外的工作,以使它适合你的情况。

大多数实现都在幕后使用生成器*/IEnumerable/iterator,await变成yield new Promise/yield return new Task,调用编码被转换为承诺/任务的枚举数。

Rx/观察力更适合于事件可以反复触发的情况,并且您希望将它们作为一个随时间迭代的集合来处理。

您可以使用自己的类来处理这个问题(可能使用async/await),但是您必须解决Rx已经存在的许多相同的问题,同时又不能节省任何复杂性。

票数 1
EN

Software Engineering用户

发布于 2017-06-13 13:02:26

您的解决方案可能太复杂,因为它本身做的太多了。例如,如果将长期运行任务(AKA作业)管理拆分为自己的组件,则可以将交互限制在管理这些任务上。类似地,临时事件处理组件可能需要使用作业管理器,但将测试限制在这些事件上可以使处理起来更加容易。我自己也做过几个项目。

您处理测试的方式是通过几个精心选择的接口。该实现可以是您的反应性可观察性,也可以是自定义实现,这取决于您的实际需求。IJob接口可以如下所示:

代码语言:javascript
复制
public interface IJob
{
    string Id { get; }
    bool IsRunning { get; }
    Task Handle { get; }
    void Cancel();
    // and anything else you need.
}

您还可以制作一个类型化版本来处理返回值的任务。

底线是,您可能只需要系统中长期运行的任务管理组件之一。您可以轻松地测试与该组件的所有交互,也可以相当容易地测试组件本身。由于Handle属性公开了一个Task,所以您可以很容易地获得代码,这些代码将简单地将作业交给await来完成。

我还没有使用反应性可观察性,但是您可以提供一个Task句柄,它可以很容易地使用TaskCompletionSourceTaskCompletionSource连接到一个简单的结果。在作业内部,您可以在需要显式时设置结果或错误状态,而外部代码并不明智。TaskCompletsionSource有一个Task属性,可以用于上面的Handle

您可以根据需要拥有尽可能多的“临时”组件,只要它们有一个一致的方法来管理长期任务,就应该将设计简化为每个人都能理解的东西。

票数 0
EN
页面原文内容由Software Engineering提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://softwareengineering.stackexchange.com/questions/344153

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档