老代码多=过度耦合=if else?阿里巴巴工程师这样捋直老代码

简介

在业务开发的过程中,往往存在平台代码和业务代码耦合严重难以分离、业务和业务之间代码交织缺少拆解的现象。平台和业务代码交织导致不易修改,不同业务的代码交织增加了不同负责团队之间的协同成本。因此不论从代码质量,还是从团队协作的角度来看都严重地影响了开发团队之间的协同效率和开发效率,最终影响到了用户体验和业务发展。在闲鱼,商品发布和编辑功能也是如此。本文将以闲鱼商品发布和编辑功能的改造为例,向大家展示闲鱼是如何解决此类问题,从而更有效地协同更多团队更快更稳定地支撑各种业务的。

发布编辑功能的升级改造

为了实现上述目标,针对发布和编辑功能,进行了两轮升级。第一轮的目标在于“平台和业务分离、业务和业务隔离”;而第二轮将更进一步,目标在于“系统之间的解耦合,提升团队协同效率”。

1.平台和业务分离,业务和业务隔离

第一轮改造中,闲鱼将原先的商品发布和编辑功能从老应用中抽取到了新应用item。为了实现“平台和业务分离、业务和业务隔离”的目标,闲鱼自研了一套技术框架SWAK,具体请参考文章《业务代码解构利器--SWAK》,该文介绍了其设计思想和实现原理。接入SWAK框架后,平台逻辑和业务逻辑得到了分离,各个业务(如租房业务、免费送业务)之间的逻辑也不再耦合,而是变成package隔离(当然也是可以做成jar包隔离)。

看一看改造后的应用情况示意图:

  • 我们根据发布和编辑的主干流程,抽象了17个SWAK扩展点。
  • 发布和编辑的主干流程主要就是对这些扩展点的编排。主干流程的编写并不需要考虑业务上怎么实现这些扩展点的。
  • 我们根据不同的业务(在SWAK里面更准确的表述是tag)对这些扩展点进行了各自的实现。

根据这样的开发方式,我们可以把开发同学分成如下的两种角色:

  • 各业务开发人员。各业务开发人员主要是负责各个业务相关的代码。在item应用里面,业务同学需要维护其业务中和发布编辑相关的个性化业务逻辑。
  • 主干开发人员。主干的人员只需要维护主干的代码,尤其是扩展点的抽象。随着不同业务的不断接入,原先的扩展点也需要随之调整。

如在之前的《业务代码解构利器--SWAK》一文中指出的一样,经过SWAK改造后,获得了如下的几个优点:

  • 代码逻辑清晰,可变和不可变一目了然。
  • 代码复用度变高。
  • 可变逻辑按照标签进行隔离,单个标签的实现不会影响到其他标签的实现,降低开发和测试成本。无论是按照“类型”分还是按照类目分,对应的开发和测试同学只需要关注对应的逻辑即可。
  • 新接手的开发人员能够快速理解,轻松上手。

2.系统之间的解耦合,提升团队协同效率

以租房为例——租房业务的同学需要在item应用中维护一套租房发布编辑相关的逻辑(如校验地小区数据、地铁数据真实性等);租房业务的同学还需要在详情应用的逻辑中维护一套和租房详情相关的逻辑(如展示地图,展示内部设施标签);租房业务的同学还需要在交易应用的逻辑中维护一套和租房交易相关的逻辑(如预约看房)等等。租房的同学不仅仅需要着手于自己的代码逻辑,还需要修改发布和编辑应用item、还需要修改详情应用,还需要修改交易应用......这种体验是非常糟糕的,有极大的可能性接手一个简单业务就需要修改和发布四五个应用。

另一方面,从主干开发人员的角度来说,其应用不仅仅由自己或自己的小团队来维护,还有很多业务开发人员也在修改和发布此应用,且频率会远远超过主干开发任务的发布和部署频次(否则就是主干扩展点逻辑抽取得不好了)。这不利于整个应用的稳定性。A业务服务挂了,应该只影响A业务,而不应该影响主干。依此逻辑,最好能做到JVM隔离。本质上来说,第一轮改造完成了业务之间的解耦合,而第二轮则是系统之间的解耦合

康威定律告诉我们:

Any organization that designs a system (defined more broadly here than just information systems) will inevitably produce a design whose structure is a copy of the organization's communication structure.

简而言之就是人员组织结构和系统结构之间的一致性。而完成系统之间的解耦合又恰恰是符合康威定律的。这一轮的改造,我们称之为“业务服务化”。

