杨立波
(太原学院计算机工程系,山西 太原 030032)
网站因频繁推出各种商业促销活动,并随着活动临近上线,技术开发人员不得不添加新的代码或修改程序以满足新活动的要求。促销活动的流程是这样的,活动的期间、参与活动的商品范围和活动规则由市场和运营部一起定制,由技术部门实现和测试,最后由市场和运营进行验收,然后部署到生产环境。但由于活动规则的无规律性,技术部门在设计活动时很难做到扩展性和复用性俱佳的设计,调整程序是不可避免的,使得每次促销活动必须相应调整很多代码。经初步分析,程序调整将涉及到商品展示、购物车和下订单,这些调整几乎涉及到了网站的所有展示前台。
促销活动的传统实现方式中,开发和测试所花的时间是整个过程中最长的,压力也是最大的,如图1所示。
图1 传统实现方式的周期
针对于传统方式的不利因素,技术部门提出了一种新的解决方法,将各种活动规则由运营人员“翻译”成公式,开发人员提供一个能影响活动结果的公式“插件”,“插入”到需要受活动影响的地方。从图2中我们可以看到,按新的解决方案执行前后的主要阶段和所花费的人力和时间相对先前的传统模式、公式的编写和测试的周期相对技术部门的开发周期要短很多,所以不会导致市场和运营部门过大的压力,但是对运营者角色提出了更高的要求,需要学习掌握怎样编写公式,但是相对于整体实现周期的大大缩短,这样付出是很值得的。
图2 新实现方式的周期
Sun JDK6+增加了对脚本语言的支持,实现包含了一个基于Mozilla Rhino的脚本语言引擎,即支持JavaScript,JDK6+支持脚本的基本原理是将脚本语言在运行时编译成字节码,因此脚本上下文能融入到JVM环境中,即能使用或改变Java Bean的状态。脚本的动态性和强大的功能能满足各种复杂的需求,但在实际操作环节,让市场和运营人员掌握脚本语言会花费很大的学习成本,而且按照技术开发人员的要求去要求运营人员是不太实际的。另外,如果使用脚本引擎,可能只会用到脚本引擎中不到百分之一的功能和特性,但如果使用自定义公式系统,可以确保公式的解析和执行效率都是程序员可控的,整体效率会比脚本引擎高很多。因此非常有必要自定制一套高效的公式系统。
1.3.1 公式系统目标
·表达式运算(赋值,运算和逻辑),表达式中支持函数,变量
·支持控制结构:if condition1{}else if condition2{}else if..else{}
·支持循环控制结构:while(condition){loop}
·支持/* */注解
·支持从外部注册函数,函数支持参数数目动态可变
·支持与外部交换公式变量(注:这里的外部指运行公式的具体项目环境)
实现以上目标后就能对类似如下的几行公式进行处理:
例如:公式示例
/*订单金额超过1000送500元优惠券*/
IF[S_ORDERSUM]- 1000 >-0.001{giveCoupon([MB_ID],201010);}
/* 送积分*/
givePoint([MB_ID],[S_POINTSUM]);
通过公式解析执行后能执行这样一段业务:参加某活动的订单金额满1000元的送500元优惠券,积分100倍返还。
1.3.2 公式系统的实现过程
公式系统的实现过程主要实现以下几个主要步骤:
解析。扫描被解析字符串,将中缀式转化为后缀式,拆解为最小运算单元,然后将拆解的运算单元压入队列,在这个过程中需要提前确定运算符号和逻辑符号。
运算。对后缀式队列中的运算单元进行计算,借助堆栈这种数据结构能很方便地实现运算处理。
处理异常。一个完整的公式系统必须有一套完备的异常体系来支撑,异常体系的设计好坏决定了公式系统的可用性。因此有必要分别为解析过程定义一套解析时异常,为运算过程定义一套运算时异常类,完备的公式异常使公式调试、测试更加轻松,让公式系统更加完整可靠。
建立公式帮助类。为方便在实际项目环境中运用公式系统,还需要建立了一个公式帮助类,以方便处理各种存在形式的公式,为增强公式的表达力,引入了对if condition1{}else if condition2{}else if..else{}的控制结构的支持,如果有需要,还可以加入对for循环等 loop结构的支持。
从以上可以知道,自定义公式系统包含两个关键部分:解析和运算,前者负载扫描公式文本,识别出操作数和操作符并封装为集合对象,然后按后缀式的遍历顺序存入队列;后者将借助堆栈对解析产生的队列进行运算。同时还可以向公式环境中注册自定义函数。一类扩展能让项目与公式交换变量,二类扩展提供了让公式直接操作项目Bean的能力。
2.1.1 促销活动影响分析
例如:
(1)降低销售价格:降价的方式可以很复杂,直接折扣,如7折;按条件折扣,如满100打九折,满200减100,成交的前5件商品5折,等等。
(2)赠送商品:如满1000送一件指定的牛仔裤。
(3)赠积分,优惠券,抽奖机会。
(4)免运费。
(5)提升用户会员级别,如从普通到VIP。
分析促销活动的影响面,如表1:
其中展示货架和购物车环节是只读模式的,即仅是提示作用。促销活动的结果不会持久化,与购物车不同的是下订单时促销活动的结果不仅要提示,而且必须记录下来,并跟客户定单号关联,在支付成功后生效,这样就可以考虑用一个活动结果类用来收集不同场合下的活动结果,至于结果的处理(只读,可写),再根据具体情况而定。
2.2.2 促销活动业务抽取
分析影响面中名词类型的关键字,可以分析出如下公式可调用的变量:
商品单价,订购数目,参与活动的商品总金额、折扣总额、积分总额。
表1 促销活动影响面
从以上影响面中过滤出动词类型的关键字,编目为公式可调用的外部函数:送积分,送优惠券,从总额总减除折扣。在分析完活动的影响后,需要将活动以公式的形式编写出来,并让一个执行机构在需要活动的地方执行。这些受影响的地方分别是:
(1)商品展示管理
(2)购物车管理
(3)订单管理
2.2.1 促销活动数据模型
促销活动数据模型,如图3。
2.2.2 促销活动举例
例如:国庆之前,市场部准备策划了一个大型商业活动“国庆大派送”,参与此活动的商品一律5折,积分100倍返还(金额乘以100),如果订单金额超过1000元送500元优惠券(优惠券编号为201010)。
(1)添加一条活动记录,活动名称“10.1国庆大派送活动”,活动时间 2010.09.3021:00 -2010.10.0623:59。
图3 促销数据模型
(2)编写活动内商品公式
[E_SUM]=[P_PRICED]*[P_ORDER_NUM];/*E_SUM是临时变量*/
[S_DISCOUNTSUM]=[S_DISCOUNTSUM]+[E_SUM]*0.5;/*统计当前商品折扣总额*/
[S_POINTSUM]=[S_POINTSUM]+[E_SUM]*100;/* 统计当前商品所送总积分*/
[S_ORDERSUM]= [S_ORDERSUM]+[E_SUM];/* 统计活动商品的订单总额*/
(3)编写活动汇总公式
/*订单金额超过1000送500元优惠券*/
IF[S_ORDERSUM]- 1000 >-0.001{giveCoupon([MB_ID],201010);}
/* 送积分*/
givePoint([MB_ID],[S_POINTSUM]);/*折扣*/
discount([S_DISCOUNTSUM]);
对于电子商务网站,促销活动是一类重要的业务,就像商场和超市离不开促销一样,其重要性是不言而喻的。在准备构建电子商务网站项目之初,应该充分考虑促销业务对于项目架构的影响,选择合适的实现方案。本文在传统系统的基础上,给出了促销另一种实现方案,考虑到促销手段的多样性以及多变性,通过建立一个公式体系,并将这段业务抽取出来,通过促销活动“插件”来执行,从而达到让业务独立于程序开发,实现业务公式化,缩短了业务实现周期。