需求简述
12306这个系统,核心要解决的问题是网上售票。涉及到2个角色使用该系统:用户、铁道部。用户的核心诉求是查询余票、购票;铁道部的核心诉求是售票。购票和售票其实是一个场景,对用户来说是购票,对铁道部来说是售票。因此,我们要设计一个在线的网站系统,解决用户的查询余票、购票,以及铁道部的售票这3个核心诉求。看起来,这3个场景都是围绕火车票展开的。
查询余票:用户输入出发地、目的地、出发日三个条件,查询可能存在的车次,用户可以看到每个车次经过的站点名称,以及每种座位的余票数量。
购票:购票分为订票和付款两个阶段,本文重点分析订票的模型设计和实现思路。
其实还有很多其他的需求,比如给不同的车次设定销售座位数配额,以及不同的区段设置不同的限额。我觉得这个需求不是核心最重要的诉求,所以,本文针对这个需求不做具体讨论,也不是本文分析设计的重点。
需求分析
确实,12306也是一个电商系统,而且看起来商品就是票了。因为如果把一张票看成是一个商品,那购票就类似于购买商品,然后每张票都有库存,商品也有库存的概念。但是如果我们仔细想想,会发现12306要复杂很多,因为我们无法预先确定好所有的票,如果非要确定,那只能通过穷举法了。
我们以北京西到深圳北的G71车次高铁为例(这里只考虑南下的方向,不考虑深圳北到北京西的,那是另外一个车次,叫G72),它有17个站(北京西是01号站,深圳北是17号站),3种座位(商务、一等、二等)。表面看起来,这不就是3个商品吗?G71商务座、G71一等座、G71二等座。大部分轻易喷12306的技术人员(包括某些中等规模公司的专家、CTO)就是在这里栽第一个跟头的。
实际上,这个车次可以卖的票是非常多的。为了方便后面的讨论,我们先明确一下票是什么?
一张票的核心信息包括:出发时间、出发地、目的地、车次、座位号。持有票的人就拥有了一个凭证,该凭证表示持有它的人可以坐某个车次的某个座位号,从某地到某地。所以,一张票,对用户来说是一个凭证,对铁道部来说是一个承诺;那对系统来说是什么呢?不知道。这就是我们要分析业务,领域建模的原因,我们再继续思考吧。
明白了票的核心信息后,我们再看看G71这个车次的高铁,可以卖多少张票?
讨论前先说明一下,一辆火车的物理座位数(站票也可以看成是一种座位,因为站票也有数量配额)不等于可用的最大配合。所有的物理座位不可能都通过12306网站来销售,而是只会销售一部分,比如40%。其余的还是会通过线下的方式销售。不仅如此,可能有些站点上车的人会比较多,有些比较少,所以我们还会给不同的区间配置不同的限额。比如D31北京南至上海共有765张,北京南有260张,杨柳青有80张,泰安有76张。如果杨柳青的80张票售完就会显示无票,就算其他站有票也会显示无票的。不管如何配置限制区段的配额和限额,我们总是针对车次进行配置,这点只是车次内部售票时的一些额外的判断条件(业务规则),不影响车次模型的核心地位。所以,为了本文讨论的清楚起见,我后续的讨论都不涉及配额和限额的问题,而是认为任何区段都可以享受火车最大的物理座位数。
为了讨论问题方便,我们减少一些站点来讨论。假设某个车次有A,B,C,D四个站点。那001这个人购买了A,B这个区间,系统会分配给001一个座位x;但是因为001坐到B站点后会下车,所以相当于x这个座位又空出来了,也就是说,从B站点开始,系统又可以认为x这个座位是可用的。所以,我们得出结论:同一个座位,其实可以同时出售AB,BC这两张票。通过这个简单的分析,我们知道,一列火车虽然只有有限的座位数,比如1000个座位。但可以卖出的票远远不止1000个。还是以A,B,C,D四个站点为例,假如火车总共有1000个座位,那AB可以卖1000张,BC也可以卖1000张,同样,CD也可以卖1000张。也就是说,理论上最多可以卖出3000张票。但是如果换一种卖法,所有人都是买ABCD的票,也就是说所有的票都是经过所有站点的,那就是最多只能卖出1000张票了。而实际的场景,一定是介于1000到3000之间。然后实际的G71这个车次,有17个站,那到底可以卖出多少个票,大家应该可以算了吧。理论上这17个站中的任意两个站点之间所形成的线段,都可以出售为一张票。我数学不好,算不太清楚,麻烦有数学好的人帮我算算,呵呵。
通过上面的分析,我们知道一张票的本质是某个车次的某一段区间(一条线段),这个区间包含了若干个站点。然后我们还发现,只要区间不重叠,那座位就不会发生竞争,可以被回收利用,也就是说,可以同时预先出售。
另外,经过更深入的分析,我们还发现区间有4种关系:1)不重叠;2)部分重叠;3)完全重叠;4)覆盖;不重叠的情况我们已经讨论过了,而覆盖也是重叠的一种。所以我们发现如果重叠,比如有两个区间发生重叠,那重叠部分的区间(可能夸一个或多个站点)是在争抢座位的。因为假设一列火车有100个座位,那每个原子区间(两个相邻站点的连线),最多允许重叠99次。
所以,经过上面的分析,我们知道了一个车次能够出售一张车票的核心业务规则是什么?就是:这张车票所包含的每个原子区间的重叠次数加1都不能超过车次的总座位数,实际上重叠次数+1也可以理解为线段的厚度。