业务服务化改造方案

  • 首先,我们把租房业务给单独抽取出来。原先的帖子和拍卖业务暂时没有独立的团队来予以维护(但也基本上没有什么新需求)因此暂时仍然放在主干应用中,时机合适将会和租房应用一样迁移出去。
  • 其次,租房业务通过远程服务的方式给主干应用提供服务。接口即是主干业务的提供的扩展点。由于现在是优先使用远程服务来连接主干应用和垂直应用,考虑到性能问题和安全问题,我们在扩展点的定义上也做了一些特殊的改动,后文会有针对性的详述。
  • 最后,SWAK框架做了一些改变以注册和调用远程服务。相对于本地服务,远程服务一般都是有超时、连接异常等问题。然而不同接口对于这些异常情况其处理策略也是截然不同的,后文“SWAK框架的针对性改进”会详述这些改动。

通过这种方式,我们将主干应用和各业务应用彻底分离了。仍然以租房业务为例,租房团队负责开发和维护租房业务的独立应用rent。租房个性化的发布和编辑需求只需要开发和部署rent应用,而不必修改主干应用。主干应用只由主干团队的同学负责维护,不会被其他业务团队的同学所开发和部署,稳定性更加能得以保障。各业务系统独立开发、独立部署。这些都大幅地减少了不必要的沟通成本、提升协同效率。

主干应用和业务应用是通过薄薄的一层接口所联系起来的,这层薄薄的接口都是“声明”:Interface定义、DO的定义和扩展点的默认Reduce策略定义。

SWAK框架的针对性改进

在之前的《业务代码解构利器--SWAK》一文中指出了,SWAK框架在应用启动的时候会通过各种注册器(registery)注册框架所需的信息。其中最重要的信息就是——业务tag及其对应的SWAK接口的实现类类名或者类实例instance。大多RPC框架都会在client端提供一个代理,代理掉内部的服务发现、保活、序列化、网络通信、反序列化等一系列操作。实际上,SWAK为了支持远程服务调用,只需要将业务tag,以及这些RPC的client的instance的对应关系注册进去就可以了。在闲鱼,RPC使用的是阿里通用的HSF框架(其类似的一个开源框架是Dubbo),这里的RPC的client就是HSF中的ConsumerBean。

上文还提到了RPC调用会引入服务超时、连接异常的概念。为何要限制超时?是因为不能被单个应用的超时占据了主干应用的服务资源而引起其他服务和整个应用系统受到影响(如大多数线程阻塞在超时调用上)。无论是超时异常还是连接异常,在业务上也有对应的处理策略。在这里,我们定义了三种异常处理策略,通过在配置上设置相应的注解,SWAK框架会自动按照策略来处理异常。这三种策略是:

  • IGNORE。 即,直接向上层抛出异常。
  • SKIP。对于一个接口有多个tag执行的时候,本tag下该扩展点将跳过,继续执行其他tag下该扩展点的实现。
  • DEFAULT_VALUE。返回默认值。默认值通过spel表达式进行设置。

减少扩展点数量

众所周知,RPC调用相对于本地调用会增加一部分的网络传输和序列化开销。对于单次调用来说,增加若干ms并没有什么问题,但对于调用10次、20次或更多,这笔开销就相当可观而应该引起重视了。为此,如何降低RPC开销,是一个必须要考虑的问题。

最可靠的方法就是降低RPC的次数。

在实践中我们发现,很多扩展点实际上都是获取业务配置。如在闲鱼业务中,“是否支持多库存”就是一种配置,如租房不支持多库存。这些业务配置项是由其业务形态所决定的,基本不会变动。因此可以将一组配置项打包一起调用,并且可以缓存下来,也可以直接由主干应用进行维护。在item应用里,这些配置项关系到主干的通用存储过程,目前由各业务方委托主干开发人员进行维护,目前配置在主干环境。可以通过阿里的动态配置平台(如Switch、Diamond)进行动态修改。

另外我们对部分邻接的扩展点进行了合并。这些相邻扩展点之间的逻辑比较简单,且不会中断主流程。通过“配置型接口”和“邻接扩展点合并”这两种操作,我们将扩展点数量降低由17个降低到了6个。要注意的是,扩展点并不是越少越好。扩展点越少,越意味着“过度拟合”,可能会对后续业务变更无法适应导致主干需要大幅改动,因此需要在数量和扩展性之间找到一个平衡。

另外值得一提的是,SWAK为配置型扩展点做了相应的小改造,并提供了查看当前配置型扩展点返回值的可视化界面。开发人员可以直观地了解当前各个业务的配置值。

接口对象定义和细节设计

在闲鱼,各种业务所需要存储的东西大同小异,从闲鱼的发布界面上来看就不难发现这一点,都是在基础对象(如标题、描述、图片)之外添加一些业务相关的数据,如拍卖业务中指定拍卖的开拍时间等信息,免费送业务中设置兑换币值,图书业务上设置条形码。即对一本图书进行拍卖当然也是允许的,这就出现了拍卖业务和图书业务叠加起来的复合型业务。

