老房改造系列--如何用一套流程接入所有业务线

news2024/11/25 15:33:49

ToB业务没有太多高并发的挑战,但同一套流程往往可能需要承载各种差异化的复杂业务需求,所以如何让系统具备良好的扩展性成为ToB业务系统最大的挑战。本文将详细讲述如何用一套流程接入所有业务线?

老系统改造不是一蹴而就的,从2022接手版权资产管理-财资系统之后,一直在进行架构重构和稳定性建设。将新吸纳的优秀架构经验融合,以业务为中心随着需求迭代进行老系统的架构升级。过程中实践和沉淀了一些不错的B端开发方法论,整理成“老房改造系列”分享给大家。

《老房改造系列--上线十年,81万行Java代码的老系统如何重构》

《老房改造系列--如何用一套流程接入所有业务线》

《老房改造系列--稳定性摸排灵魂三问》

前言

ToB业务没有太多高并发的挑战,但同一套流程往往可能需要承载各种差异化的复杂业务需求,所以如何让系统具备良好的扩展性成为ToB业务系统最大的挑战。以版权资产管理-财资系统举例,横向需要承接财、法、商、boss四类角色,纵向要支持十几条不同频道业务线,这样粗略计算会有近百维差异化业务需求,这会比C端的用户画像要复杂的多。如何用一套流程接入所有业务线?

之前在《上线十年,81万行Java代码的老系统如何重构》一文中有提到过,老系统重构的时候通过自上而下的方法进行流程拆解,再通过模板模式,用继承重写差异化method的方法进行差异化扩展。这种方法可以解决代码臃肿问题,也可以进行快速的扩展。但是当接入流程逐渐增多、流程差异化大小不一,会再一次引入一些坏味道。

问题

还是以付款模块举例,付款作为整个业务流程中最末端的节点,从流程图上可以看出来付款本身并没有特别复杂的业务逻辑,但是需要支持的业务却特别的多,那就意味着付款这个服务必须要有很好的扩展能力才能支持快速接入。

第一版重构时使用的是模板模式进行扩展,但这样设计会产生一些问题,首先从业务扩展实操上来说,使用模板模式进行扩展会出现俩个问题。

1、继承关系复杂:

随着接入业务逐渐增多继承关系会越来越“胖”或者越来越“高”,当一个新的扩展品类来的时候,我们都需要决策一件事情,新来的品类是继承最根部base类(变胖),还是找一个实现逻辑最相近的类来继承(变高)。变胖带来的后果就是复用性不好,一样的实现逻辑可能会出现在多个流程中;变高带来的后果是父类实现的修改有可能会影响子类的业务。

2、粒度过粗

当使用继承重写的方式进行扩展的时候,必须重写整个方法。假设流程某一个步骤的method的实现中有3条规则,而新的流程步骤中只有第1条规则与父流程不同,但由于继承关系的限制另外2条规则需要复制过来,这就又产生了重复逻辑代码,影响代码复用性。

设计模式中也提到过“多用组合,少用继承”的建议,原因如下

总结来说,“多用组合,少用继承”强调的是以聚合的方式来组合对象的能力,这样可以构造出更灵活、松散耦合、易于维护和扩展的设计模式。当然,在具体实践中,并非完全排除继承,而是倡导根据实际需求权衡使用,对于“is-a”的语义关系合理使用继承,而对于“has-a”或者“can-do”的能力可以通过组合来实现。

扩展体系建设

为了解决上面的问题,做了几件事情:梳理流程差异点,梳理领域模型,二次抽象隔离层,基于SPI的扩展体系建设。

梳理流程差异点

还是前面那张图,重新梳理后把有差异的部分标出来。

业务流程:

  • 付款发起的来源很多,而且后续会越来越多;
  • 基于不同业务对于付款单的校验逻辑也会有差异;
  • 提交审批后由于业务线不同,审批流初始化和审批流程肯定有差异。

View层:

  • 付款单中要展示各自的业务单据信息,用来辅助审批人决策;
  • 填写表单的时候,下拉字典根据业务需求会有不同的选择范围;
  • 风险提示的卡片也会跟各自业务相关。

权限控制:

  • 基于身份的权限控制是固定的,但是有业务单据权限必然要有能查看基于该单据发起付款的权限。

消息同步:

  • 每个业务对于付款流程中的消息的消费也各有不同。
  • 有了这张图之后我们就知道流程中所有的业务差异点,可以辅助无遗漏的抽象扩展点。

梳理领域模型

