最近在做订单及支付相关的系统,在订单表的设计阶段,团队成员就‘订单状态’数据库字段设计有了一些分歧,网上也有不少关于这方面的思考和探讨,结合这些资料和项目的实际情况,拟对一些共性问题进行更深一层的思考,笔耕在此,和大家一起探讨。
问题综述这里的分歧点即有团队内部的分歧点,也有网络上常见的一些分歧点,先将存在的分歧点抛出来:
1、订单表的‘订单状态’字段对应的字典值应当包含哪些状态值?对于‘已评论’、‘已退货’、’已退款’这类状态是放到‘订单状态’中?还是独立一个字段标识?
2、订单表的‘订单状态’字段对应的字典值如何表示?可选项有:使用数字标识、使用多‘位’存储方式标识、使用具有明确业务含义的英文字符串标识;
3、订单表的‘订单状态’字段使用何种类型?可选项有:number(N)、char(N)、varchar2(N);
如果嫌分析过程过于啰嗦,可以直接拉到最后看结论。
业务分析我们先不去看问题,先来看看和‘订单(Order)’实体相关的业务是怎样的。下面我们会针对可能改变订单实体状态的行为已经状态变化的可能性进行详细的分析。
订单业务实体相关的业务流程如下:下单(create)--> 买家付款(pay)--> 卖家发货(deliver)-->买家收货(receive)-->退货(rereturn);此外,还有退款(refund)和评论(comment),这两个行为比较特殊,其前向行为可能存在多个。
首先,可以改变订单业务状态【这里的状态不是指‘订单状态’(OrderState)这个数据库字段,而是指实际业务状态,我们简记为(BizState),以和OrderState区分开】的行为有哪些?按照典型电商的业务流程,主要的行为(action)有:下单、付款、发货、收货、退款/退货、评论;每一种行为的发生,都会导致订单的业务状态BizState发生变化,比如‘下单’行为会创建订单,‘付款’行为会使订单变为‘已付款’,‘发货’行为可以使订单状态变为‘已发货’,‘收货’行为会使订单状态变为‘已收货’,‘评论’行为会使订单状态变为‘已评论’。‘退款/退货’action不是所有订单都支持的,为减小复杂度,暂不考虑它们。
其次,细分下每种action对BizState带来的影响,会发现还可以细分为四种子状态(subState):action未开始(标记为0)、action进行中(标记为1)、action成功(标记为2)、action失败(标记为3);理论上,将所有action的所有subState进行排列得到4*4*4*4*4=1024(暂未考虑‘退货’);实际上,很多组合是没有业务意义的,是不可能存在的,比如‘未开始已付款...’(***20)这一类组合是不可能发生的,应当舍弃。用表格将上述的组合分析如下:
通过上表,我们可以发现些的规律:
‘下单’、‘付款’、‘发货’、‘收货’前四种action是存在依赖关系的,亦即后一个action依赖于前一个action的完成;所以,他们的SubState组合情况就会非常少;
‘评论comment’这个action的SubState和其他状态组合会有很多种可能性;除了前面了两行是‘X’,后面是‘?’或者‘Y’,‘?’是指需求上是否允许在对应的BizState上进行评论,如果允许,则每种BizState需要多出4种可能,这样组合的可能性就会变得很大。
没有业务意义的SubState组合被舍弃。表中的标黑单元格,表示这个BizState是毫无意义的,因为‘未下单’的订单对于我们来讲是不存在的,这类组合需要舍弃;同样的,还有很多其他的组合也是不存在的,被舍弃掉,未展示在上表中,如‘已下单已付款未发货已收货’这种。
通常某个action的SubState为‘1进行中’、‘3失败’时,会被忽略,但也有例外;比如‘付款’action的‘3失败’状态,和‘付款’action的‘1进行中’状态,具体分析见后面内容。
忽略所有action的‘0未开始’SubState状态。因为这类SubState对于BizState不会带来变化。
综合下来,我们得到上表的BizState,注意这里的Comment action未进行细化处理,如果细化处理,会发现BizState的可能性会增大很多很多。
接下来我们就之前提出的这些问题进行逐个讨论。
问题一、订单表的‘订单状态’字段应当包含哪些状态值?什么样的‘订单业务状态’(BizState)需要记录到系统层面的‘订单状态’(OrderState)字段呢?如果记录多了,则系统处理的复杂度会增大;记录少了,那么‘订单状态’(OrderState)字段就不能完整的表示出订单实体状态变化情况。
核心状态通过上面的业务分析可知:大部分存在依赖关系的action(create、pay、deliver、receive),他们产生的合理的SubState组合是非常少的,而且他们之间的依赖是单向依赖,状态机的处理也很简单,因此,我们先将这部分BizState纳入到OrderState中:
目前的订单状态流转:
‘action行为’失败的情况对于action的SubState是‘3失败’的处理,需要针对不同的action进行分析。类似‘下单Create’这样的action,如果失败,则可以直接将OrderState置为‘订单创建失败’,因为Create action是第一个action,它的失败意味着Order实体出生即死,BizState置为终态,对于这个BizState应当纳入到OrderState中记录,不过这个OrderState其实对于用户并无多大用处,因为用户并不会关心下单失败的订单,他更关心的是重新下单;