CRM系统化整合从N-1做减法实践 | 京东物流技术团队

1 背景

京销易系统已经接入大网、KA以及云仓三个条线商机,每个条线商机规则差异比较大,当前现状是独立实现三套系统分别做支撑。

2 目标

2022年下半年CRM目标是完成9个新条线业务接入,完成销售过程线上化,实现销售规则统一。

3 问题

前端实现数据存储与逻辑代码耦合一起,无法复用,无法扩展,组件化拆分难度大。
组件拆分颗粒度较大,业务功能抽象不充分,缺乏复用性。
代码重复编写,相似功能冗余严重,开发和维护效率低。
代码版本多,接口不统一,开发、运维成本高,难扩展。
每个条线阶段、条线内每个商机阶段推进规则都是通过代码单独实现,开发、维护成本高,规则调整都需要代码调整并上线,时效性低,同时阶段规则维护在代码中,无法直观呈现和规则统一收口,运维难度大。

4 实现

4.1 方案调研

方案调研阶段,针对业务场景,多次组会对于底层实现方案进行充分讨论,列举每个方案优劣势,选择最适合当前业务场景的解决方案,最终选择上图的框架升级方案。

4.2 方案设计

4.2.1 设计思路

快速实现相似业务,减少相似代码,通过前端组件化、后端服务标准化、商机阶段配置化技术手段,支持各条线快速复用和灵活扩展。

4.2.2 前端组件化

1.前端现状
数据存储与逻辑代码耦合在一起,无法复用,无法扩展,组件化拆分难度大。表现为mixins逻辑代码与store数据存储耦合在一起,既降低了代码的可读性,也降低了store数据读写的灵活性。举个栗子,在人员信息集合中,本来可以针对name和sex两个字段在各自的组件进行维护即可,可现实是两个组件不得不调用同一个mixins进行维护。
组件拆分颗粒度较大,业务功能抽象不充分,缺乏复用性。组件的拆分没有一个清晰的界限,没有依据业务功能进行拆分,导致有一些组件不够纯粹,不符合单一职责原则,无法复用。在后期的维护过程中组件逐渐变得臃肿不堪。
代码重复编写,相似功能冗余严重,开发和维护效率低。由于组件无法复用,在后期维护过程中,开发人员对于类似的功能,不得不写了很多相似的代码,致使整个项目代码冗余、重复,慢慢的变得不可维护。
2.解决方案
针对本次商机条线接入功能,采用现有技术方案很难对后续条线依次接入,一个条线一套代码实现,接入周期长人力成本高,按期完成目标是一项不可能完成的挑战。经过技术方案调研,决定搭建一套求同存异(同为各个条线共用部分,异为各个条线单独部分)的前端组件化方案。依据业务功能,抽象出独立业务组件模块,依据条线插拔式组装,搭建出可维护、可扩展、灵活性高的组件积木化方案,在业务扩展性比较强的前端模块架构中优势更加明显。
 


组件积木化方案特点如下:
1.方案采用积木化前端组件搭建,其中任何一个组件都可以被替换(webComponent),任何一个父组件都可以扩展n个子组件。以上图商机信息组件为例,各条线商机信息所包含的字段存在差异,每个条线所对应的商机信息组件不同,最终会根据条线选择对应的组件加载。

2.数据统一管理(store),组件和数据之间为更新和依赖关系,当有组件更新数据时,其他组件也会立即更新,而不用相互传值。以商机详情组件为例,商机详情中修改了商机名称字段,则所有用到商机名称的组件都会得到更新。这需要提前对组件和store进行数据依赖更新的建立,通过computed与store双向依赖和监控机制,当computed监听store数据变化,将变化的数据更新到组件上,组件中通过store的mutaions更新数据到store上。

商机详情组件化抽象示意图如下:

4.2.3 后端标准化后端现状

由于前期未对条线的领域模型和功能模块进行抽象,导致烟囱代码林立;每个条线接入都要重复开发多套代码,各端(PC、移动端)接口不统一,前后端联调对接接口都需要区分多套;各条线独立开发部署,随着系统功能的丰富以及产品线持续增加,个性化需求和缺陷修复极大的消耗了研发资源和精力。同时,无法满足各条线商机阶段推进可定制的业务诉求,大致状态如下图。


2.解决方案
通过梳理商机流程与功能可以发现,商机中各条线既有相同的功能模块,也有各自独有的功能,例如商机创建、关闭、激活等流程每个条线差异不大,但是有些相似的功能模块各条线也存在差异,例如大宗的关闭商机与服务+中的关闭商机各自的关闭条件就不一样;那么基于此种业务场景,首先我们需要将主流程抽象出标准服务能力;例如,商机创建流程,我们将其定义为权限校验、参数校验、额外特殊校验、补充信息、模型转换、保存数据、跨区校验、后续额外处理等标准模板服务;每一个步骤方法都是抽象的,后续每个条线都将继承它,可以重写自己的逻辑;这样一个创建商机流程就标准化了。