第二步进行了领域模型的梳理,梳理后可以看出来付款的核心域中,付款单据是聚合根。各个业务都可以发起付款,所以其他领域都算是付款的支撑域。但由于之前的付款单中会聚合引入其他域的单据作为付款依据,所以会导致每次接入新的业务类型,都需要重新引入新的业务单据,这也就导致了付款核心领域是不稳定的。核心域不稳定带来的结果就是每次大量的升级和兼容,那怎么样把不稳定因素隔离开?

二次抽象隔离层

如上图所示,这里二次抽象出了付款凭证,付款单据的后续流程只依赖付款凭证,从其他业务域单据到付款凭证的Translator可以放在业务域来实现。这样当付款域接入新业务时,核心域的代码是稳定不变的,即减少了兼容逻辑代码也可以保证付款流程的稳定性。

现在解决了核心域代码稳定的问题,但还是会有很多不同业务带来的流程差异问题,如下:

 

基于SPI的扩展体系建设

既然这些都是根据不同业务会带来的差异,那我们可以将定义和实现倒置,由付款域定义接口,业务域来实现差异的部分,所以直接使用SPI的方式来扩展。行业上有很多SPI的实现方案,如何选择?

方案需要满足俩个条件:

1、根据业务身份获取扩展实现

2、接入成本:由于我们是老系统改造,所以改造要考虑ROI

JAVA SPISpring-SPIDubbo\Hsf-SPITMF-SPICOLA-SPI
优势原生自动装配天然支持RPC调用、分布式功能支持业务身份自动映射、支持批量扩展点与顺序等,功能强大支持业务身份自动映射、实现简单、支持本地和HSF扩展点
劣势每次加载全量、不支持业务身份自动映射、非线程安全不支持业务身份自动映射不支持业务身份自动映射配置复杂、封装能力层带来理解成本、老系统改动成本高不支持批量扩展点与顺序

由于前三个不是天然满足需求1,如果想用需要二次开发,付款中对于批量扩展点的需求很少,所以基于以上方案选型对比最后选择COLA-SPI进行扩展体系建设。大家可以根据自身的业务来选择合适的方案,没有最完美只有最合适。

最终扩展体系建设之后的架构图如下:

付款的应用架构上在流程编排层和Domian层之间加入了扩展层,付款流程中调用的差异化部分,付款域来定义接口,接入业务域来做实现;在过程当中用到的一些付款域的通用方法,付款域来定义接口,付款域来实现。

每个接入的业务域,都将业务差异化逻辑封装到二方包里,通过maven仓库加载到付款域中。付款域应用启动时会将扫描所有扩展点实现,并将业务身份与扩展点实现绑定( Map<Scenario,I***ExtPt> ),放入SpringContext中。一个付款流程运行时,会根据业务身份来mapping响应扩展点实现。cola-spi支持三维坐标系,具体使用可以参考cola文档。

扩展点的方案毕竟是要引入外部代码和调用外部服务,所以一定保证安全性和稳定性:

开放原则:如图不详述

业务身份安全:二方包是通过maven仓库引入进来,所以必须要保证二方包中有配置业务身份,并且保证引入的是release版本,这样可以保证在不修改版本的前提下,业务身份是安全的。

数据隔离:大部分B端业务系统都是要求有严格的数据隔离的,一旦被破坏会带来数据泄露、合规等风险。

MQ消息隔离:传统的解决方案是把所有消息有生产方发送,统一发送到一个topic下,通过tag信息来做隔离,但这样就意味着可以接收到所有业务身份下的消息。为了解决这个问题,这里使用的方案是把消息发送的职责交给接入方,生产方只负责在可以发消息的流程节点去调用扩展方法,传入单据信息,至于发送到哪个topic、发送哪些信息、是否发送都有接入方扩展实现。

接口查询隔离:由于扩展方法在实现过程中,一定会用到一些通用方法,比如反查历史单据信息等。此时如果接口不做数据隔离,那就有可能返回其他业务身份下的数据。所以需要拦截器进行方法参数的拦截,并且和业务身份进行校对。

环境隔离:如图不详述

逻辑稳定性:线上二方包引入release版本,可以保证包内逻辑的稳定和调用的RPC服务版本稳定,并且在所有扩展方法外进行异常处理。但还是会有RPC服务升级带来的逻辑问题,目前没有万无一失的方法,只能从三方面来努力。

1、前:严格遵守开放原则,并且在接入文档中说清楚返回结果的用途。

2、中:对扩展点接入自动化测试手段

3、后:加入扩展点坐标系粒度的开关控制,发现问题及时止损

流程依赖扩展点:如图不详述

