业务代码解构利器--SWAK

简介

业务的不断发展、商品类型的不断增多、不断添加的业务需求使得闲鱼的代码出现“bad smell”——平台代码和业务代码耦合严重难以分离;业务和业务之间代码交织缺少拆解。这也是行业中的通病。为解决此类问题,闲鱼自研了一套技术框架——SWAK。本文带大家一起看看SWAK是怎么解构闲鱼代码的。

SWAK是Swiss Army Knife的简称,众所周知,瑞士军刀是一款小巧灵活、适用于多种场景的工具。在闲鱼服务端,SWAK框架也是这样一种小巧灵活、适用于多种场景的技术框架, 它所要使用的场景都具有同一个特点——多实现间的规则化执行。本文将以一个例子开篇,来详细介绍其中的概念。

多实现和规则化执行

熟悉闲鱼的朋友们应该知道,在闲鱼App里面,商品有丰富的表现形式,不妨叫做类型A、类型B和类型C,各种类型也可以有各自的子类型。每种类型的业务逻辑存在一定的共性,但是也存在部分差异——如在分享页面中,subtitle字段的展示逻辑就不尽相同:

这种单一的实现通常会被写成如下的代码:

if(A类型) {if(A1类型) {doSomething1();}else if(A2类型) {doSomething2();}
} else if(B类型) {doSomething3();
} else if(C类型) {if(C1类型) {doSomething4();}else if(C2类型) {doSomething5();}
}

类似的代码大家应该都写过不少。逻辑简单的时候写成这样无可厚非,但当逻辑开始变复杂的时候这种写法会具有较多的坏处:

  • 难以抽出公共的逻辑,代码块愈发臃肿。
  • 有较多相同点少量异同点的新类型的实现很难复用原先的代码。
  • 各个类型的代码实际上融合在一块,更改代码可能会影响到其他类型,提高上线风险和测试回归成本。
  • 对于新接手的开发人员来说,理解成本高,上手难度大,无形中降低开发效率。

按照面向对象的思想,获取title的方式对于所有类型都是一致的,应该沉淀成平台逻辑,而获取subtitle就可以抽象成一个接口方法,而类型A、类型B和类型C的宝贝都具有各自的实现而已。对于 获取subtitle这个接口方法来说,它有着多种实现。

那么什么是规则化执行呢?在上面的例子中,我们按照了商品的类型(type)进行了逻辑的分离,但通常情况下并非能分隔地如此彻底。举一个例子,运营团队的划分可能也按照商品类型(type)做划分,也有可能按照类目(category,如手机、3C数码、服饰、图书等)体系来做划分,甚至还有可能按照地域进行划分。那么一个商品可能既会受到商品类型体系的约束,又会受到类目体系的约束,还会受到地域的约束。如果几种约束不一致的话,就会产生冲突。比如subtitle字段,从类型A的视角上来看应该显示价格,在图书类目的视角下或许应该透出出版社——毕竟爱读书的人大多更关注质量而出版社是衡量质量的一个重要标准。是展示价格,还是出版社?或者都展示?如果都展示的话先展示价格还是先展示出版社?如果一行不够放下所有内容又怎么办?无论是上述的哪一种展示方式,背后都是“规则”(在设计模式里,称之为“策略”),代码也无非是按照“规则”进行编写而已。

以上的例子是多实现规则化执行的一个经典场景。类似地,如ABTest、双写等逻辑也是多实现规则化执行的应用场景。

基本思想

在上面的例子中,按照商品的类型或者按照商品的类目进行区分会产生冲突。其实无所谓类型或者类目,对于商品这个对象来说,无非是给其贴上了不同的标签而已——如一个类型A的图书类目宝贝被贴上“类型A”和“图书”两个标签。“类型A”的获取subtitle接口方法对应着一种实现,而“图书”的获取subtitle接口方法又对应着另一个实现。当一个对象被贴多个标签的时候,多个标签对应的实现就会产生冲突。