上述我们是根据业务特性进行的模板抽象固化,但是如何将整个架构按照条线来走呢,这就需要我们将每个条线的流程进行抽象,例如,几乎每个条线都有创建商机、关闭商机、激活商机、修改商机等相同的动作,我们需要将这些抽象成固定的接口;然后各自条线都实现该接口并声明成策略,根据入参的识别自动分流至不同条线策略处理;也就形成了按条线为策略锚点的模式。

所以总体上是利用策略模式 + 模板模式支持各条线快速复用和灵活扩展,整体服务抽象复用及扩展思路形成大致的核心类图如下图:

整个商机的后端架构经过单条线多套接口处理的方式调整为适配所有条线统一接口接入;后端整体架构大致分5层,在核心层其实还会细分逻辑层,代理层以及Mapper 层。

首先我们在这次改造过程中统一了接口层,不在区分PC端接口,JME 端接口,统一以JSF接口形式提供出去;然后借助物流网关配置PC认证以及JME认证并一致以Http协议对接出去,保证了接口层面的统一。在适配层我们是定义了一个策略适配器,它会扫描所有声明了注解@LineType的策略处理器并缓存,然后根据解析入参中的条线进行自动匹配处理器进行分配处理,从而达到请求的自动分配处理。在核心层中其实更多的是模板方法的抽象与封装,将商机的基本查询、基础CMD操作、以及商机相关联信息操作进行分类抽象。将商机的推进机制建立在规则引擎中,将每个条线的推进规则提前配置在规则引擎的规则表中,并在后端服务中统一提供一个推进入口,所有条线都将基于该入口进行推进,达到推进规则明确,入口统一,阶段可配置等可灵活扩展的方式。

通过整体架构的优化和调整后,目前已经可以适配所有条统一接入、商机阶段可配置,推进规则可定义、接口统一等优点,大大节省了研发的接入成本。

4.2.4 商机阶段配置化

1.场景现状
每个销售条线的商机流程阶段及相应规则都存在差异,甚至同一个销售条线也存在多种业务,对应的商机流程阶段也不同,为支持多销售条线的差异化商机业务;要求必须实现每个条线的商机阶段个数是可配置的,并且每个阶段的规则也是可配置。
2.方案选型
如下图中所示,列举了几个条线的商机阶段生命周期,几乎每个条线的商机生命周期都不一样,这里需要说明一下阶段与阶段之间的推进条件是允许不一样的,所以会存在不同条线存在相同的阶段,但其实到达该阶段的前置条件是有可能不一样的,这就要求阶段的规则是可配置的,这也会造成可复用的可能性小。如果通过编码方式去实现每个条线的阶段生命周期会是一个非常复杂的过程,并且也难以维护。经过调研发现,我们的这种场景模型就是通过多个入参条件决定流程走向(通过、不通过)的一种简单形式,相对于多入多出的模式还简单一些,而这种模式正好现在已经有比较好的解决方案(规则引擎),在现有的流程引擎(Flowable、Activity)都有对规则引擎的实现,包括强大的Drools 规则引擎。对比几款规则引擎几乎都可以很好的满足我们的需求,那就要考虑成本问题,毕竟引入一款中间件对系统的维护成本也是比较大的。经过了解部门内部已经对Flowable 已经进行二次封装对外赋能了,所以在这边我们采用了基于Flowable 流程引擎中的DMN来实现,从模型上来说就是输入多个入参,然后根据规则配置进行判断走向,没有多分支相关联,所以选择Flowable 的规则引擎也比较合适。

解决方案:通过规则引擎,配置商机阶段和阶段推进规则,解决各条线商机阶段差异化问题,将变化流程用配置化方式融入到整体流程中。

3.实现效果
在规则引擎中,提供决策表的表达式,决策表分为输入表达式与输出表达式两个主要区域。在输入表达式中,可以定义变量,用于规则输入项(input entries)的表达式。可以通过选择Add Input(添加输入),定义多个输入表达式。在输出表达式中,可以定义选择表执行结果要创建的变量(变量的值将用于输出项表达式,在下面解释)。可以通过选择Add Output(添加输出),定义多个输出表达式。

规则配置如下图:(以服务+条线举例)
服务+ 权授权业务商机推进规则:jd-rule-crm_fwj_chance_authorized_business


服务+ B线上业务商机推进规则:jd-rule-crm_fwj_chance_b_online_business