对于主干应用开发人员来说,应该提供单个接口以支持所有业务类型,这样不用每次修改或者新增业务时都需要提供新接口。从稳定性的角度考虑,这样的要求很合理。既然是单个接口,那么DO的定义也应该统一。以商品DO为例,有以下三种方式:

  1. 第一种是继承型结构,该结构不适用于业务叠加的情况。另外主干需要知晓各个业务的DO,每次业务修改或新增,主干都需要做变动。
  2. 第二种是组合型结构,适用于业务叠加的情况,但同上一种一样,主干需要知晓各个业务的DO,每次业务修改或新增,主干也需要随之变动。
  3. 第三种使用了Map类型类承载各个业务(biz)的定义类型。主干完全不知道、也不需要知道各个业务DO是如何组成的。这种方式具有最好的扩展性(有点无边界的扩展),也分离了主干应用和业务应用,最接近主干和业务分离的期望。最终我们选择了这一种。

使用第三种的对象模型,以新加一种业务为例,其开发流程是:

  1. 新业务服务端开发人员和客户端开发人员约定各业务的DO,这些DO会存储到bizMap字段。主干应用开发人员不需要了解这些约定。
  2. 主干应用新增一份新业务的配置,实际上是新业务的识别信息和路由信息。
  3. 新业务应用实现主干扩展点。
  4. 联调、测试和上线。

业务应用在扩展点返回值中设置需要更新的数据,由主干应用合并。业务应用不应该也不可以直接修改ItemDO,避免影响其他业务的处理逻辑。对于发布和编辑这种需要持久化存储的逻辑来说,必须要强控各业务对ItemDO的修改,否则理论上来说,各业务都有可能将所有的关键字段修改得面目全非。前面提到的“配置型接口”中,就有这样的配置——该业务是否可以修改属性字段、该业务是否可以修改描述字段等配置。

总结

闲鱼的商品发布和编辑功能基于SWAK框架经过了两次改造升级,第一次升级完成了平台和业务之间的解耦合以及业务和业务之间的解耦合,第二次升级通过平台和业务间使用RPC调用完成了系统和系统之间的解耦合。改造之后,能更有效地协同更多团队更快更稳定地支撑各种业务。SWAK框架依然在继续演进,如部分扩展点原则上可以通过并行处理或异步化处理来提升性能,但暂时还没有提供支持。在这两次改造中, 我们还在测试用例的采集、回放、监控告警等方面也有很多积累,敬请期待后续的文章分享。

 


原文链接
本文为云栖社区原创内容,未经允许不得转载。

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

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

相关文章

阿里高级技术专家:研发效能的追求永无止境

背景 大约在5年前,也就是2013年我刚加入阿里的时候,那个时候 DevOps 的风刚吹起来没多久,有家公司宣称能够一天发布几十上百次,这意味着相比传统软件公司几周一次的发布来说,他们响应商业需求的能力可以甩后者几条街&…

就因为一个笔记本,运营和产品吵得不可开交......

上班最讨厌的一件事情,莫过于开会,因为每次开会感觉就要吵架,这个今天开会又吵架了,吵架竟然是因为产品小姐姐的笔记本。产品小姐姐用了一本可擦笔记本记录会议内容,运营小姐姐竟然说这个本子有什么用,不就…

Spring Boot 配置SSL 实现HTTPS

文章目录1. 简介2. 证书生成3. 证书引入4. 创建测试index5. 配置6. 创建配置类7. 创建控制器测试8. 浏览器验证1. 简介 传输层安全性协议(英语:Transport Layer Security,缩写作 TLS),及其前身安全套接层 &#xff08…

一幅GAN网络创造的肖像图卖了40万美金,但那又怎样?

在2018年一场著名的拍卖会上,一部AI制作的肖像以432,500美元的价格成交!这篇新闻在科技媒体上被广泛讨论,有些人认为这一事件对人类艺术家构成了威胁。其实,这只是深度学习快速发展中众多不可思议的案例中的一个,这些故…

PyTorch可视化理解卷积神经网络

如今,机器已经能够在理解、识别图像中的特征和对象等领域实现99%级别的准确率。生活中,我们每天都会运用到这一点,比如,智能手机拍照的时候能够识别脸部、在类似于谷歌搜图中搜索特定照片、从条形码扫描文本或扫描书籍…

区块链工程师平均薪资 25~50k?6 个理由告诉你为什么要懂区块链!

作者 | Carol出品 | 区块链大本营(blockchain_camp)* 文末可参与抽奖活动!如果说有一个什么领域,能让中科院、华为、腾讯、京东、360、微众银行的大咖汇聚在一起,那一定是——区块链。悄咪咪地给大家剧透一下&#xff…

SpringBoot Controller接收参数的几种常用方式

第一类:请求路径参数 1、PathVariable 获取路径参数。即url/{id}这种形式。 2、RequestParam 获取查询参数。即url?name这种形式 例子 GET http://localhost:8080/demo/123?namesuki_rong 对应的java代码 GetMapping("/demo/{id}") public void demo…

