XState

xstate

XState是一个状态管理(State Management)Library,负责储存及描述各种状态与各种状态间的转换,有点类似于Redux、Flux,不同的地方在于XState整个核心都源自于Statecharts,也就是我们需要定义好整个应用,程序会有哪些状态,和每个状态下能转换到哪些状态(顺序性)以及他们之间如何转换。

Statecharts

其实Statecharts并不是什麽新技术或新概念,早在1984David HAREL的论文就提出了Statechart,是由早期的状态图(state diagrams)所拓展而来的,在该篇论文中对状态图加入了三个元素分别处理了层级(hierarchy)、併发(concurrency)和通讯(communication)。让原先的状态图变的高度结构化且能更有效地描述各种状态。

Statecharts 来描述 Fetch

为何需要xstate

其实用过Angular.js的开发者都会知道状态管理的重要性,当应用,程序状态分散在不同地方时,就会使得状态难以管理,并且容易出现Bug,直到Flux出现提出了单一资料源(Single Source of Truth)及单向资料流(unidirectional data flow)等概念后,状态管理的问题才得到了缓解。而Redux的出现利用Funtional Programming的手法大幅度的降低原先Flux的複杂度以及学习成本,如果我们依照Redux的架构已经可以把因为状态複杂度而陡然上升的维护成本控制得很好,那如今为什麽我们还需要一个新的状态管理工具呢?

缺乏清晰的状态描述

不管是使用Redux或其他相关的Library都会有状态难以清晰描述的问题,最主要原因有两个,第一个是我们完全混合了状态(state)跟资料(context),所有东西都直接往Reducer裡面塞导致我们无法分清楚哪些是资料、哪些是状态。这裡的资料(context)指的是显示在页面上的内容,通常这些资料会存储在后端并透过API取得,在XState称之为context,在UML State Mechine裡面称为Extended states;而状态(state)则是指应用,程序当前的状态,比如说是否已登入或者Menu是否展开等等状态。

另一个因素是我们通常都使用flag来表达某个小状态,再由多个flags来表达某个状态,当这种flag越来越多时,我们的,程序就会很容易出现Bug,程序码会长的像下面这样:

if (isLogin && isYYY && isXXX)

这样的,程序码其实就是所谓的bottom-up code,通常是我们先有一个小状态比如说isLogin然后后面又加了其他各种状态,当我们这种小状态一多,就会让,程序容出现难以察觉的Bug

过于自由的状态转换

如上面我们提到的,过去我们的状态是由多个flags所组成,这导致了我们无法明确的定义各种状态之间的关係,最后就会变成我们无法确定状态之间的切换是否正确,比如说isAdmintrueisLogin应该必定为true。像这样用flag储存小状态就会有可能出现状态转换出错的情况,比如说isAdmin设定成true了,却忘记把isLogin也设定为true;而实际上状态的複杂度会比这裡举的例子複杂许多,这样的,程序码大到一定程度就会变成我们再也无法真正理解,程序有哪些状态,以及哪些可能的状态应该被处理(除非你再从头跟PMDesigner完整的过一次流程与画面,但如果专案够大很有可能他们也不会很清楚)

难以与工程师之外的人讨论

同样的当我们今天用各种flags的方式去描述整个应用,程序的状态时,其实是很难跟工程师之外的人沟通或讨论的,就算是工程师也要追Code花时间理解当前的,程序到底是如何运作并且在哪个状态下出现的Bug,这会让我们很难快速地发现问题也很难跟PM讨论需求设计是否存在逻辑上的矛盾,或是有未处理的状态。

XState有什麽优势?

,程序码即UI Spec

当我们今天用XState定义好各种状态之后,就可以直接利用XState提供的图像化工具(Visualizer),程序码转换成图片,如下:

xstate 状态逻辑图

当我们有这张图之后,就可以把这个当作UI SpecPM及设计师讨论哪方面流程有问题,或是还有哪些没有明确订定的状态。

写更少的测试

由于我们已经明确定义出各个状态以及每个状态之间的关係,这让我们可以更轻鬆的撰写测试,也不需要测试那些根本不可能出现的状态,并透过Model-based Testing我们只需要写各个状态下的断言(assertion)就可以自动把各种状态切换的路径都测试完!XState在这方面也提供了xstate-test有完整的范例跟教学。

更快速的路径优化

当我们完成一个应用,程序时,最需要做的通常就是使用者体验(User Experience)的优化,我们常常需要利用各种服务来收集各个页面间的转化率或是哪些状态让使用者最快跳过等等的数据。透过这些数据来优化我们应用,程序的流程,让使用者体验进一步的提升。而如果使用了XState我们就可以在各个状态转换之间送log到数据收集的服务(GA, MIXpanel等等),就可以进一步分析哪些状态可能是不必要的,来优化我们的User Flow