当前位置: 首页 > news >正文

真知灼见|客户视图与工作台:金融行业呼叫中心领域驱动设计

无论银行规模大小、类型如何,当你真正面对银行系统建设时,不可避免的需要接触银行后台诸多系统,典型的有如:银行主机前置、信用卡前置、积分系统、CIM、支付系统、短信平台、邮件平台、账单系统、反洗钱、历史库等。各系统提供的功能接口从三五个到上百个不等,随便哪个银行都能给你翻出成百上千个后台接口服务,他们各自提供某个局部信息和能力,这些接口文档如果打印出来,通常够得上几本名著的厚度。

纷繁的功能接口和海量的信息数据是不易翻越的大山

令人沮丧的是,每个后台系统所使用的通讯标准和接口标准各不相同。许多银行会建设接口服务总线,将众多的接口在一个统一平台上集中提供,但这仍然无法掩盖这庞大的接口群带来的业务理解上的困难和压力,找到一个精通整个信息和业务体系的人或团队通常非常困难,一般项目推进的有效手段是找一个或者若干个了解项目需求的专家,针对当前项目所需的范围进行专门地解读。

但更令人沮丧的是,为了实施项目,找了多位业务专家培训讲解,好不容易对某个领域有了不错的熟悉和掌握,一旦出现工作变动,这些成果却很难传承。也许您会觉得使用更好的项目管理和配置管理机制可以增强这一知识传承,但是这种工作标准和投入是非常高的,通常在有限成本压力内很难如愿。这种困难甚至会出现在同一个项目内部:因为进度压力,分工实施的2个开发人员,需要分别学习理解领域内的信息,他们可能使用的是完全相同的过程域信息,却同时发明了2项成果,甚至他们交付的结果都不一致。

总之,一个银行的业务体系非常庞大,学习和理解这个体系,或者在项目中运用,其繁琐和复杂程度非常高,而且容易产生知识的失传。

更高效精准地融合银行的业务体系、快速地推动系统建设,能够支持银行IT建设的稳健发展

对于呼叫中心而言,最典型的应用场景是座席工作台中大量的代客交易,以及IVR等自助系统的代客交易。本文针对呼叫中心的这些相关应用,尝试使用领域驱动设计的方法,为大家呈现如何快速高效地构建这些应用,以支持银行IT系统的持续建设。

金融行业呼叫中心领域驱动设计方案

总体构成

方案主要由两部分组成:客户视图工作台实现

其中又以客户视图最为关键,它是设计的核心,领域驱动设计的关键实践,工作台和IVR代客交易是建立在客户视图之上的应用,本文将借由工作台阐述客户视图对于业务开发的增益以及工作台的推荐设计方案。

总体方案图

客户视图

客户视图的设计基于这样一个假设:银行客户的所有信息能够基于单一主键(通常为客户号)为原点,直接或者间接地挖掘(透过交易查询)。

客户信息树

将所有的客户信息在一个二维平面上从原点出发,以有向图的方式将所有客户信息组织成一颗巨大的信息树。

客户信息树之所以定义为有向图,是因为所有的信息最终都会来源于银行后端各系统的查询接口,查询就需要输入项,这些输入项是从原点提供或者基于原点查询得到的信息,不断地衍生查询继而填充整棵信息树。

客户信息树的主要目的是通过一个原点信息的牵引就能够获得该客户的所有相关信息,并且可获得信息的定义是运行时可列举(反射)的,同时业务开发团队完全不用关心这些数据的来源。

客户视图将银行的业务系统建设从根本上分为两层,向下表达了银行有哪些信息,向上为业务系统定义了能获得什么信息。与客户需求形成对标,将信息来源与客户需求进行对接就完成了功能需求梳理。

■ 懒加载

一次性将整个客户信息树加载完成并不现实,也不需要。那么懒加载的设计必不可少,因此,客户视图的每一个节点都包含一个额外的定义:是否已装载,每当应用系统尝试get视图中的某个局部信息时,视图模块将自动识别加载状态,如果已加载则直接提供,如果未加载则触发相应的接口请求,并在完成请求后填充信息并返回。

