领域驱动设计对12306购票业务的设计思考

2019-10-29 22:50:03

请关注唯心的个人微信公众号:craft6-cn(中划线,也可以搜索:领域驱动业务建模)

领域驱动设计对12306购票业务的设计思考

网站:craft6.cn。公众号:craft6-cn


1

前言

常规的电商系统的业务针对商品,处理好SKU和SPU的关系即可,购物下单时,最复杂的业务在促销和分布式库存的处理,至于订单流程,相对固化。


至于12306购票系统的购票业务复杂度则复杂得多,而且这是动态商品的典型案例,甚至于购买的每一张车票都会影响后续可够票的不同组合变化,对于站点较多的车次,持续运营下来,要找出两趟车所售出的票完全相同都不容易。


这种复杂度这么高的业务,如果单纯用数据驱动或者事件驱动的形式来开发,很容易代码缠绕越来越深,开发和维护难度越来越大。


越简单的业务系统越不必用领域驱动设计,而在业务越复杂的领域,领域驱动设计(DDD)的优势就彰显出来。


2

基本概念

我们先分析一下系统涉及哪些业务对象:

  • 车次:车次标识着从始发站到终点站的某一趟特定的列车;还包含发车时间、每个站的标准到达时间;

  • 车厢:一趟列车包含若干节车厢,一般按数字来命名,每个车次的车厢数量会有所不同。对于高铁一般分为二等座车厢、一等座车厢、商务座车厢等。

  • 座位:不同的车厢类型会分布着若干个座位,如果是餐车车厢则没有提供可购买的座位。根据车厢的不同座位数量和编号也不同。

  • 座位编号:高铁座位编号用第几排 + ABCDF表示,对于二等座则是ABC DF,对于一等座则是AC DF,对于特等座或者商务座则是AC F,中间是过道,两边是车窗。

  • 站点:一个车次从始发站、经过中间若干站点,然后到达终点站,每次停靠和供乘客上下车的地方称为站点。

  • 车票:一张车票的主要信息包含:出发时间、出发站点、目的站点、车次、车厢、座位号。

  • 限额:这个概念比较复杂,下面会专门章节分析。铁路运营同样要考虑营收,如果不设置限额,则某趟车次出现大量短站点乘车时,该趟列车全程上座率就会很低。


3

购票可能 和 站点重叠


以一个最简单的例子:

最简单例子.png

    这趟车次只有6个站S1~S6,只有一节车厢一排座位,5个位置。

  • 情况1:最好的情况最简单例子 - 满 (1).png

    每个座位售出的票都是首发到终点,这对于运营是利益最大的。

  • 情况2:最差的情况

    空车当然是最差的情况,我要讨论的不是空车,而是每个座位都有购买,但是每个座位都只是售出了最短的路途。


  • 站点重叠:其它的情况,则会涉及站点重叠

    比如客户A购买了S1--》S2(或者S2--》S3诸如此类)的A座位,那么剩余从S1到S6的剩余票数则是4,但是如果购买S2--》S6却还是有座位的。

    极端的情况下,就是当一趟车次只有座位的情况下,可以拆成N-1张票(N为站点数量)。只要不存在重叠,就可以购票(当然,前提是该区间限额允许)


4

可售矩阵和可售区间


矩阵方法 (1).png

    如图所示,对于本文例子,可以形成这样的【矩阵】,每一个块就是一个可选的【区间】,在不考虑限额的前提下,均可以独立下单购买一张车票。

    图中绿色表示已购买,黄色表示选择已选择但未付款,时间到了(如10分钟)会自动解锁释放,白色整体表示【可售矩阵】,每一块表示【可售区间】。

    如果站点很多,则Y轴延长,如果座位行数多,以及不同车厢类型(如商务车厢只有3个座位)则X轴延长,如6C,表示第6行C座位。


    从图中可见,A座位已经全部售出,B座位则锁定了S1-->S4(下车,所以不含),但是如果未支付,会到时释放。这是B座位也可以购买S4--》S6的区间;C也一样;D则可以购买S1--》S3 和 S5--》S6 的区间;F则可以购买S5--》S6区间。


    所以一趟车的可售票,就转换为 座位 * 站点(N-1)的可售区间矩阵了。


   当然,实际运营中,为了利润(上座率)更高,对于不同的站点会设置限额,让可售区间更倾向热门站点,避免冷门站点占用资源过多或者出现恶意占用(比如黄牛)的情况。


5