NLP度量指标BELU真的完美么?

刚接触自然语言处理的朋友通常会问我:当系统的输出是文本,而非对输入文本进行某种分类,如何对该系统进行评估。当模型的输入是文本信息,输出也是文本信息时,我们称之为序列到序列问题,也可称为字符串转换问…

开放华为30年研发能力与实践 助力DevOps真正落地

戳蓝字“CSDN云计算”关注我们哦!作者 | 刘丹受访者 | 汪维敏出品 | CSDN云计算(ID:CSDNcloud)高速的中子撞击U235原子核,使其分裂成两个原子核,释放出巨大能量,同时产生的几个中子再去撞击其它…

Euler 今日问世!国内首个工业级的图深度学习开源框架,阿里妈妈造

千呼万唤始出来!阿里妈妈正式公布重磅开源项目——图深度学习框架Euler。这是国内首个在核心业务大规模应用后开源的图深度学习框架。此次开源,Euler内置了大量的算法供用户直接使用,相关代码已经可在GitHub上进行下载。 图学习和深度学习都…

天啦噜!在家和爱豆玩quot;剪刀石头布quot;,阿里工程师如何办到?

如今,90、00后一代成为消费主力,补贴、打折、优惠等“价格战”已很难建立起忠诚度,如何与年轻人建立更深层次的情感共鸣?互动就是一种很好的方式,它能让用户更深度的参与品牌/平台呈现的内容,提供更深层的参…

查看计算机或网络资源列表的命令,dos命令net view图文教程,显示网络计算机列表查看共享资源...

大家好,我是老盖,首先感谢观看本文,本篇文章做的有视频,视频讲述的比较详细,也可以看我发布的视频。今天我们学习net命令中的view,它这个命令可以查看网络计算机列表和共享的资源。直接输入net view可以看到…

使用Opencv构建一个简单的图像相似检测器(MSE、SSIM)

介绍 作为人类,我们通常非常善于发现图像中的差异。例如,常见的游戏——两张图像找不同。现在让我们玩下这个游戏吧,首先让我们看看上面的图像,三十秒内看看是否能够从中找出有什么不同的地方。 答案:水果、冰淇淋和…

云+X案例展 | 民生类:云途腾助力城建开启智慧城轨新征程

本案例是由云途腾投递并参与评选,CSDN云计算独家全网首发;更多关于【云X 案例征集】的相关信息,点击了解详情丨挖掘展现更多优秀案例,为不同行业领域带来启迪,推动整个“云行业”的健康发展。2019年7月,城建…

关于开源分布式事务中间件Fescar,我们总结了开发者关心的13个问题

开源分布式事务中间件 Fescar 自1月10日上线v0.1版本以来,受到了开发者们的极大关注(watch249,star3005,fork649,社区讨论的issue58,数据统计于1月17日14:00),可见,天下苦…

计算机桌面图标变成腾讯图标,桌面图标变成了未知图标

在电脑日常使用生活中,有时候会遇到桌面图标显示不正常,变成未知图标或者白色。遇到这种情况怎么办呢?今天就让我来和大家分享一下我的经验。首先,产生这种问题的原因,有如下几种:• 电脑桌面图标缓存导致的…

云+X案例展 | 民生类:基于AWS PaaS构建基础集团企业级中台

本案例由浪潮投递并参与评选,CSDN云计算独家全网首发;更多关于【云X 案例征集】的相关信息,点击了解详情丨挖掘展现更多优秀案例,为不同行业领域带来启迪,进而推动整个“云行业”的健康发展。上海市基础工程集团有限公…

互联网下半场的角逐,玩转轻资产的大数据服务 | 阿里云栖开发者沙龙大数据专场(北京站)干货集锦

2019年1月18日下午,一个晴冷的冬日,由阿里巴巴MaxCompute开发者社区和阿里云栖社区联合主办的“阿里云栖开发者沙龙大数据技术专场”走近北京联合大学。当日,近200名大数据开发者和爱好者现场参与了本次活动,同时也有1800多名开发…

日志服务与SIEM(如Splunk)集成方案实战

背景信息 目标 本文主要介绍如何让阿里云日志服务与您的SIEM方案(如Splunk)对接, 以便确保阿里云上的所有法规、审计、与其他相关日志能够导入到您的安全运维中心(SOC)中。 名词解释 LOG(SLS) - 阿里云日志服务,简…

行,Python终于跌神坛了!程序员:活该!你敢来评论吗...

Python还有“敌人”吗?最近网络上一则帖子吸引了笔者,大意内容为:据说A是有2年多经验的Python工程师,面一个公司相关的岗位,由于人手紧缺,所以只问了一个框架,就按笔者提的29K办理了入职。对此&…