每次触发了查询后,并不是只填充当前get的字段,而是将该接口所能提供的信息都映射在客户信息树上进行填充。

懒加载的整体机制对上层业务应用是透明的,业务系统并不关心加载机制。同时客户信息树会进行缓存,尽可能地根据信息时效性降低重复查询的几率。

为了应对某些时效敏感型的需求,也允许在获取信息时强行指定reload,以迫使信息树重新装载所需信息,确保信息的时效性。比如变更类交易的许多前提查询通常要求立即查询,而不建议使用缓存。

■ 数据字典

这里说的数据字典并非枚举类型,枚举类型的问题在下一节有专门解释。这里的数据字典单指业务字段的命名。

单纯的字段命名,并没有多大的讨论意义,数据字典的实际目的是合并业务信息,典型的比如:两个渠道返回的各自的字段,其字段名称,相关描述均不相同,但通过业务分析后,识别得出它们是意义完全相同的字段,那么业务梳理时将它们在信息树上映射为同一个字段。

数据字典的命名功能也从一定程度上规范化业务字段名及其解释,以帮助应用需求分析和开发人员更容易理解和使用。

数据字典的定义在技术上并没有多少投入,仍然是信息树上的内外字段映射,并建议形成具有业务含义的命名解释。但数据字典却恰恰是整个业务梳理中最困难的部分,也是整个业务体系理解程度的最高要求和标志。

■ 枚举的统一

一个令人崩溃的问题是:某些业务功能可能会跨多个银行后台渠道,但这些渠道之间的某些业务枚举的定义并不一致。例如:

▷主机-婚姻状况:已婚=Y,未婚=N,离异无子=L0,离异有1子=L1

▷CIM-婚姻状况:已婚=1,未婚=2,离异=3

▷权益平台-婚姻状况:已婚=NAN,未婚=NV,丧偶=DEAD

相信项目团队看到这个情况,心里是崩溃的,即使是前面说的业务专家,也最多只能够帮助你梳理每个渠道之间枚举项的映射关系,如果这种转换只发生一次还能勉强接受,但可悲的是这种转换映射发生在每两个渠道之间,次数是N*(N-1),一旦涉及到的渠道增多,这就完全变成一个不可能完成的任务。

从客户视图的角度来看,客户信息树是业务需求和信息供给侧的中间切面,参考这一格局,则枚举的相关问题也应该是在视图层决定所有枚举的标准定义,并与所有银行后端的枚举进行映射,上层应用只使用标准枚举定义进行沟通和开发。这个设计产生的枚举转换次数始终小于等于N(如果渠道的枚举定义与标准枚举相同则不需要执行转换),并且所有的转换只发生在与后端接口通讯过程中。

这里给出一种通过xml配置加Java注解的方式实现枚举的自动翻译,仅供参考:

dict-std.xml(标准枚举定义,全局唯一):

<?xml version="1.0" encoding="UTF-8"?><dict title="标准字典" desc="" stdInstead="true">  <enum name="sex" title="性别" desc="" stdInstead="true">    <item std="0" locale="0" title="未知的性别" desc="" />    <item std="1" locale="1" title="男性" desc="" />    <item std="2" locale="2" title="女性" desc="" />    <item std="9" locale="9" title="未说明性别" desc="" />  </enum></dict>

dict-dialect-test.xml(某个方言:test):

