从设计的角度看,如果系统内一个模块设计的变动不会引起另一个模块变动,模块间能够灵活组合,那么我们会说他设计的模块是松耦合的;从开发的角度看,如果修改一个组件的时候不影响其他组件,不会导致一连串的程序需要修改,那么我们就说他的代码是松耦合的;从测试的角度看,符合松耦合的程序会更易于对局部进行黑盒测试。
所以针对项目中的不同角色,多维度梳理银行IT系统中松耦合的内容,并进行深入探讨很有必要。在写作的过程中,参考了很多资料并结合自己的理解,做了一些梳理和重新表达。归纳的也并不完善,欢迎大家补充。
本文分五个部分来谈:
银行IT系统耦合的概念。
银行IT系统耦合度怎么衡量。
银行IT系统松耦合的基本内容。
松耦合的代价。
结束语。
一、银行IT系统耦合的概念
“耦合”一词被广泛运用在通信、软件、机械等许多领域。其实就是用以描述偶数以上多体系的相互作用/彼此影响/互相联合的现象。
在软件工程中,耦合指模块之间相互依赖对方的一个度量。模块间联系越紧密,其耦合性就越强,模块的独立性则越差,维护成本也就越高,为了便于维护,自然是希望耦合越低越好。
从事务间的关系上来看,可以分为组织耦合、运行耦合(流程耦合与数据耦合)、空间(地域)耦合、时间耦合;从耦合的机制上来看,还可以分为内容耦合、公共耦合、外部耦合、控制耦合、印记耦合、数据耦合和非直接耦合。
例如,控制耦合指的是如果一个模块通过传送开关、标志等控制信息,明显地控制选择另一模块的功能,就是控制耦合。
总之,只要事物之间相互影响、相互作用,都可以理解为是一种耦合。
1)耦合方
耦合方是指耦合在一起的各方。
在系统运行中,基于某业务场景的两个耦合方,有一方会向另一方发起一个运行耦合的要求,而另一方会进行相应的响应。我们把运行耦合的发起方称之为:请求方;把响应方称之为服务方。
比如银行核心系统外调密管平台,用于MAC生成、MAC地址验证、验密、设密等操作。那么,我们将银行核心系统称为请求方;把密管平台称为服务方。
又如,手机银行调核心系统查询账户信息,那核心系统就是服务方。
2)耦合点
耦合点是指请求方与服务方之间的连接点,还可以细分为单点接入和多点接入。
例如,支付系统大/小额直联接口系统支持总行单点接入模式,即所有分行的交易通过总行一个单点接入人行支付系统。
还支持总分行多点接入方案,即系统能够支持总分行以不同的 MBFE 接入支付系统或同一城市多家分行接入支付系统的模式。
3)松耦合
拿传统胖核心来说,随着银行业务的高速发展,核心系统所承载的交易范围越来越多,包含了业务模块和管理功能,如信贷管理、风险管理、财务管理等业务中部分流程管理的功能。
这些原因导致了系统升级困难,牵一发而动全身,改造风险较大,难以快速响应业务发展和创新。所以,现在建设系统都讲究松耦合。
在《银行信息系统架构》一书中,关于松耦合是这么说的:“松耦合原则是指要建立松耦合的体系架构,减少某一些系统的变动和故障对全局的影响,提高架构的灵活性和扩展性,实现与敏捷业务相适应的IT架构。”
以台式机为例,它由显示器、主机箱、键盘鼠标等硬件组成,各部分都是松耦合的。如果某一部分坏了,可以很容易就拆下来换新的或者维修,即松耦合的可维护性;如果要换音响,买个新的连接上就好了,即松耦合的可扩展性。
二、银行IT系统耦合度怎么衡量
对于紧耦合的系统,其主要缺点在于程序代码间关联度过高,不利于模块化处理,出现更新一个模块的结果,引发其它模块的结果也发生变化的窘境。
那耦合度该怎么衡量呢?可以通过耦合点&耦合方的多少、大小等方面来思考。
耦合点越少越好,主要是为了避免一个类承担的职责过多,即单一原则。如果一个类有多于一个的动机被改变,那么这个类就具有多于一个的职责,则一个职责的变化可能会削弱或者抑制这个类完成其他职责的能力。
这种耦合会导致脆弱的设计,当发生变化时,设计会遭受到意想不到的破坏。所以,对于一个类应该尽量只专注于做一件事,而且引起它改变的因素只应该有一个。
因此,耦合点越少越好,不仅仅是降低耦合,而且它也使得代码变得整洁明了、便于维护、降低管理成本。当然在取舍实现的时候,更多的是靠经验和对业务逻辑的理解。
耦合点越小越好,主要是为了避免“胖”接口出现,即接口隔离原则,指尽量细化接口,使用多个小而专的接口,而不要使用一个大的总接口。
因为胖接口不仅仅是设计上的一种“浪费”,而且在实施上会带来潜在的问题,所以对其进行修改将导致一连串的程序需要修改,有时候这是一种灾难。
例如,贷款程序要调用活期动账程序,那么贷款程序会通过通信区将接口信息传递给活期动账程序,由于活期动账程序包含了入账和扣账的处理,所以通信区包含的耦合内容较多。
应该将活期动账程序分为入账和扣账两个接口,每个接口只提供跟这个接口最直接的服务,将与之无关的全部隔离出去。
不难看出,对接口进行细化可以提高程序设计灵活性是不争的事实,但一定要适度,如果过小,则会造成接口数量过多,使设计复杂化。
总之,要能减弱接口间的耦合性,那么维护相对较多的接口也比维护一个庞大臃肿的接口要强。
耦合方要求越低越好,主要是不希望类之间建立直接的联系,即迪米特法则,又叫最少知识原则。
因为每个对象尽量减少对其他对象的了解,所以很容易使得系统的功能模块功能独立,相互之间不存在(或很少有)依赖关系,更有利于复用,一个处在弱耦合的类被修改,不会对有关系的类造成波及。
就好比请求方无需关心服务方的具体实现操作,当需要更换操作时,修改配置文件,使得程序稳定,实现了请求方与服务方的松耦合。
这就像现实中的插座一样,可以随时更替,随时插拔。
关于衡量耦合度的思路,就列举到这里。总的来说,耦合的强弱取决于模块间接口的复杂性、调用模块的方式以及通过界面传送数据的多少。
三、银行IT系统松耦合的基本内容
我们经常在分析系统耦合度的过程中不知道该怎么去梳理,或者当我们接触到系统的时候,不知道该从哪些角度去分析系统的松耦合情况。
对于这问题我们需要对系统进行全方面的分析,那就来一起聊聊,对银行IT系统进行分析时能够了解到的内容。
1)组件松耦合
生活中的很多物品都是由若干个零件组成,有手机、电脑等等。以面包机为例,在我们印象中是这样的:
但面包机经过拆解之后,大概有400多种零件,每个零件都是单独存在的,而且是看得见摸得着。如果某个零件坏了,我们只要替换下来换一个好的再安装就可以了。
不难发现,这些零件与我们软件工程中的组件有共通之处,比如可被组装、有重复的部分等等。
那回到主题,实现组件松耦合,该具有什么样的特性呢?我认为有以下几点:
职责清晰、功能独立。
可复用、可更换、可组合。
与外界的接口是标准的接口。
运行的硬、软件无强依赖关系。
2)组件松耦合
接口的定义在系统设计过程中发挥着重要的作用,不管是在日常练习还是工作中,我们每个人都少不了要定义各种接口(interface),有系统集成、有前后台调用。
接口的定义能在一定程度上反应程序员的编程功底或业务能力,可以看出有的人着重实现细节,有的更注重整体性......
这都体现了背后所隐含的设计思想和设计理念的差异,定义的好,能规避掉很多无用的返工修改和可能出现的问题。
俗话说无规矩不成方圆,下面列几点:
允许跨平台或不同的对象间轻松交互。
采用统一的接口规则,如“ISO8583”。
统一接口命名法,如"驼峰命名法"。
避免出现无关或复杂的输入参数。
3)应用与数据松耦合
在计算机发展的初期,程序员们使用机器语言来进行编程运算,可以理解为只有计算机能够识别的一套0,1编码。
后来为了便于阅读,出现的汇编语言代替了机器语言的二进制码。当计算机语言发展到第三代时,就进入了“面向人类”的高级语言。
随着软件开发规模愈来愈大,早期应用与数据之间多对多做法的弊端逐渐凸显,导致软件难以维护,比如修复一个Bug而引发更多Bug,以及软件开发人员之间的信息交流不准确等,因此容易产生疏漏和错误。
那就需要一整套方法来规范这些人和事,所以引入了工程学的概念,即软件工程。
也就是现在的核心系统都已能做到应用与数据松耦合的原因了,比如将数据库的增删改查封装到类中、早期报表与应用程序和数据的解耦等。
以数据库的封装来说,好处在于将变化隔离,便于使用、提高了重用性和安全性。规则如下:
各应用的数据分别封装在相应的应用模块中。
不可跨应用访问表,必须由应用本身去操作。
要访问其他应用数据,由其他应用提供服务。
1)流程松耦合
流程松耦合的前提是能准确对交易干系人的行为进行分析,这就需要我们了解清楚干系人在交易中的需求或是服务。
如果对行为分析的不到位,一定会对业务流程分析产生一定的影响,甚至是库表结构等数据层面的松耦合。因此设计一套简洁,耦合度低的流程是非常重要的。
比如,银行柜员为公司客户提供金融服务,这就进入了公司业务条线,其中会包含存款、贷款、贸易融资、供应链、现金管理等具体业务。但这个粒度太粗,可以按不同的角色在对业务中承担的职责进行逐步拆解。
再如,银行柜员在为客户办理金融交易时,无需关心会计信息,对核心这种交易系统而言也一样,所以可以对前端业务的办理与后台的账务处理进行解耦,就是我们常提到的交易与核算分离,也可以按上述方法进行分析。
又如,采用异步的方式连接本系统与第三方系统,这也算是一种解耦;再如,采用ESB服务总线的方式设置系统内部和系统间的服务调用,减少系统间的耦合性,便于系统的功能扩展等等。
虽然这个抽丝剥茧过程主要依赖于设计者的经验,而且需要不断摸索、总结和反复验证。但只有这样,才能打通业务和技术,落实对流程IT组件的生产和组装,以及对业务按场景、事件等维度的流程配置和动态调整,实现流程松耦合。
2)数据松耦合
数据耦合在百度百科中是这么说的,指的是两个模块之间有调用关系,传递的是简单的数据值,相当于高级语言的值传递。例子如下:
确实是这样的,再换个角度,说数据拆分。数据拆分可以与流程分解同步进行,有利于明确数据边界,实现数据层面的解耦。
如果我们不懂业务,就听不懂别人的问题,就提不出好的建议,就无法更好的拆分数据,也就很难达到预期。
所以,数据拆分是基于对业务&技术知识和实践方面,有深入了解的前提条件下进行的。以编码生成的规则为例,有日志号、错误码、客户号、账号、子序号、冻结编号等等。
这些都属于数据松耦合的范畴内。那良好的编码该具备怎样的规范呢?
编码能直接区分编码类型。
编码的序号是顺序生成的。
编码中不要包含以后会变的信息。
编码能体现少量信息,如客户类型。
关注编码与属性松耦合、系统开销。
当然,各类数据的规范远远不止这些,比如客户合并、机构撤并等场景。因此,除了要对现有数据进行拆分,还要对比各种种解决方案,以及可能存在数据冗余的问题等,都会影响到后续的接口设计。
所以多维度的梳理,能向实现数据松耦合更进一步。
除了以上介绍的两种关键维度外,还有很多其他方面的松耦合影响着银行IT系统。比如IT架构管控方面,有项目审查、方案确认、对硬件的依赖程度、代码版本控制、系统上线步骤的要求等全生命周期的管理。咱就来简单唠唠。
银行IT系统建设是一个自顶向下逐步细化的过程,对于整个信息系统来说也一样,当然这也是很多业界大师都给出过的论证。
因为在系统开发的过程中,经常会出现信息不一致,而这种现象的存在对系统往往是致命的。因此,自顶向下是从整体架构的角度思考,以便达到信息的一致性。
银行核心系统投产就是一个典型的例子,相信经历过这激动人心的时刻,都会深有感触。在短时间、资源紧张的情况下,面对磕磕碰碰,在日夜不懈奋斗之后,将多个项目组成一个个投产版本,其复杂性与工程量可谓不易。
当资源封板后,仍有很多因素需要考虑。
比如对上线时间的考量、是否按子系统分步投产、是否某地域先投产、如何将风险降到最近,怎么做到客户无感知等等,这些都是对系统稳定的考验。以分步投产为例:
准备:客户信息补录、数据清理、系统培训、数据迁移、停售部分产品、网络改造、细化规章制度、机构柜员信息采集、切换演练、并行演练、投产预演、灾备演练等。
预备:如版本冲突问题,一般投产后几天,出现的问题会相对较多,因此要考虑新版本上线的影响、与其他组件的兼容情况、与功能间的松耦合。
其他:如按子系统分布投产,要考虑系统间的依赖情况,能否做到松耦合,以及对外报批报备及宣传解释、系统切换及档案保管等。
这例子只是一部分,还有很多有意思的设计关键点就不过多叙述了。当然,除了编码的艺术、优雅的设计,合适的性能也是非常重要的。俗话说:“没有对比就看不出差距”。
下图对比了紧耦合与松耦合的性能特点:
四、松耦合的代价
文章读到这里,相信大家紧耦合与松耦合有了一定的了解,那到底是用紧耦合好还是松耦合好?
之前也有过一些交流,其实这是一个比较难回答的问题,没有不顾场景和资源下绝对的好与坏,也不是一定要追求松耦合,关键要权衡利弊。
首先,松耦合意味着更多的代码开发和维护工作量,那么系统会付出更加复杂的代价;其次,不同公司、部门或团队也有不同的进度安排、利益和预算,是需要集中力量一起协作完成的;最后是松耦合的架构增加了系统开销,从而降低了系统处理效率。
例如,异步处理的方式比同步处理的方式复杂;再如,组件服务化不彻底导致不清、服务间关系复杂;又如,由于调用链太长,且故障存在扩散现象,快速定位问题问题。
五、结束语
基于各家行的信息系统情况与数据量,紧耦合与松耦合的相对优势是存在的,或者说,各有优势,看银行根据自身情况取舍价值判断。但当信息系统或数据量发展到一定阶段,松耦合是必经之路。无论是以前的SOA还是现在的微服务,主要都是为了化繁为简。
所以在系统设计时需要把松耦合的环节通盘考虑清楚并平衡多方因素,当然还有技术架构、部署架构等场景。
每个环节都按照既定的目标去执行,形成统一的语言,才能最终实现真正意义上的松耦合,使系统架构随着系统的发展而进行适应性的优化,始终保持适度的耦合度,起到落实IT和业务战略目标。
至此,松耦合的内容就到这里。如果能为你带来些许帮助,那是一件非常欣慰的事情。感谢网络上编写了松耦合相关文章的作者。限于个人整体认知,有些方面只是概要讲述,并未详细展开。欢迎在评论区分享你的观点,我们一起探讨。
参考资料
梁礼方.《松耦合》,2013年
程杰.《大话设计模式》,2007年
刘光瑞.《松耦合系统架构浅析》,2018年
网络.《松耦合和紧耦合的架构设计及性能对比》
如果字段的最大可能长度超过255字节,那么长度值可能…
只能说作者太用心了,优秀
感谢详解
一般干个7-8年(即30岁左右),能做到年入40w-50w;有…
230721