冲突的解决依赖于“规则”。“规则”最重要的两个部分是——优先级(Priority)和归约(Reduce)策略;执行的先后顺序由优先级决定,而显示第一个实现的结果、显示第二个实现的结果还是两个实现结果的拼接等都是归约策略。“规则”还可以包含如“并行执行方式”和“异常处理方式”等其他组成部分。

如上,可以得出SWAK的基本思想:

  • 分析对象所具有的标签。
  • 分离出不可变的逻辑和可变的逻辑。可变的逻辑抽象成接口。
  • 可变的逻辑根据标签的不同有多种实现。每种实现是独立的,即每种实现是互相隔离的。
  • 当对象同时具有多个标签时,使用优先级和归约策略来解决冲突问题。

值得一提的是,SWAK的基本思想借鉴自阿里巴巴中台的TMF架构,关于TMF的细节可以参考《尽在双11--阿里巴巴技术演进与超越》一书的《基于TMF框架的交易平台架构》章节。

相应地,使用SWAK框架将带来如下的好处:

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

实现原理

相较于运行期才进行根据标签去扫描并加载实现类的方式,SWAK框架更倾向于在静态期就能分析出具有某几个标签的对象在不同的实现方法下会有着怎样的执行逻辑。一方面通过缓存可以明显降低响应时间,另一方面也便于在开发期间发现和排查问题。整体的实现原理可以分成两个部分:注册和 执行。基本流程如下:

在注册过程中,SWAK框架将会扫描文件(多实现接口、归约策略、冲突优先级采用了Java注解或者XML文件进行了配置,下面的代码示例中介绍多实现接口和其实现类是如何配置的),扫描出的结果都注册到了本地缓存中,而在执行过程中SWAK框架会从本地缓存中直接查找其所需的冲突优先级配置和归约策略等,这样有助于减少响应时间。另外,使用统一的本地缓存有助于进行“可视化的展现”——开发人员可以直观地看到并分析出程序的执行流程;产品经理也可以直观地看到哪些功能点可以方便扩展,哪些地方的优先级需要更新等等,甚至有助于需求的估时和排期。使用统一的本地缓存也为“可视化的配置”提供了可能性,结合阿里内部的Diamond或者Switch框架(轻量级的开关和动态配置项管理框架),可以无需更新代码,仅需推送配置就可以更新冲突优先级,为开发和测试提供了极大的便利。

/*** 此处用一个简单的demo演示下基本的配置,实际的业务要远比demo复杂*/
@SwakInterface(desc="获取subtitle") // 使用注解声明这是一个多实现接口
public interface SubtitleFetcher {@SwakMethodString fetchSubtitle();
}@SwakTag(tags = {"tagA"}) // 使用SwakTag绑定tagA的实现
@Component
public class TagASubtitleFetcher implements SubtitleFetcher {@Overridepublic String fetchSubtitle() {return "我是TagA";}
}@Component
@SwakTag(tags = {"tagB"}) // 使用SwakTag绑定tagB的实现
public class TagBSubtitleFetcher implements SubtitleFetcher {@Overridepublic String fetchSubtitle() {return "我是TagB";}
}

闲鱼服务端应用基本都基于Spring框架。为了便于在服务端应用上使用SWAK框架,在设计之初,我们就要求SWAK需要100%地兼容Spring框架。最终的实现版本做到了这一点,无论是业务的bean还是SWAK框架自身引入的bean,都完全由Spring容器托管。框架还使用了cglib代理了上图里执行过程中的一系列流程,完全由框架执行,对开发同学是完全透明、无感知的,使用起来如普通的单实现的接口一般,如下代码块所示。

@Autowired 
private SubtitleFetcher subtitleFetcher;//省略大段代码.......String subtitle = subtitleFetcher.fetchSubtile();//省略大段代码.......

在闲鱼的应用情况

目前,SWAK框架在闲鱼已经在商品发布和编辑的部分流程上得以应用,我们正在积极将SWAK框架扩展到到更多的流程上。下图是基于SWAK框架的商品域核心功能的改造计划。经过基于SWAK的升级改造,闲鱼商品域核心功能按照业务隔离,各业务开发同学仅需关系其对应业务的开发即可,其通用逻辑和业务隔离由基于SWAK框架的一层和二层充分保证。代码质量和开发效率将获得显著提升。

 

