幽霄 阿里开发者 2023-06-27 09:01 发表于黑龙江
阿里妹导读
本文主要讲述我们如何通过一个主干业务流程承接多个业务场景并在数据上可适配到多端型多场景,实现在服务端高质量高效率的“包接口”。
(资料图片)
一、背景
前台业务同学在业务承接过程中总是抱怨大部分业务无法通过设计模式来承接,写的代码是越来越没有追求,理由是我无法预测未来的业务的发展,且设计模式更多的是在框架或中间件中使用。然而设计模式是对能力抽象出的通用模式,从哲学的角度来看世间万物皆尘土,事物都是可以抽象出共同的本质的东西。所以,难道只有底层能力可以抽象,业务逻辑部分就不可以抽象了?必须可以才是啊。
在前台业务承接过程中除了能力可以抽象,还有可以抽象出业务流程,假设在有这样一些业务场景,品搜和图搜、直播间评论和点赞、公域直播会场和私域商详透直播等等,这些各领域内的业务流程“大同小异”,因此都可以抽象出通用的业务流程节点。
但是通常在一个主干流程需要承接的场景有很多,比如直播间互动这个主干流程包括了直播间评论、点赞、求讲解、看证书、进场等等场景,所以我们需要通过主要流程进行进行多场景承接。但是这样还不够,在面对多端型多场景的情况下需要处理返回不同的数据模型。
综上所述,我们如何通过一个主干业务流程承接多个业务场景并在数据上可适配到多端型多场景,实现在服务端高质量高效率的“包接口”,下面会详细介绍。
二、业务承接
如果你面临的问题是在同一个业务域上承接多种类似的业务场景,每天在适配各种端型或者各种场景而对外提供接口时,为了保证应用系统的可扩展性和高效承接业务,那么可以按照如下步骤进行设计。
业务流程抽象
首先需要进行业务建模,抽象出用户用例或者user story,当然具体的粒度可以自己把控,具体如下:
在直播间互动领域内的用户用例如下:
从整个系统出发,挖掘出面向不同的用户提供的能力有哪些,在这些用例背后需要进行的流程和节点又是什么。通过这些流程和节点才能进行后续的系统时序和流程抽象,举例如下
在互动领域内的流程和节点如下:
风控检查 评论持久化 评论上屏 评论进沟通基于用户用例进行分析,这些用例都需要经过什么的流程节点进行处理,然后将这些流程按照系统时序进行呈现。
到此基于上述的用例和时序是不是可以抽象出具体互动流程了,显而易见。
有了系统用例和系统时序这一步就比较简单,从系统时序里很容易可以抽象出具体的流程和流程中的处理节点,具体如下:
对于直播间互动领域可以抽象出的业务流程:风控检查->互动内容持久化-》消息上屏-》互动进IM 对于直播间分发领域可以抽象出的业务流程:直播推荐-》直播间基础信息-》直播流信息-》直播间品信息到此,大家可以按照上述步骤在大脑里对自己的业务域进行抽象出来了。
按照业务主流程可以通过模板模式将处理流程固定下来,如下所示:
@Override@LiveLog(logResult = true)public InteractionResult interactionSubmit(MobileInteractionRequest request, InteractionLiveRoom liveRoom) { Boolean needSave = ((), _SAVE); // 默认保存 InteractionResult saveResult = null; if ((()) || (needSave) || needSave) { saveResult = save(request, liveRoom); if((saveResult) && !()) { return saveResult; } } // 默认进沟通 InteractionResult chatResult; if ((()) || (())) { chatResult = sendToChat(request); if((chatResult) && !()) { return chatResult; } } if((saveResult) && ()) { return saveResult; } return null;}/** * 互动行为保存到数据库或者缓存中 * * @param request * @return */protected abstract InteractionResult save(MobileInteractionRequest request, InteractionLiveRoom liveRoom);/** * 进沟通 * * @param request * @return */protected abstract InteractionResult sendToChat(MobileInteractionRequest request);
业务流程扩展
因在上述模版模式中预留了两个扩展点,所以在子类中可以通过扩展点进行扩展,举例如下:
如果有更多的场景就需要扩展实现上述两个扩展点进行扩展即可,这样保证了业务的高效承接。这里会有两个问题:
在程序运行时如何根据具体的场景选择哪个子类进行逻辑处理 如何进行适配端和场景返回的数据模型针对第一个问题,其实就是如何去if else的问题,这里也给出比较经典的方案:
枚举法 表驱动法 策略模式+工厂模式其中枚举法和表驱动法比较简单易用,原理就是将映射关系封装在枚举类或本地缓存中,这里简单介绍下如何通过策略模式消除if else。
// 策略接口public interface Opt { int apply(int a, int b);}// 策略实现类@Component(value = "addOpt")public class AddOpt implements Opt { @Autowired xxxAddResource resource; // 这里通过Spring框架注入了资源 @Override public int apply(int a, int b) { return (a, b); }}// 策略实现类@Component(value = "devideOpt")public class devideOpt implements Opt { @Autowired xxxDivResource resource; // 这里通过Spring框架注入了资源 @Override public int apply(int a, int b) { return (a, b); }}// 策略处理@Componentpublic class OptStrategyContext{ private MapstrategyMap = new ConcurrentHashMap<>(); @Autowired public OptStrategyContext(MapstrategyMap) { (); (strategyMap); } public int apply(Sting opt, int a, int b) { return (opt).apply(a, b); }}
总结伪代码:
// 抽象类固定业务流程 预留扩展点public abstract class AbstractXxxx { doXxx(Object context) { // 节点1 doNode1(context); // 节点2 doNode2(context); // 节点3 doNode3(context); // 节点n ... } // 扩展点1 protected abstract Result doNode1(Object context); // 扩展点2 protected abstract Result doNode2(Object context); // 扩展点3 protected abstract Result doNode3(Object context);} // 策略处理public class OptStrategyContext{ private MapstrategyMap = new ConcurrentHashMap<>(); static { // 上述模版模式的实现类 ("business1", Xxxx1); ("business2", Xxxx2); ("business3", Xxxx3); } // 初始化 public OptStrategyContext(MapstrategyMap) { (); (strategyMap); } public int doXxxx(Object context) { return (business).doXxxx(context); }}
多场景多端型适配
既然是模版模式,这里的主干流程又是什么呢?主要跟我们解决的问题有关系,按照中的流程步骤,可以抽象出固定的流程为:请求入参处理-》业务逻辑处理-》结果返回处理。
其中业务逻辑处理可以选定为中介绍的通过策略模式选择业务扩展的子类,来处里业务部分;请求入参和结果返回处理部分可以设置为扩展点,供子类扩展。具体伪代码如下:
// 抽象类固定业务流程 预留扩展点 适配多端型多场景public abstract class AbstractSceneAdapter { T doXxx(Object context) { // 节点1 doRequestFilter(context); // 节点2 getBusinessService(context).doBusiness(context); // 节点3 return doResultWrap(context); } // 扩展点1 protected abstract Result doRequestFilter(Object context); // 扩展点2 protected abstract Result doBusiness(Object context); // 扩展点3 protected abstract Result doResultWrap(Object context); // 业务逻辑处理子类 protected abstract BusinessService getBusinessService(Object context);} // 策略处理 根据不同端型场景选择合适的子类public class SceneAdapterViewService { private MapstrategyMap = new ConcurrentHashMap<>(); static { // 上述模版模式的实现类 ("scene1", Xxxx1); ("scene2", Xxxx2); ("scene3", Xxxx3); } // 初始化 public SceneAdapterViewService(MapstrategyMap) { (); (strategyMap); } public Result doXxxx(Object context) { return (scene).doXxxx(context); }}
注:因要适配不同端型不同场景返回不同的数据模型,所以上述伪代码中主流程最终返回的结果是一个泛型,在子类实现的时候进行确定具体返回的类型。
通过模版模式来适配时会有一个小问题,当需要有多个请求入参处理器或者多个结果包装器的时候需要在模版里增加处理节点,但其实这些节点是有共性的可抽象出来的。因此可以针对入参处理器和结果包装器定义单独的接口,需要多个处理器时同时实现接口进行处理。然后这些实现类打包放在单独的类中依次执行即可。当然其中的业务处理部分也可以定义接口动态实现。伪代码如下:
// 入参处理器public interface IRequestFilter<>{ void doFilter(T t);}// 结果包装器public interface IResultWrapper{ ResultdoWrap(Resultres);}public class SceneAdapterViewService implements InitializingBean { private Listfilters; private Listwrappers; private MapstrategyMap = new ConcurrentHashMap<>(); // 请求过滤器实现类 @Autowired @Qualifier("filter1") private IRequestFilter filter1; @Autowired @Qualifier("filter2") private IRequestFilter filter2; // 结果处理器实现类 @Autowired @Qualifier("wrapper1") private IResultWrapper wrapper1; // 业务处理实现类 @Autowired @Qualifier("scene1") private SceneAdapter scene1; @Autowired @Qualifier("scene2") private SceneAdapter scene2; @Autowired @Qualifier("scene3") private SceneAdapter scene3; // 主方法 publice Result sceneAdapte(Object context) { // 请求入参过滤 异常时返回 for(int i = 0; i<(); i++) { try { (i).doFilter(context) } catch { return null; } } // 策略模式执行业务逻辑,执行是按照模版模式 Result res = (scene).doXxxx(context); Result result = res; // 过滤处理,包括树结构改变,数据字段裁剪等 for(int i = 0; i<(); i++) { try { result = (i).doWrap(result) } catch { return res; } } return result; } // 初始化各个节点值 @Override public void afterPropertiesSet() throws Exception { // 入参过滤器 可多个 (filter1); (filter2); // 结果处理器 可多个 (wrapper1); // 业务处理部分 ("scene1", Xxxx1); ("scene2", Xxxx2); ("scene3", Xxxx3); }}
三、接口设计
基于上述两种设计模式来适配时我们的接口又该如何设计,是设计面向通用的业务层接口还是面向定制化的业务接口,两种方式各有优缺点:
优点 | 缺点 | |
通用业务接口 | 1,扩展性强 2,业务承接效率高,无需频繁发布代码 | 1,业务边界不清晰,问题排查效率低 2,接口数据冗余 |
定制化业务接口 | 1,业务边界清晰 2,接口出入参数据无冗余 | 1,无扩展 2,频繁包接口发布代码 |
对于接口提供者来说肯定不希望频繁改动代码发布代码,但是又希望能够在业务承接过程中能够高效适配多端型多场景,因此这里总结了下接口设计原则:
1、对于越底层的接口应该越通用,例如HSF接口、领域服务、中间件提供的接口;
2、对于越上层的接口应该越定制化,例如对于不同的UI适配、不同的场景适配等;
3、对于业务领域内的接口应该通用化,例如直播业务域的分发领域、互动领域内的接口尽可能的通用化;
四、总结
在承接业务过程中会面临频繁包接口、一个view层的数据模型充满了小100个属性,系统的扩展性遇到瓶颈,这些问题除了通过平台化配置化的能力来解决,但是回归到代码本身我们任然可以通过抽象的设计模式来解决。
基于抽象的理论达到复用、高内聚低耦合,降低系统复杂度的目标,设计模式不只是用在底层能力或中间件中,在业务承接过程中亦有大的功效。 千万不要为了用设计模式而刻意使用设计模式,带来的效果适得其反,在选择设计模式时也要三思,落地后再改动成本将会巨大。 在前台业务开发中,需要划分主各个业务领域,在领域中抽象出该业务的处理流程,基于流程可设计相关的扩展和编排能力,方式有很多种,包括SPI、设计模式、DSL等,本文主要通过模版模式和棒棒糖模式来解决问题。 接口设计应该按照越底层越通用,越上层越定制化的原则进行设计,当然在业务域内的接口应尽可能的通用话。关键词:
-
【全球播资讯】从设计模式谈业务开发
幽霄阿里开发者2023-06-2709:01发表于黑龙江阿里妹导读本文主要讲述我
-
北京大学教授张维迎:不应频繁调整利率政策 要尽可能保持其稳定连续性_环球微动态
【北京大学教授张维迎:不应频繁调整利率政策要尽可能保持其稳定连续性
-
天天快资讯丨五次递表港交所,亿腾医药上市渐行渐近?
曾四度向港交所递交招股书未有结果,亿腾医药集团有限公司(EddingGrou
-
新马尔萨斯主义战争论_关于新马尔萨斯主义战争论简介
1、新马尔萨斯主义战争论,亦称“战争人口论”。2、现代西方战争理论的
-
WTI原油日内跌2%
每经AI快讯,WTI原油日内下跌2%,现报68 19美元 桶;布伦特原油跌1 81%
-
营商环境周报(第95期)|世界银行宜商环境“获取金融服务”指标解读
营商环境周报(第95期)|世界银行宜商环境“获取金融服务”指标解读,
-
【环球报资讯】恒辉安防:拟发行可转债募资不超5亿元 用于4800吨超高分子量聚乙烯纤维项目等
恒辉安防6月26日发布向不特定对象发行可转换公司债券预案,公司本次拟
-
保利置业退出投资惠州胜龙房地产 投资数额8000万人民币
惠州胜龙房地产开发有限公司成立于2005年,位于广东省惠州市,是一家以
-
天天速讯:农行陵城支行组织党员干部接受红色教育
海报新闻记者孙晓雨通讯员廉星辉德州报道近日,农行陵城支行组织党员干
-
简讯:名爵怎样激活一键升窗功能(名爵怎样激活一键升窗?)
名爵激活一键升窗方法:把车窗降下来,在车的主驾驶左手侧会有车窗升降
-
新都名片丨红蜂志愿服务队:从“没钱做这干啥” ,到人人都是“红蜂” 世界快消息
文 图半岛全媒体首席记者李晓哲刘笑笑李伟志“2020年刚招募志愿者的时
-
世界滚动:知识竞赛荣誉证书模板内容_竞赛证书招生依据
1、强基计划不需要竞赛证书作为敲门砖2、原自主招生的报考条件便是竞赛
-
出代表什么生肖(出尔反尔是什么生肖?)
出尔反尔是什么生肖?出尔反尔我觉得是生肖蛇生肖蛇的性格特点是占有欲
-
屏山抽水蓄能电站开发主体将确定!川投能源等公司联合体!-天天实时
屏山抽水蓄能电站开发主体将确定!川投能源等公司联合体!北极星电力网
-
2023-06-28 05:00陕西高速公路最新路况实时播报-全球焦点
在我们出行前一定要把自己所去的地方的路况弄清楚,避免在出行过程当中
-
这部国产悬疑片凭啥领跑端午档期
作者:王筱丽刚刚过去的2023端午档期表现抢眼。据国家电影局统计,全国
-
地评线丨银川述评:让传统节日里的文化味更浓 环球资讯
传统节日是激活和提振消费的“黄金档”,更是传承优秀传统文化的重要载
-
今日播报!陕西发布冰雹橙色预警 部分地区未来6小时内出现冰雹天气可能性很大
陕西省气象台6月27日17时13分发布冰雹橙色预警信号:预计下述地区未来6
-
共进股份等51股近五日获机构净买入
近五个交易日的龙虎榜当中,115只个股出现了机构的身影,其中51只股票
-
董事长前妻拟高位套现带崩股价 深交所发函问询 “秒回”监管 昆仑万维跌势难止 焦点短讯
在连续数日下跌后,周二AI概念股终于止跌反弹,而对于之前的连跌,市场