优势:

  1. 规则统一收口,每个条线商机阶段推进规则可以直观呈现,规则演化轨迹可以追踪,避免问题排查时,通过代码排查方式核对规则,提升运维效率。
  2. 规则调整可以实时生效,避免代码维护和系统上线,提升研发效率。
  3. 一套代码实现所有条线阶段推进,只需要根据条线添加不同的输入即可。

5 效果

5.1 提升效率

消灭烟囱系统,一套系统完成所有条线支撑,实现各条线、各端接口统一。
开发成本低,易扩展,提升研发效率,降低运维成本;
按照领域对商机进行拆分解耦,实现商机领域独立部署,在商机领域内,通过前端组件化、后端服务标准化、商机阶段配置化技术手段,支持各条线快速复用和灵活扩展。接入对比结果来看,研发效率提升显著,同时也降低运维成本。随着标准流程不断抽象,底层基础服务不断完善,后续条线接入的效率在进一步提升,从后续接入的云仓生态、物流科技、价值供应链,供应链金融,新业务-新业务、金融、供应商7个条线来看,平均接入工时维持在30人日左右。
条线接入工时如下:

标准流程和通用基础服务,提升研测过程效率,其中:服务+条线接入测试工时从最初评估的30人日到实际的23人日,测试阶段效率提升23.3%:

大宗条线接入测试评估工时及实际工时,基于服务+接入商机项目的测试经验,大宗商机接入项目测试阶段从原计划30人日降低到10人日,效率提升66.7%:

5.2 提升质量

服务+较原计划提前4工作日交付,大宗较原计划提前11工作日交付,交付演示过程中均未出现任何问题,验收全程未出现影响整体进度的阻塞性问题。
大宗UAT过程中共提出6个问题,其中5个为页面调优等优化项,1个为环境引起的无法勾选问题,未出现任何bug类问题,整体验收过程顺畅无阻。

作者:京东物流 姚再毅 孔祥东 樊平安 杨攀 田雷雷
来源:京东云开发者社区 自猿其说Tech

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

IDEA使用lombok实体类加上@Data注解后无法找到get和set方法

文章目录 一、问题原因二、解决方法1.File→Settings2.Plugins→搜索"lombok"→Install3.Restart IDE(重启IDEA) 一、问题原因 IDEA没有安装lombok插件 二、解决方法 1.File→Settings 2.Plugins→搜索"lombok"→Install 3.Restart…

RocketMQ 5.0 无状态实时性消费详解

作者:绍舒 背景 RocketMQ 5.0 版本引入了 Proxy 模块、无状态 pop 消费机制和 gRPC 协议等创新功能,同时还推出了一种全新的客户端类型:SimpleConsumer。 SimpleConsumer 客户端采用了无状态的 pop 机制,彻底解决了在客户端发布…

MB5B在HDB上的性能调优

背景 MB5B是用于查询物料的收发以及现有库存。日常业务查询,通常会按照月份查看某片地区物料的库存以及收发状态。 调优思路 按照客户日常操作的习惯,得到日常操作的数据范围,选出数据量最为突出最有代表性的地区和物料;利用SE30分别运行不同数量级的数据,比如20个门店、…

基于LoRA进行Stable Diffusion的微调

文章目录 基于LoRA进行Stable Diffusion的微调数据集模型下载环境配置微调过程 基于LoRA进行Stable Diffusion的微调 数据集 本次微调使用的数据集为: LambdaLabs的Pokemon数据集 使用git clone命令下载数据集 git clone https://huggingface.co/datasets/lambd…

17. 电话号码的字母组合

题目描述 给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。 示例 1: 输入:digits "23" …

数据结构的复杂度

> 作者简介:დ旧言~,目前大一,现在学习Java,c,c,Python等 > 座右铭:松树千年终是朽,槿花一日自为荣。 > 望小伙伴们点赞👍收藏✨加关注哟💕&#x1…

结构型设计模式之桥接模式【设计模式系列】

系列文章目录 C技能系列 Linux通信架构系列 C高性能优化编程系列 深入理解软件架构设计系列 高级C并发线程编程 设计模式系列 期待你的关注哦!!! 现在的一切都是为将来的梦想编织翅膀,让梦想在现实中展翅高飞。 Now everythi…

【玩转Linux】标准io缓冲区的操作

(꒪ꇴ꒪ ),hello我是祐言博客主页:C语言基础,Linux基础,软件配置领域博主🌍快上🚘,一起学习!送给读者的一句鸡汤🤔:集中起来的意志可以击穿顽石!作者水平很有限,如果发现错误&#x…

【前缀和】LeetCode 560. 和为k的字数组