总结

闲鱼自研的SWAK这一多实现规则化执行框架,可以很好地解决平台代码和业务代码耦合严重难以分离、业务和业务之间代码交织缺少拆解的问题。并且SWAK 100%兼容Spring,使用方便,快速上手。名副其实地,SWAK框架就像瑞士军刀一样可以适用于多种场景,小巧方便。当然,SWAK仍在不断进化,特性和功能仍在不断丰富。类似地,在闲鱼还有很多有意思的、创造性的尝试。


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

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

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

相关文章

(Docker实战) 第4篇:Centos7 拉取和部署Redis

文章目录搭建redis搭建redis docker run --name redis -di --publish 6379:6379 redis:4.0远程验证测试: 想学习更多微服务、分布式、中间件、数据库、项目快速构建等系列技术 请访问http://gblfy.com 让我们一起进步!!!

阿里巴巴上线静态开源站点搭建工具 Docsite

近日,阿里巴巴在Github上线了静态开源站点搭建工具Docsite,这是一款集官网、文档、博客和社区为一体的静态开源站点的解决方案,具有简单易上手、上手不撒手的特质,同时支持react和静态渲染、PC端和移动端、支持中英文国际化、SEO、…

重磅 | 边缘计算核心技术辨析

戳蓝字“CSDN云计算”关注我们哦!作者 | 中国电信广研院责编 | 阿秃边缘计算(Edge Computing)是云计算向边缘的延伸,本文对边缘计算、雾计算、MEC、Cloudlet、分布式云等边缘计算领域相关概念和技术的定义、架构、场景等进行了比…

php请求接口两次,php curl post请求执行一次curl_exce 请求的接口确执行两次

1、php curl post请求接口,打印日志执行了一次curl_exce,但是请求的接口却重复执行两次.2、代码:$ch curl_init();if(false $ch){writeRedisLog(create_curl, $activity_id, $mobile, $user_id, , 0, curl failed to initialize);}curl_set…

(Docker实战) 第5篇:Centos7 拉取和部署搭建 NEXUS私服

文章目录搭建nexus私服1. 安装nexus3(admin/admin123)2 .配置nexus32.1 新建一个maven2(proxy)仓库2.2. 新建一个maven2(hosted)仓库2.3. 配置public仓库搭建nexus私服 1. 安装nexus3(admin/admin123) #创建文件夹,安装过程如果…

Nacos发布 v0.2 版本,无缝支持 Spring Cloud 微服务生态及高可用集群模式

近日,阿里巴巴新开源项目Nacos 发布了 v0.2 版本,该版本开始支持完整的Spring生态技术栈,这包括 Spring Framework、Spring Boot和Spring Cloud。 为了让更多的Spring用户可以在生产上基于 Nacos 做微服务平台的服务发现、配置管理、服务管控…

是时候展现真正的技术了!4道程序员智力题你能对几道| IT巨能唠

程序员对很多人来说那就是个神秘组织,高薪、加班多都是他们的代名词。但是,大家好像还忘了一点,那就是他们也绝对聪明!黑客、代码天才、编程老手……层出不穷,晦涩的计算机难题也是分分钟搞定,想想就令人神…

阿里关涛谈大规模计算—从数字化阿里到数字化城市的进化

在刚刚结束的2018杭州云栖大会上,阿里巴巴通用计算平台负责人,阿里巴巴计算平台资深技术专家关涛从计算力,联合计算,智能化,企业级服务能力四个方面详细介绍阿里巴巴统一的超大规模数据计算平台MaxCompute的探索与实践…

15年大厂经历!大佬总结:0基础如何学习Python?

在学习之前,你一定要知道你的学习目标是什么。现在市面上有太多人鼓吹“Python太火了”、“Python第一”。但是,注意,“火”、“第一”一定不能成为你学习的理由,千万别火急火燎的随大流。正确做法是,看看市面上的真正…

STL体系结构概述

