在哪里绘制反应式编程线

在我的项目中,我一直在使用RxJava大约一年。 随着时间的推移,我开始非常喜欢它 – 现在我想也许太多了…

我写的大多数方法现在都有某种forms的Rx,这太棒了! (直到不是)。 我现在注意到有些方法需要大量的工作来组合不同的可观察生产方法。 我感觉到虽然我明白我写的东西,但下一位程序员很难理解我的代码。

在底线之前,让我直接从我在Kotlin的代码给出一个例子(不要太深入):

private fun  getCachedEntities( getManyFunc: () -> Observable<Timestamped<List>>, getFromNetwork: () -> Observable<ListResult>, getFunc: (String) -> Observable<Timestamped>, insertFunc: (T) -> Unit, updateFunc: (T) -> Unit, deleteFunc: (String) -> Unit) = concat( getManyFunc().filter { isNew(it.timestampMillis) } .map { ListResult(it.value, "") }, getFromNetwork().doOnNext { syncWithStorage(it.entities, getFunc, insertFunc, updateFunc, deleteFunc) }).first() .onErrorResumeNext { e -> // If a network error occurred, return the cached data and the error concat(getManyFunc().map { ListResult(it.value, "") }, error(e)) } 

简而言之,这是做什么的:

  • 从存储中检索一些时间戳数据
    • 如果数据不是新的,则从网络获取数据
      • 再次与存储同步网络数据(以更新它)
    • 如果发生网络错误,请再次检索旧数据和错误

下面是我的实际问题:反应式编程提供了一些非常强大的概念。 但是,正如我们所知道的那样, with great power comes great responsibility

我们在哪里画线? 用完美的react native线索填充我们的整个项目是否可行,还是仅仅为了真正的普通操作而保存?

显然这是非常主观的,但我希望有更多经验的人可以分享他的知识和陷阱。 让我说得更好

我如何设计我的代码来反应,但容易阅读?

当你拿起Rx的时候,它变成了这个真棒shiny的锤子 ,一切都开始像一个生锈的钉子,只是等着你砰的一声。

就我个人而言,我认为最大的线索就是名字, 被动框架。 给定一个要求,你需要反思一个被动解决方案是否真的有意义。

在任何Rx命题中,您都希望引入一个或多个事件流,并针对某个事件执行一些操作。

我想有两个关键的问题要问:

  • 你在控制事件流?
  • 你必须在什么程度上以事件流的速度完成回应?

如果您无法控制事件流,并且必须以事件流的响应速度进行响应,那么Rx是一个很好的选择。

在任何其他情况下,这可能是一个糟糕的选择。

我曾经看到过很多例子,人们为了certificateRx的缺陷而创造了一种缺乏控制的幻觉 – 这对我来说似乎很疯狂。 为什么放弃你拥有的控制权?

一些例子:

  1. 您必须从固定的文件列表中提取数据并将其存储在数据库中。 您决定将每个文件名称推送到一个主题中,并创建一个反应式管道,打开每个文件并投影数据,然后以某种方式处理数据,最后将其写入数据库。

    这不能控制测试和速率测试。 遍历这些文件并将其入并尽可能快地处理它们会更容易。 “决定推”这个词是这里的赠品。

  2. 您需要显示证券交易所的股票价格。

    显然这是Rx的不错选择。 如果你不能跟上价格的速度,那么你就被搞砸了。 这可能是你混淆价格的情况(也许只是每秒更新一次) – 但这仍然符合保持。 你不能做的一件事是要求证券交易所放缓。

这些(现实世界)的例子几乎落在了光谱的两端,没有太多的灰色区域。 但是在那里控制不清楚的地方有很多的灰色地带。

有时候,你在客户/服务器系统中戴着客户端帽子,很容易陷入牺牲控制的陷阱,或把控制放在错误的地方 – 这可以很容易地用正确的设计来固定。 考虑一下:

  1. 客户端应用程序显示来自服务器的新闻更新。

    • 新闻更新随时都会提交给服务器,并以大量创建。
    • 客户端应该刷新客户端设置的时间间隔。
    • 刷新间隔可以随时更改,用户可以随时请求立即刷新。
    • 客户端仅显示用特定关键字标记的更新,如用户指定的那样。
    • 新闻更新有时很长,客户不应该存储新闻更新的全部内容,而是显示标题和摘要。
    • 根据用户请求,可以显示文章的全部内容。

在这里,新闻更新的频率不受客户的控制。 但是所需的刷新率和感兴趣的标签是。

为了让客户端收到所有的新闻更新,并过滤它们,客户端不会工作。 但有很多选择:

  • 服务器是否应该考虑客户端刷新率发送更新数据流? 如果客户端下线怎么办?
  • 如果有成千上万的客户呢? 如果客户想要立即刷新呢?

有很多有效的方法来解决这个问题,包括或多或少的react native元素。 但任何好的解决方案都应该考虑到客户端对标签的控制和所需的刷新率,以及新闻更新频率(客户端或服务器)缺乏控制。 您可能希望服务器通过更新推送到客户端的事件来响应客户端感兴趣的更改 – 只要客户端正在监听(通过检测信号检测到),它就会推送它。 当用户想要一个完整的文章,然后客户将拉下文章。

Rx社区有很多关于背压的争论。 这是客户端应该在服务器过载时通知服务器,服务器以某种方式减少事件流的响应。 我认为这是一个误导的方法,可能会导致混淆的设计。

在我看来,一旦客户需要提供这种反馈意见,就没有响应率测试。 在这一点上,你并没有处于被动状态,你处在一个异步的情况下。 即,当客户端准备好更多时,应该说“我准备好了”,然后以非阻塞的方式等待服务器响应。

如果第一种情况被修改为到达放置文件夹的文件,这将是适当的,处理的长度和复杂程度各不相同。 客户端应该对下一个文件进行非阻塞呼叫,处理它,然后重复。 (根据需要添加并行) – 而不是响应文件到达的事件流。

包起来

我故意避免了其他有效的问题,比如代码的可维护性,Rx本身的性能等等。大部分是因为它们在其他地方被处理,更重要的是因为我认为这里的想法比这些问题更加分裂。

所以,如果你在你的情况下反思控制响应率的要素,你可能会保持正确的轨道。

答复率问题可以是微妙的 – 程度方面是重要的。 到达率可能会波动,回复率会有一定程度的波动 – 显然,如果您最终没有办法“赶上”,那么在某个时候,客户就会爆炸。

我发现在编写Rx时(或任何稍微复杂的/新技术)我记住了两件事情,

  1. 我可以测试吗?
  2. 我可以轻松聘请能维护它的人吗? 不是为了维护它而奋斗,而是要好好保持下去呢?

为此,我也发现,只因为可以,并不总是意味着你应该。 作为指导,我尽量避免创建超过7行代码的查询。 查询比这更大,我尝试分解成我构成的子查询。

如果您提供的代码是代码库的核心,并且处于复杂性的极端,那么可能没问题。 但是,如果您发现所有的Rx代码都具有这么多的复杂性,那么您可能会创建一个难以使用代码库的工具。