之前在服务化设计模式实践(http://blog.brucefeng.info/post/service-design-patterns-practices)里面介绍了交易侧系统服务变迁的模式,服务的变迁更好的支持了业务的发展,伴随着业务的发展,对业务系统内部的要求也更好,需要具有更好的扩展性。随着业务的不断发展,每个服务内部的逻辑也变得越来越多,需要有更好的抽象来支持以后更多的业务类型。 1. 项目业务背景重构的项目有订单服务,预订系统,退款系统;这三个系统都是与用户交易行为息息相关。 其中订单系统参与重构的模块为订单创建,订单状态流转,订单支付; 预订系统的重构主要为了支撑更多的预订方式,如之前已经支持的库存模式、商家接单模式和售中客服模式,伴随着重构还需要支持商家系统直连模式,而且需要能够支持以后业务发展更多的预订模式。 退款服务的复杂度主要来源于多种退款类型,如用户退款,系统退款,商家退款和客服退款等多种类型,而每种类型又有各种不同的退款规则;退款服务需要支持多种业务,如已有的KTV预订和将要扩展出的酒水点单。 在这里我们主要来讲讲预订系统重构,因为这个系统的重构几乎涵盖了订单服务和退款服务重构所使用到的技术 目标
2. 业务抽象由图中可以看出,业务流程非常复杂,一个订单的预订过程会根据不同的情况走不同的预订渠道,如果一个预订渠道因为某种原因预订失败了,可能会继续使用另外一个预订渠道继续进行预订,也就是会发生流转。 另外,在预订成功和预订失败时,会需要做一些其他操作,例如发送短信告知用户结果等;
根据这些条件我们做了以下抽象:
一级业务是系统最重要的业务,业务流程标准化且会直接影响业务结果;二级业务是一级业务一个步骤,但因为预订渠道的不同而有个性化操作;三级业务是根据业务结果来执行的操作,不会再影响系统的主流程。 3. 重构3.1 核心业务流程
开始预订: publicclassKtvReserveService{
publicKtvReserveResultDTOreserve(KtvReserveContextreserveContext)throwsReserveException{
//校验
KtvValidateResultvalidateResult=this.ktvReserveValidateStack.validate(reserveContext);
if(validateResult==null||!validateResult.isValid()){
returnKtvReserveResultDTO.createFailedResult("validateinvalid");
}
//判定预订渠道
KtvReserveChannelreserveChannel=reserveChannelJudgeService.judgeChannelType(reserveContext);
reserveDataService.store()
reserveDataService.transferReserveChannelStatus();
//开始渠道预订
ChannelResultchannelResult=this.reserveChannelService.reserve(reserveContext);
returnKtvReserveResultDTO
.genResult(channelResult.isSuccess(),channelResult.getDesc(),reserveFlow.getReserveId());
}}渠道反馈预订结果: publicclassKtvReplyReserveService{
@Override
publicReplyReserveResultreply(KtvReplyReserveInforeplyReserveInfo)throwsReplyReserveException{
//校验
KtvValidateResultvalidateResult=replyReserveValidateStack.validate(replyReserveInfo);
if(validateResult==null||!validateResult.isValid()){
logger.warn(String.format("%svalidatefailed",param));
returnReplyReserveResult.createFailedResult("validatefailed");
}
//更新预订状态
reserveDataService.transferReserveChannelStatus();
ReplyReserveResultresult;
//判定预订结果
KtvReserveStatustoReserveStatus=this.reserveChannelJudgeService.judgeReserveResult(replyReserveInfo);
booleanreserveFailed=
toReserveStatus==null||toReserveStatus==KtvReserveStatus.ReserveFailed||toReserveStatus==KtvReserveStatus.Init;
if(reserveFailed){
//预订失败处理
result=this.reserveFailed(replyReserveInfo);
}elseif(toReserveStatus==KtvReserveStatus.ReserveSuccess){
//预订成功处理
result=this.reserveSuccess(replyReserveInfo);
}else{
//需要转移其他渠道预订
result=ktvReserveTransferService.transferChannel(ktvReserveContext);
}
//渠道处理内部事务
this.replyReserveChannelService.reply(replyReserveInfo);
returnresult;
}}3.2 校验栈在业务性很强的服务来说,在业务开始之前需要有复杂的校验,如果在这个服务中支持多种业务类型,还需要根据不同的业务类型来选择不同的校验逻辑,因此在服务中将校验栈独立出来。 校验栈的组装采用责任链模式,这样每个校验service通过组装的方式即可以灵活支持多种校验。但是对于业务主流程来说,把校验service的组装服务并不适合放在主业务流程里,因此在重构的时候将校验栈的组装逻辑放在一个单独的service中采用代理模式进行组装。 publicinterfaceKtvReserveValidateService{
/***校验预订信息*@paramreserveContext*@return*/
KtvValidateResultvalidate(KtvReserveContextreserveContext);}publicclassKtvReserveValidateStackimplementsKtvReserveValidateService{
privateList |
|
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系
[邮箱地址] 删除
|