使用有限状态机建模UI状态在反应表格组件中

图片由Garett Mizunaka.uns

在Ok188bet金宝搏官网cupid,我们正在为用户建立一个新的位置搜索体验,以根据国家/地区,城市名称和GPS设置自己的位置。

与早期的位置搜索体验的迭代相反,从源代码中不再静态加载所需搜索的数据。新的搜索体验由来自后端的多个数据和服务供电,为错误和成功案例提供更复杂的用户反馈。

是什么让新位置搜索UX复合物的前端是有很多活动部件。UI需要在仍在加载数据时管理用户输入。UI还需要基于搜索结果向用户显示反馈,并处理网络连接等各种错误条件和服务器端错误。在引擎盖下,用户在选择国家/地区名称时看到的简单形式必须使用来自用户的事件协调对后端的请求。

这篇文章探讨了我们在OKCupid中使用的有限状态机(FSM)的架构设计模式,以制作强大的位置搜索UX。188bet金宝搏官网

FSM的主要使用已经进入编程嵌入式系统但近年来,其他应用中的FSM出现了FSM在浏览器中管理状态建模行为, 和建筑聊天禁止.这篇文章的目的不是要宣传FSM是一个比它的替代品更好的状态管理解决方案但是,要引入一种简化系统的架构的模式,并写出可理解,可扩展的强大代码删除

什么是FSM?

FSM是一种架构设计模式,允许我们将大型系统模拟为松散耦合组件的集合。系统中的每个组件在内部状态更改时更改其行为。

FSM由国家和国家转型组成。它可以由状态机表示图表

FSM代表红绿灯

正式,

  • 状态代表系统的模式并驱动系统的输出。灯开关有两个状态:打开或关闭。红绿灯包含三个州:红色,黄色或绿色。FSM中有一个有限数量的州。每个FSM都有一个初始状态,它是系统在第一次启动时的状态。

如果我们将反应组件造型为FSM,则用户,服务器或组件的呼叫者在外部提供系统输入。这些包括事件,例如按钮单击或从服务器接收某个响应。系统的输出是JSX(即,呈现的内容),因为这是最终从组件返回的内容。

作为FSM建模的React组件的输入和输出

退换出来必须互斥。这意味着给定的输入不能导致转换到两个状态。这确保了我们系统的确定性行为。

一个由几个国家组成的组成部分

您可能已经有经验建立使用组件状态的反应组件insloading.和一样被禁用确定如何呈现。这些是可以用具有二进制状态的简单FSM建模的状态组件的示例。允许我们在一个具体示例中将一个简单的状态反应组件建模到FSM的信息,以应用于FSM。

假设我们正在建立组件来自反应钩子文件.在任何给定的时间,该组件显示三条消息“加载...”,“在线”和“脱机”中的一个。

组件状态isOnline准确地确定要呈现和初始化的消息无效的并更新到“在线”或“离线”使用

isOnline让我们储存三个UI状态:加载,离线,在线。

我们可以重写渲染基于ui状态反而。

状态转变发生在handlestatuschange.,这是在每个渲染中触发的使用没有第二个理由。

Setuistate(Nextuistate)负责基于系统输入(即,)引起从uistate的电流转换到下一个uistate(即,地位来自ChataPi)。

我们的系统输出是我们想要渲染的消息,即直接来自uistatemessagemap..我们可以这样做,因为我们的系统只能处于三个州之一。当系统的输出完全取决于当前状态时,我们有一种特殊类型的FSM,称为a摩尔机器.摩尔机器更具有确定性,但对输入变化的反应较慢粉机.在Mealy机器中,输出取决于当前的状态和系统的输入。

无论您是构建摩尔机器还是MEALY机器都真的取决于您的系统的要求。我们将在帖子的下一部分中看到如何构建一个系统,该系统是使用架构的混合摩尔和MEALY机器,该架构将状态驱动输出的实现委托给子组件。

具有许多州的一个组件

对于只有两种或三种状态的简单组件,一个FSM可能是多余的。实现FSM有相当多的开销(例如,定义所有UI状态和转换),而没有多少额外的好处。