可售数量限额

    限额针对的是可售数量,类型包括:

  • 售票渠道(网上、窗口)

  • 目的站点的不同可售数量会有差异

  • 投放数量,比如逢节假日,热门车次不一定是一次性投放全部可售票数的。


    现在高铁统一了销售形式,售票渠道的差异可以没有(这点我不确定),所以本文暂时不考虑这个因素,只考虑目的站点的可售数量限额。


   以湛江西到佛山西高铁为例,阳江到阳东这一段几乎没有下车的人,高铁也以车次作为调控,即每天经停阳东的班次只有几列,但是针对这几列为了规避黄牛和提高全程上座率,可能也是做了数量限额(这点要向铁路部门考证,本文只是把这种因素考虑入内,用于分析)。


   另外,分批投放的情况也是存在的,这样兼顾公平,避免票被一次性抢完。

6

限额和矩阵


    矩阵方法 (2).png

  • 站点限额:如目的站的是S2或者S3,则限额为2,座位不限,只要有区间组合就可以选择。

  • 分批投放:不限站点,但是只分配2/5出来,座位不限,对照图中的例子,如一旦购买了A+S1--》S6、F+S1--》S6,则本次限额就用完了。或者这个组合也可以A+S1--》S6、F+S1--》S5、F+S5--》S6.

  • 额数值:高铁线路初始时,可以根据站点所在城市人口、GDP、流动性(外出打工、商贸物流之类)给予该站点一个限额初始值,后面根据客流量数据持续微调,运营一段时间便会相对正确,到了春节等节假日,根据春运的流向需要做反向调整。

7

模型设计 -- 聚合根


    可以作为聚合根的勾选无非就是车次、站点、座位、票等,但是站点和座位只是归属车次的子域,而票是一次购票的输出凭证,所以,

    以车次作为聚合根是没什么异议的。


    领域模型 (1).jpg


  •  车次领域模型

    包含3个实体,分别是车次、车厢和座位。实体是需要持久化保存的。

    然后基于这些基本元素,计算获得可售矩阵和可售区间,这部分数据可以持久化,也可以放入内存即可,因为只要该车次售票停止(考虑到图中可以补票、升位之类,所以一般是到达终点站后停止),该矩阵则不会再被使用,所以并不需要持久化。


     下面是限额的约束,限额一般会在系统层面定义一些限额模版,然后根据模版生成每一个班次的列车限额配置。


     基于可售矩阵和区间,可以形成一套售票方法,作为车次领域模型对外提供的服务方法。


     当接收到乘客信息、班次、选位(有则满足,无则动态分配),然后生成车票,并锁定区间。


     当支付成功后,则永久锁定该区间,直到客户发生改签行为。


  • 购票资格领域模型

    这个判断相当复杂,需要对接很多外部的系统获的诸如个人信用等信息,当资格通过后,还要继续验证如:

    1、同一班次只能购买一次。

    2、同一人乘坐两趟列车时间是否冲突、地点是否冲突等。


  • 车票领域模型

    作为铁路出行的唯一凭证,当然要独立作为一个领域模型,并且该模型需要外部各类系统对接。


7

总结


这篇文章我只是提出了一个矩阵和区间的建模思路,至于12306是不是就是这样实现的,那就未必了。

学习领域驱动设计,最重要的是不断思考,要从业务聚合的角度去设计,而从根本性改变以数据库设计驱动或者业务事件驱动的开发思路。



作 者 简 介



    唯心,颜超敏。软件行业、互联网行业多家企业创业者。

    个人网站:www.craft6.cn

    本文原创,转载请注明出处。






可通过扫描左侧二维码阅读本文。本站文章均为颜超敏原创,欢迎转载,请注明出处即可,转载可通过下面的社会化工具快速完成。

分享到:


领域驱动设计对12306购票业务的设计思考

12306 领域驱动设计 ddd

12306购票系统的购票业务复杂度则复杂得多,而且这是动态商品的典型案例,甚至于购买的每一张车票都会影响后续可够票的不同组合变化,对于站点较多的车次,持续运营下来,要找出两趟车所售出的票完全相同都不容易

颜超敏,唯心六艺,Craft6.cn,电子商务博客,电子商务研发,电商研发,电子商务研究,电商研究,电子商务专家,电商专家,电子商务知识,电商知识,电子商务教程,电商教程,电子商务模式,电子商务平台,电子商务商业模式,电子商务数据库设计,电商数据库设计,电子商务系统分析,Java架构设计,Java软件架构,B2C,O2O,o2o模式,o2o电子商务,o2o电子商务平台,中国电子商务,电子商务平台建设方案
粤ICP备14060523号 Copyright @2014 -唯心六艺软件