总结

为了进一步解决流程差异化给B端服务带来的挑战,在老系统改造的场景下通过以下四个步骤来升级架构:

①梳理流程差异点,找到所有业务流程有差异的部分

②梳理领域模型,找出核心域和支撑域的边界

③二次抽象隔离层,保证核心域的逻辑稳定

④基于SPI的扩展体系建设,实现基于不同业务身份的流程差异

提升了业务流程的可扩展性,解决了之前架构使用模板模式带来的变“高”变“胖”的问题。同时扩展体系将接入的业务逻辑交给接入方,也解决了对核心域开发人员对支撑业务域理解不审和核心域开发人力有限的问题。

我相信这也不会是最完美的解决方案,随着业务量的增多一定会带来新的问题,我们需要做的就是不断的学习和吸纳,将新的思想融入到解决方案中,让系统架构和开发者都处在一个良性的循环中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1588004.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【自用笔记】【大数据】

1 mapreduce &#xff08;1&#xff09;Map任务的数量&#xff1a;由输入数据的大小决定的&#xff0c;如文件数量和大小、HDFS块大小以及FileInputFormat的设置等。每个MapSlot可以运行一个Map任务 &#xff08;2&#xff09;Reduce任务的数量&#xff08;分区数&#xff09;&…

想走?可以!先买票--迭代器模式

1.1 乘车买票&#xff0c;不管你是谁&#xff01; 售票员检查谁没有买票&#xff0c;把车厢里的人都遍历一遍。 1.2 迭代器模式 迭代器模式&#xff08;Iterator&#xff09;&#xff0c;提供一种方法顺序访问一个聚合对象中的各个元素&#xff0c;而又不暴露该对象的内部表示…

[CSS]布局

盒子就是把网站分割成一小块一小块的吧&#xff0c;然后方便移动或者管理 背景 属性名描述background-color设置元素的背景颜色。background-image设置元素的背景图片。背景图片与背景颜色同时设置时&#xff0c;则图片覆盖颜色。写法如下&#xff1a;background-image: url(&…

【洛谷 P4017】最大食物链计数 题解(深度优先搜索+动态规划+邻接表+记忆化搜索+剪枝)

最大食物链计数 题目背景 你知道食物链吗&#xff1f;Delia 生物考试的时候&#xff0c;数食物链条数的题目全都错了&#xff0c;因为她总是重复数了几条或漏掉了几条。于是她来就来求助你&#xff0c;然而你也不会啊&#xff01;写一个程序来帮帮她吧。 题目描述 给你一个…

【Java核心技术】第4章 对象与类

1 面向对象 2 自定义类 形式&#xff1a; class ClassName { field // 字段 constructor // 构造器&#xff08;构造函数&#xff09; method // 方法 } 如&#xff1a; class Employee {private String name;private double salary;private LocalDate hireDay;public Emp…

【拓展技术】——AutoDL服务器训练Pycharm使用注意点Pycharm配置AutoDL

一、AutoDL服务器模型训练 AutoDL是一个为研究人员、开发者和企业提供的平台&#xff0c;它致力于提供一个高效、可靠和易用的环境&#xff0c;以支持复杂的计算任务和AI模型的部署&#xff1a; 高效的并行计算资源&#xff1a;AutoDL拥有强大的计算集群和高性能的计算节点&a…

MySOL之旅--------MySQL数据库基础( 2 )

本篇碎碎念:尽自己最大的努力,直到筋疲力尽为止,加油 今日份励志文案: 别人都在前进,我为什么要停下 目录 补上一条博客缺失的内容 常用数据类型 数值类型&#xff1a; 字符串类型&#xff1a; 日期/时间类型&#xff1a; 二进制类型&#xff1a; 其他类型&#xff1a; …

工业4G路由器SR500护航清远市智慧环卫项目

一、项目背景 随着智慧城市建设的不断推进,清远市政府高度重视城市环卫管理的智能化升级。由于清远地处山区,环卫作业路线长、工作环境复杂,有效监控和调度成为亟待解决的难题。 经过严格筛选,清远市最终选定了星创易联科技的SR500双网口4G工业路由器,与环卫车载智能终端配合使…

BM25和语言模型的改进研究

原文链接&#xff1a; BM25和语言模型的改进研究 摘要&#xff1a; 近期关于搜索引擎排名函数的研究报告指出&#xff0c;BM25和带Dirichlet平滑的语言模型有所改进。本研究通过在INEX 2009维基百科语料库上训练&#xff0c;然后在INEX 2010和9个TREC语料库上测试&#xff0…