对于一个由许多具有横切关注点的子系统组成的复杂系统,FSM提供了巨大的好处。

考虑您的系统由多个组件组成,其中需要禁用一个组件而另一个组件加载,并且两个组件的输出确定第三组件的输出。

交叉组件依赖性可能导致组件的紧密耦合,并使封装困难,系统难以测试。

188bet金宝搏官网,我们建立了这样的组件()允许您指定一个国家/地区和查询词(邮政编码或城市名称),以查找世界任何地方的位置。这似乎非常直接,直到您考虑所有边缘案例,该组件必须处理。

  • 该组件使用一个API进行接口,该API提供最匹配国家和查询搜索项的位置对象数组。根据这个数组的长度,组件可以显示一条成功消息、各种错误消息和另一个选择UI,通过从一个最佳匹配列表中进行选择来消除搜索的歧义。

如果您在JIRA票证中看到了这种设计规范,那么它似乎有点压倒。有很多需要实施的逻辑。但是,拥有前面的所有功能要求实际上是伪装的祝福 - 它使我们能够更全面地思考这个组件的设计,并选择可以有效地管理该组件所有复杂性的架构。

所有UI状态的枚举

与设计师在一个跨职能团队中工作的一个好处是,在开始执行之前,您就获得了所有的模拟。这些模拟可以用来设计架构。

由于这是一篇关于使用FSM的UI状态建模的文章,因此您可能已经看到了它。我们将为每个模拟分配UI状态,该模拟表示在操作中的组件的快照。

每个州的位置输出

这些图像描绘了每个状态中系统的输出(用户看到的内容)。让我们来看看输出在不同状态中的共同之处。这将为我们提供如何分开我们的想法组件进入子系统。

  • 在成功状态下,显示所有错误状态,显示反馈消息。文本颜色取决于状态。

通过将特定于状态的输出的实现委托给这些组件,我们能够进行转换进入通过UI状态协调的松散耦合组件的系统。我们正在封装FSM,在父组件的意义上不知道此组件中UI状态的实现。

现在我们已经定义了每个状态的状态和输出,我们将指定状态转换。

国家过渡

类似于我们所做的早些时候,我们将要实例化uistate.作为一个组成状态和变异uistate.在一个使用.下一个的评价uistate.将在辅助功能中完成getUiState.使下一个州评估的优势在显式中getUiState我们将能够分离计算的关注点吗什么时候从…的关心中提出什么渲染。

召回FSM可以表示为定向图形,状态转换是节点之间的边缘。这就是我们的FSM应该是什么样的。

FSM代表位置搜索

PENDING状态是初始状态第一个安装。由于组件可以安装有预装位置,因此有一个箭头直接从待处理状态到成功状态。我们还可以通过向服务器或GPS位置提供国家+查询来达到成功州。

通过客户端输入验证达到error_not_zip_code状态,不依赖于服务器请求的结果。另一方面,只有在向服务器提出请求之后才能达到所有其他错误状态。

结论

在这篇文章中,我们了解了FSM是什么以及如何将复杂的反应组件建模为通过UI状态协调的松散耦合子系统的系统。FSM允许我们构建一个可理解,可扩展的强大的系统和删除

我们已经看到了一些使用React原语的例子,比如useestate.使用.有类似JavaScript库XSTATE.Machina.js它为创建,解释和执行有限状态机和StateChart提供了更具自融合的框架。

虽然FSM是一种强大的设计模式,但对于项目来说并不总是正确的事情。当建筑设计最有效的时候最明确的产品愿景和预期,以满足如何满足全用户体验的愿景。预成熟优化可能导致更糟糕的代码可维护性。幸运的是,我工作的位置搜索体验项目188bet金宝搏官网拥有良好的产品规划和清晰的设计目标,这使得分解问题和构建健壮的技术解决方案成为可能。

188bet金宝搏官网Okcupid Tech Blog.

阅读来自工程团队的故事,这些故事每天连接着数百万人