文章目录 STL是什么?STL的六大组件STL的实现版本额外补充一、容器范围区间二、容器结构与分类序列式容器关联容器有序关联容器不定序关联容器 参考 本文将是STL系列的第一篇文章,主要参考《STL源码剖析》,辅以网络博文,不定时更新…

迁移学习让深度学习更容易

深度学习在一些传统方法难以处理的领域有了很大的进展。这种成功是由于改变了传统机器学习的几个出发点,使其在应用于非结构化数据时性能很好。如今深度学习模型可以玩游戏,检测癌症,和人类交谈,自动驾驶。 深度学习变得强大的同…

java多线程系列:通过对战游戏学习CyclicBarrier

CyclicBarrier是java.util.concurrent包下面的一个工具类,字面意思是可循环使用(Cyclic)的屏障(Barrier),通过它可以实现让一组线程到达一个屏障(也可以叫同步点)时被阻塞&#xff0…

Wi-Fi 6到底有什么特别?

戳蓝字“CSDN云计算”关注我们哦!作者 | 甜草莓责编 | 阿秃▋ 什么是Wi-Fi 6 ?Wi-Fi 6,是Wi-Fi联盟给IEEE Std. P802.11ax起的别名。众所周知,以前我们的Wi-Fi都是叫作802.11a/b/n/g/ac/ax之类的名字。这种命名方式实在容易让人…

matlab直流电机pid调速仿真,直流电机双闭环PID调速系统仿真设计

目录直流电机双闭环PID调速系统仿真1 转速、电流双闭环直流调速系统的组成及工作原理2 双闭环调速系统的动态数学模型3 调节器的设计3.1 电流调节器的设计3.2 转速调节器的设计4 搭建模型5 参数计算5.1 参数的直接计算5仿真具体参数6 仿真结果7 结束语8 参考文献摘要在工程的应…

【小技巧】桌面图标出现蓝色问号的怎么办?

【背景】 今天因为要联调前端所以用SVN更新了一下前端的代码,结果没想到桌面图标全部变成了带着蓝色问号的,吓了自己一跳。查了一下之后顺利解决了,不过以防万一记录一下解决方法。 【内容】 解决步骤:首先确定是SVN的问题导致了…

恒强制版系统980_速来围观 | 恒强制版小图高级功能讲解

点击蓝字关注我们 Spring comes小图是用自定义的动作来定义使用者色码(120-183)。小图的主要构成如下图:1. 模块色数属性模块色数有如下规则:(1) 小于100(一般填1)的小图为普通小图【980修改】;(2) 小于200大于100(一般填101)的小图为提花小图…

读懂这篇文章,你的阿里技术面就可以过关了 | Apache RocketMQ 101

在美国的大学课程中,101是所有课程中的第一门,是新生入学后的必修课程。阿里巴巴中间件技术专家刘振东在上周的Apache RocketMQ开发者沙龙北京站的活动上,进行了主题为《ApacheRocketMQ 101》的分享,帮助开发者从0开始学习 Apache…

Nacos 计划发布v0.2版本,进一步融合Dubbo和SpringCloud生态

在近期的Aliware Open Source 成都站的活动上,阿里巴巴高级工程师邢学超(于怀)分享了Nacos v0.2的规划和进度,并对Nacos v0.3的控制台进行了预览。Nacos v0.2将进一步融入Duboo和Spring Cloud生态,帮助开发者更好的在微…

你还在疯狂加班打码?兄dei,不如跟我学做超融合吧!

纵观过去十年,媒体、娱乐、交通、银行、保险、医疗、旅游、物流等行业,无一不打上了数字化的烙印。据统计,一百多年前,公司的平均寿命是67年;而在当今的数字化时代,则锐减至15年。 除此之外,更有…

你只差这两步 | 将Sentinel 控制台应用于生产环境

这是围绕 Sentinel 的使用场景、技术对比和实现、开发者实践等维度推出的系列文章的第四篇。 第一篇回顾: Dubbo 的流量防卫兵 | Sentinel如何通过限流实现服务的高可用性 - 传送门 第二篇回顾: RocketMQ 的保险丝| Sentinel 如何通过匀速请求和冷启动…