ffmpeg命令与批处理编程

(一) CMD脚本查找所有文件 powershell与cmd转换 powershell与cmd虽然同为windows命令&#xff0c;但许多命令并不通用。 CMD换行符 a 在CMD下&#xff0c;可以用^作为换行符&#xff0c;类似于Linux下的\。举例如下&#xff1a; start pemu.exe ^ -net nic,vlan1,macaddr…

低功耗接地故障中断器D4145,无需任何电位计符合 U.L.943 标准,直接连接至SCR

概述&#xff1a; D4145 是交流电源插座接地故障中断器的低功率控制器。 在发生有 害或致命冲击前&#xff0c;这些器件检测是否有危险的接地情况&#xff0c;比如设备( 与 AC 线路反相连接) 与水以及与裸露电线接触。内含一个 26V 齐纳并联稳压 器、 一个运算放大器和一个…

实体抽取全解析:技术与实战

目录 一、前言二、实体抽取技术概览基于规则的实体抽取基于统计的实体抽取基于深度学习的实体抽取 三、实体抽取的发展历程早期的实体抽取方法基于规则和词典的方法基于特征的机器学习方法 深度学习时代的实体抽取从传统模型到神经网络序列标注模型的兴起预训练语言模型的革命 …

第十三届蓝桥杯省赛大学B组编程题(c++)

D.刷题统计 二分(AC): 注意:二分时右边界 right 的确定 #include<iostream> using namespace std; long long a,b,n; bool check(long long x){long long tx/7;x%7;long long temp0;if(x<5) tempx*a;else temp5*a(x-5)*b;long long cntt*(5*a2*b)temp;return cnt&g…

第十一届蓝桥杯大赛第二场省赛试题 CC++ 研究生组-七段码

#include<iostream> using namespace std; const int N 10, M 7; int e[N][N] {0}, f[N], open[N];//e[i][j]表示i和j之间是否连通&#xff1b;f[i]表示结点i的父节点&#xff1b;open[i] 1表示结点i打开&#xff0c;0表示关闭 long long ans 0;int find(int x){if(…

水果店加盟哪家好?仙果很忙水果零食店怎么样?

人们越来越重视饮食健康,一些水果类的食品获得了更多消费者的认可。很多投资者也看中了水果店的商机,想要开一家品牌水果店。那么现在水果店加盟哪家好呢!在加盟前,需要了解当前市场的发展潜力,了解哪个项目更值得人们加盟。 健康水果餐饮文化近几年受到了更多消费者的认可,开…

中国网站数量竟然比2022年多了10000个

关注卢松松&#xff0c;会经常给你分享一些我的经验和观点。 CNNIC发布了最新中国互联网报告&#xff0c;报告显示&#xff1a; 2018年中国有523万个网站&#xff0c;2023年13月下降到388万个&#xff0c;5年时间网站数量下降30%&#xff0c;但相比于2022年12月&#xff0c;竟…

Kyligence 发布企业级 AI 解决方案,Data + AI 落地迈向新阶段

4月11日&#xff0c;Kyligence 2024 数智论坛暨春季发布会成功召开。Kyligence 正式发布全新的企业级 AI 解决方案&#xff0c;基于服务金融、零售、制造、医药等行业领先客户的落地实践&#xff0c;Kyligence 为企业提供准确、可靠、智能的 AI 指标平台一站式解决方案&#x…

分布式系统:缓存与数据库一致性问题

前言 缓存设计是应用系统设计中重要的一环&#xff0c;是通过空间换取时间的一种策略&#xff0c;达到高性能访问数据的目的&#xff1b;但是缓存的数据并不是时刻存在内存中&#xff0c;当数据发生变化时&#xff0c;如何与数据库中的数据保持一致&#xff0c;以满足业务系统…

Excel·VBA二维数组S形排列

与之前的文章《ExcelVBA螺旋数组函数》将一维数组转为二维螺旋数组 本文将数组转为S形排列的二维数组&#xff0c;类似考场座位S形顺序 Function S形排列(ByVal arr, ByVal num_rows&, ByVal num_cols&, Optional ByVal mode$ "row")将数组arr转为num_rows…

【并发】 第四篇 原子操作(一)

导航 一. 非原子操作二. 原子操作1. 使用锁2. 使用原子类一. 非原子操作 首先在并发场景中, 一个线程需要对内存中的某个共享变量的值进行修改时,大致可分为以下三个步骤: # 1.从内存中读取共享变量的值,到线程本地 # 2.执行修改操作 # 3.将修改后的新值,重新写回到内存中此时…