文章目录 题目描述方法1 暴力方法2 暴力优化方法3 前缀和方法4 前缀和优化 题目描述 力扣560题,链接:https://leetcode.cn/problems/subarray-sum-equals-k 方法1 暴力 暴力法,三重for循环,时间复杂度 O ( N 3 ) O(N^3) O(N3)&a…

WebClient,HTTP Interface远程调用阿里云API

HTTP Interface Spring 允许我们通过定义接口的方式&#xff0c;给任意位置发送 http 请求&#xff0c;实现远程调用&#xff0c;可以用来简化 HTTP 远程访问。需要webflux场景才可 <dependency><groupId>org.springframework.boot</groupId><artifactId&…

二十三种设计模式第十七篇--迭代子模式

迭代子模式是一种行为型设计模式&#xff0c;它允许你按照特定方式访问一个集合对象的元素&#xff0c;而又不暴露该对象的内部结构。迭代子模式提供了一种统一的方式来遍历容器中的元素&#xff0c;而不需要关心容器的底层实现。 该模式包含以下几个关键角色&#xff1a; 迭…

K8S初级入门系列之五-Pod的高级特性

一、前言 前一篇我们了解了Pod的基本概念和操作&#xff0c;本篇我们继续研究Pod的一些高级特性&#xff0c;包括Pod的生命周期&#xff0c;pod探针&#xff0c;pod的调度等。 二、生命周期 1、Pod的生命周期 Pod的生命周期示意图如下&#xff1a; 挂起(Pending)&#xff0c…

【node-1】node validation exception. bootstrap checks failed

记录ElasticSearch 内存分配不足报错 背景做出的改变说在最后&#xff1a;最后访问es&#xff1a; 背景 从报错信息中看到&#xff0c;文件&#xff0c;虚拟内存的最大值太低&#xff0c;我们需要调整设置虚拟内存大小&#xff0c;以满足ElasticSearch 运行需求。 做出的改变 …

剑指offer40.最小的k个数

简直不要太简单了这道题&#xff0c;先给数组排个序&#xff0c;然后输出前k个数就好了。我用的是快排&#xff0c;这是我的代码&#xff1a; class Solution {public int[] getLeastNumbers(int[] arr, int k) {int n arr.length;quickSort(arr, 0, n-1);int[] res new int…

拆解雪花算法生成规则 | 京东物流技术团队

1 介绍 雪花算法&#xff08;Snowflake&#xff09;是一种生成分布式全局唯一 ID 的算法&#xff0c;生成的 ID 称为 Snowflake IDs 或 snowflakes。这种算法由 Twitter 创建&#xff0c;并用于推文的 ID。目前仓储平台生成 ID 是用的雪花算法修改后的版本。 雪花算法几个特性…

在 vue3 中使用 ScrollReveal

文章目录 什么是 ScrollReveal安装使用介绍 什么是 ScrollReveal ScrollReveal 官网链接&#xff1a;https://scrollrevealjs.org/ ScrollReveal 是一个 JavaScript 库&#xff0c;用于在元素进入/离开视口时轻松实现动画效果。 先看个入门示例&#xff1a; ScrollReveal …

[SSM]Spring IoC注解式开发

目录 十二、Spring IoC注解式开发 12.1回顾注解 12.1.1自定义注解 12.1.2使用注解 12.1.3通过反射机制读取注解 12.2声明Bean的注解 12.3Spring注解的使用 12.4选择性实例化Bean 12.5负责注入的注解 12.5.1Value 12.5.2Autowired与Qualifier 12.5.3Resource 12.6全…

【数据挖掘】使用 LSTM 进行时间和序列预测

一、说明 每天&#xff0c;人类在执行诸如过马路之类的任务时都会做出被动预测&#xff0c;他们估计汽车的速度和与汽车的距离&#xff0c;或者通过猜测球的速度并相应地定位手来接球。这些技能是通过经验和实践获得的。然而&#xff0c;由于涉及众多变量&#xff0c;预测天气或…

【Linux命令200例】chown修改文件或目录的所有者

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;全栈领域新星创作者✌&#xff0c;2023年6月csdn上海赛道top4。 &#x1f3c6;本文已收录于专栏&#xff1a;Linux命令大全。 &#x1f3c6;本专栏我们会通过具体的系统的命令讲解加上鲜活的实操案例对各个命令进行深入…

iOS-持久化

目的 1.快速展示&#xff0c;提升体验 已经加载过的数据&#xff0c;用户下次查看时&#xff0c;不需要再次从网络&#xff08;磁盘&#xff09;加载&#xff0c;直接展示给用户 2.节省用户流量&#xff08;节省服务器资源&#xff09; 对于较大的资源数据进行缓存&#xf…