封装复杂度之批量接口

简介: 封装复杂度之批量接口

一、背景

在平时项目开发过程中,难免需要作为接口提供方封装批量接口给上游调用;或者作为上游系统调用下游业务或者中间件的批量接口,执行某些操作。

lu.png

常见的批量操作有很多,比如批量查询内容详情,批量发送提醒;批量插入数据、批量更新、批量发送MQ消息等。


不知道,大家想过没有。


为什么要提供批量接口?


作为批量接口的提供方和批量接口的使用方我们通常需要注意哪些问题?


二、 问题思考

2.1 为什么要提供批量接口?

通常最主要的一个原因是为了性能优化。


通常 IO 操作是性能的主要瓶颈,批量接口可以减少网络 IO 次数,从而达到降低耗时的目的。


2.2 批量接口的提供方我们要注意哪些问题?

【1】健壮性

很多人,尤其是新手,容易直线思考,批量接口嘛,直接传给我一个 List 作为参数,返回结果即可。


(1) 批量限制


如果上游传入集合中元素多,会不会有问题?


上游传入的元素过多,很容易对本系统造成很多压力,而且非常容易超时。


public List queryOrders(String userId, List orderIds){

 // 省略

}

因此,批量接口通常需要增加分页参数,通常需要对集合长度进行检查。


public List queryOrders(String userId, List orderIds, PageRequest page){


 // orderIds size 检查

}

FBI Warning:请在函数的注释中或者接口文档中必须显式标注集合长度限制!


(2)参数校验


上游传入的参数合法性也要进行校验,比如例子中 userId 是否有权限查看这些 order ?