<?xml version="1.0" encoding="UTF-8"?><!-- 以下配置在标准字典中无效 (就给懒人复制的时候方便) --><!-- /dict/enum/item/locale 方言值,标准字典不适用该配置,只会使用std配置 --><!-- /dict/@stdInstead 默认:false 继承机制定义,当方言中未配置该枚举类型时,是否使用标准字典的定义(继承配置时,方言值和标准值相同),配置为不替代时未命中的项目会抛出异常 --><!-- /dict/enum/@stdInstead 默认:false 继承机制定义,当方言中未配置该枚举项目时,是否使用标准字典的定义(继承配置时,方言值和标准值相同),配置为不替代时未命中的项目会抛出异常 --><dict title="标准字典" desc="" stdInstead="true">  <!-- 顺序敏感性声明:item配置std,locale单方面或都重复时,顺序靠前的生效 -->  <enum name="sex" title="性别" desc="" stdInstead="false">    <item std="1" locale="M" title="男" desc="" />    <item std="2" locale="F" title="女" desc="" />  </enum></dict>

Customer.java(实体字段使用注解绑定):

 

@Enum("sex")    private String sex;

该方案允许需求分析人员以非开发的方式,直接定义标准枚举字典,以及各渠道的方言定义,方言中的每一选项都必须与标准枚举字典的一项映射,允许多对一映射,但某个方向上的翻译出现多个选项时,优先使用靠前的项目。

开发中,只需要在渠道接口的实体定义相应字段上使用注解进行标注,那么向后发送交易时,交易模块将自动执行注解处理器完成相应方向上的转换动作。

■EL表达式

既然客户信息被绘制为一棵完整的表达树,那么很明显,它非常适用于提供EL表达式进行检索,EL表达式能够为业务逻辑的规则判定等场景提供低代码开发的规则处理,为业务的扩展性提供无限的想象空间。

■交易视图

交易视图,实践中可隶属于客户视图,但通常建议分离实现。主要原因是客户视图是幂等的,而交易视图都是功能型的动作,会对系统产生变更。一般在最下层分离实现,并向上统一聚合为一个视图。

交易视图分离实现还有另一个重要的因素,每个操作类交易完成后,通常可预见地影响了客户信息树中的部分数据,因此交易视图中绑定的操作类交易完成后,需要触发某些信息的过期(按需加载),或者直接由该交易完成信息树缓存的局部修改。

■客户中心

既然客户视图完整地定义了底层信息和能力,很明显多数业务系统都希望能够享受到其带来的便利。因此,这一设计的升华便是将其划分为独立的服务模块,以远程调用的方式向各业务系统提供能力。

作为分布式的一员,客户中心的规划就需要额外考虑集中缓存、哈希负载等设计问题,从单机模式切换到分布式是另一个大话题,此处不再展开,留待日后继续分享!

工作台

■ 上下文

上下文是相对于业务终端操作环境而言的,用于记录:

▷座席当前的操作轨迹,比如客户卡片列表中当前选择的卡片及其相关信息;

▷座席与客户的沟通状态,比如是否正在通话,通话的媒体类型,渠道;

▷客户的核身信息,比如核身等级;

▷其他临时信息。

■ 会话信息

会话信息主要是针对呼叫中心一次沟通的相关信息,包括用户本次会话的标识号,用户进线时使用的线索信息(卡号、证件号、用户ID、手机号等),以及用户的联络历史信息。

■ 代客交易

大量的项目经验表明,工作台功能的绝大部分是代客查询或者代客交易功能,并且绝大多数的代客查询和代客交易功能,都是面向银行后台系统接口的存储转发,也就是接口调用。

同时,通过对大量项目中的海量交付过程进行总结,绝大部分的功能从需求描述上,只有3个部分:

▷输入:查询或操作所需字段;

▷输出:查询结果,分为列表和表单;

▷前置条件:操作该功能的前置条件。

工作台的整体布局,比如菜单的规划和层级的规划通常是项目初期一次性商定并实现的。每个功能的布局和样式也是在项目初期一次性商定并实现的。因此这里的每一个功能需求描述只需要包括这三要素。

这一业务共性给了系统设计空间,通过配置方式、低代码完成绝大部分的功能开发,只需预留好扩展口以完成剩余的少量特殊定制即可。

■ UI自动渲染

业务上确定了三要素,基于技术上的框架就已经明确了该功能的开发方向,那么通过良好设计提供的配置可以由前端自动渲染UI。