public List queryOrders(String userId, List orderIds, PageRequest page){

 // userId 合法性校验

 // orderIds size 检查


再比如传入日期,日期的格式是否正确,是否符合预期? 都是需要考量的事情。


(3)并发校验

有些批量操作不允许并发,要考虑加分布式锁。


(4)失败处理

失败该如何处理,也是一个需要考虑的问题


将失败的对象当做返回值返回给上游? 将失败的部分忽略掉?中间有数据失败,需要回滚?


【2】可拓展性

通常建议将主要参数甚至返回值定义成自定义对象,而不是使用封装类型在函数签名中铺开。


请看下面的案例,如果后续需要新增一些参数,就需要提供新的接口:


public List queryOrders(String userId, List orderIds, PageRequest page){

 // 省略

}

可以参考以下写法,将参数定义为批量查询对象:


public List queryOrders(OrderBatchQuery query, PageRequest page){

 // 省略

}

这样如果需要新增参数时,不需要修改函数签名。


对于一些“写”操作,还可以考虑,提供失败处理策略,如失败抛异常、部分失败返回失败列表等。


【3】封装复杂度

通常提供批量接口的同学会理直气壮的认为,设置集合 size 限制,最多再给个 page 参数就可以了。


如果有批量的需求,自己去对集合进行分批,自己对分页进行处理呗!


其实最大的问题是,几乎所有上游都需要对当前自己拿到的整个 list 的所有内容都要进行查询!!每个使用方都要自己处理分批和分页,非常麻烦,气得直跺脚!!!


其实有时候可以多走一步,既能体现出自己的专业度,也能更容易赢得上游的信任和称赞。


可以考虑提供一个自动分批和处理分页的方法(需告知上游虽然可以自动分批,但是如果 size 过大仍然会有因数据量过大导致调用超时,甚至 OOM 的风险)。


还可以提供一个自动对参数接口进行分批执行调用拼接结果的工具类等。


对于带返回值的调用,可以参考下面工具方法的定义:


public static  List partitionCall2ListAsync(List dataList,

                                                        int size,

                                                        ExecutorService executorService,

                                                    Function, List> function) {

 

}

                                                     

                                                 

其中 dataList 即待分批的集合, size 即每一批的数量, executorService 线程池,Function function 即单次调用。


可参考为的另外一篇博文:https://blog.csdn.net/w605283073/article/details/101399427


2.3 批量接口的使用方需要主要哪些问题?

【1】长度限制

不管是业务接口还是中间件的批量接口,通常参数中集合都会有 size 限制,一定仔细看函数说明、接口文档,甚至有条件拉下对方源码看看实现方式。


工作这几年,已经见到过身边同时多次因为使用下游提供的批量接口,而下游没有在接口上写 size 限制,导致上游在数据量大时报错,测试阶段通常数据量较小不容易发现该问题。


如果下游没有提供自动分批的批量调用方法,可以自己在本系统的外部依赖模块通过编写一个 XXX对应的 XXXXClient 进行二次封装,避免将复杂度再向上游暴露。


【2】 部分失败如何处理?

要核实下游对部分失败的情况的处理办法,是提供了失败策略,还是一起回滚,我们直接失败或者重试?


三、启发

本文希望通过批量接口的编写和使用,让大家意识到封装复杂性的必要性。


希望大家在设计方案或编写代码时,一定要带着“封装复杂度”的思想,尽量将复杂度封装在更底层的位置。


这也是“迪米特法则”即“最小知道原则”的要求,也是高内聚、低耦合的要求。


创作不易,如果你觉得本文对你有帮助,欢迎点赞、收藏加关注,你的支持和鼓励是我创作的最大动力

————————————————

版权声明:本文为CSDN博主「明明如月学长」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/w605283073/article/details/120575996

相关文章
|
设计模式 机器学习/深度学习 SQL
软考高级系统架构设计师通关经验分享
为什么考系统架构设计师是国家设立的计算机技术与软件专业技术资格考试(简称软考)中的一个高级科目,属于工程师高级职称系列,具有一定含金量。浙江省每年通过软考高级的人数约为1000+人,其中系统架构设计师科目的通过人数约为200+人。从学习角度来说,通过准备系统架构设计师的考试的过程,可以查漏补缺,并且了解一些系统架构设计相关的基础知识,实现一定程度上的自我提升;从目的性的角度来说,通过考试,可以在一
14689 4
软考高级系统架构设计师通关经验分享
|
缓存 资源调度 区块链
Electron打包图标不显示解决方案
Electron打包图标不显示解决方案
2325 0
|
前端开发 Java
Java下载多个文件打成压缩包返回输出流,并解决被JVM占用无法打开
Java下载多个文件打成压缩包返回输出流,并解决被JVM占用无法打开
874 0
Java下载多个文件打成压缩包返回输出流,并解决被JVM占用无法打开
|
JavaScript 测试技术 Python
低成本、快速造测试数据,这个造数工具我后悔推荐晚了!
没有测试数据,所谓的功能测试和性能测试全都是无米之炊。但我发现一个蛮诡异的事情,就是行业内很少会有人去强调测试数据的重要性,甚至市面上都没有人在做测试数据这门生意。
低成本、快速造测试数据,这个造数工具我后悔推荐晚了!
|
11月前
|
Cloud Native JavaScript Devops
云原生技术在现代软件开发中的应用与实践
本文将深入探讨云原生技术如何改变现代软件开发的格局。通过分析云原生的核心概念、优势以及在实际开发中的应用案例,我们将了解这一前沿技术如何助力企业快速适应市场变化,提高开发效率和系统稳定性。文章还将提供实用的代码示例,帮助开发者更好地理解和运用云原生技术。
|
12月前
|
存储 NoSQL 开发工具
开发者如何使用表格存储 Tablestore
【10月更文挑战第11天】开发者如何使用表格存储 Tablestore
576 0
|
12月前
|
供应链 监控 数据挖掘
淘宝商品详情数据接口:解锁电商数据分析新密码
在数字化时代,电商竞争激烈,精准的数据分析成为制胜关键。淘宝商品详情数据接口如同一把神奇的钥匙,为商家提供商品名称、价格、销量、评价等详细信息,助力洞察市场趋势、优化商品策略、提升运营效率。通过实时更新的数据,商家可以及时调整定价、促销和库存管理,增强竞争力。未来,该接口将带来更多智能化的数据分析工具和精准的市场预测模型,助力电商从业者在竞争中脱颖而出。
|
C#
WPF 静态资源(StaticResource)和动态资源(DynamicResource)
WPF 静态资源(StaticResource)和动态资源(DynamicResource)
381 0
|
Java 开发者
Java一分钟之-Java IO流:文件读写基础
【5月更文挑战第10天】本文介绍了Java IO流在文件读写中的应用,包括`FileInputStream`和`FileOutputStream`用于字节流操作,`BufferedReader`和`PrintWriter`用于字符流。通过代码示例展示了如何读取和写入文件,强调了常见问题如未关闭流、文件路径、编码、权限和异常处理,并提供了追加写入与读取的示例。理解这些基础知识和注意事项能帮助开发者编写更可靠的程序。
273 0
|
SQL 弹性计算 Cloud Native
分布式事务 GTS 的价值和原理浅析
GTS 今年双 11 的成绩 今年 2684 亿的背后,有一个默默支撑,低调到几乎被遗忘的中间件云产品——GTS(全局事务服务,Global Transaction Service),稳稳地通过了自 2014 年诞生以来的第 5 次“大考”。
4469 85
分布式事务 GTS 的价值和原理浅析

热门文章

最新文章