写在结尾

以上即为尝试使用领域驱动设计方法,快速构建呼叫中心相关应用的整体设计思路。

整体的设计能够在较大的层面集成银行的业务体系,并向业务系统快速交付,为银行业务快速发展奠定IT实施基础。但如果你只是实施一个中小型项目则需要谨慎尝试,这是一个投资回报周期很长的工作,对于一锤子买卖,压根没有意义做这方面的考虑。但如果你作为银行体系内部IT成员或者与该银行具有长期合作,那么该设计能够为后期的IT建设提供巨大的竞争优势。

 

相关文章:

  • spring-task进行任务调度
  • npm实现格式化时间---就是实现时间按照要求输出--moment包
  • webdriver API进阶
  • 除自身以外数组的乘积、找到所有数组中消失的数字、两数之和
  • 四川农信分布式核心设计及验证项目成果专家评审会召开
  • 快速知识蒸馏的视觉框架-来自卡耐基梅隆大学等单位
  • c++ 11 线程支持 (std::promise)
  • 一篇文章带你看清C语言中的类型转换规则
  • 单海军:行业AI平台赋能金融企业数智化转型
  • Jmeter接口自动化(十)断言
  • C++ 小游戏 视频及资料集(7)
  • 计算机网络笔记(王道考研) 第二章:物理层
  • TCP的连接过程——三次握手和四次挥手
  • tensorflow2从入门到精通——DCGAN算法实现
  • 反欺诈黑产总结
  • 2019年如何成为全栈工程师?
  • Android路由框架AnnoRouter:使用Java接口来定义路由跳转
  • docker-consul
  • ERLANG 网工修炼笔记 ---- UDP
  • ES6--对象的扩展
  • HTTP 简介
  • js 实现textarea输入字数提示
  • Node项目之评分系统(二)- 数据库设计
  • Python 反序列化安全问题(二)
  • tab.js分享及浏览器兼容性问题汇总
  • 程序员最讨厌的9句话,你可有补充?
  • 从零开始在ubuntu上搭建node开发环境
  • 互联网大裁员:Java程序员失工作,焉知不能进ali?
  • 基于HAProxy的高性能缓存服务器nuster
  • ------- 计算机网络基础
  • 聊聊spring cloud的LoadBalancerAutoConfiguration
  • 如何解决微信端直接跳WAP端
  • 如何在 Tornado 中实现 Middleware
  • 问:在指定的JSON数据中(最外层是数组)根据指定条件拿到匹配到的结果
  • 我是如何设计 Upload 上传组件的
  • 系统认识JavaScript正则表达式
  • ​​​​​​​sokit v1.3抓手机应用socket数据包: Socket是传输控制层协议,WebSocket是应用层协议。
  • ​批处理文件中的errorlevel用法
  • ​软考-高级-系统架构设计师教程(清华第2版)【第12章 信息系统架构设计理论与实践(P420~465)-思维导图】​
  • ​总结MySQL 的一些知识点:MySQL 选择数据库​
  • # Swust 12th acm 邀请赛# [ K ] 三角形判定 [题解]
  • %check_box% in rails :coditions={:has_many , :through}
  • (+4)2.2UML建模图
  • (02)Hive SQL编译成MapReduce任务的过程
  • (12)Linux 常见的三种进程状态
  • (Matlab)遗传算法优化的BP神经网络实现回归预测
  • (动手学习深度学习)第13章 计算机视觉---图像增广与微调
  • (多级缓存)缓存同步
  • (二十四)Flask之flask-session组件
  • (附源码)小程序 交通违法举报系统 毕业设计 242045
  • (更新)A股上市公司华证ESG评级得分稳健性校验ESG得分年均值中位数(2009-2023年.12)
  • *Django中的Ajax 纯js的书写样式1
  • .net 4.0发布后不能正常显示图片问题
  • .NET delegate 委托 、 Event 事件
  • .Net Web项目创建比较不错的参考文章