论接口原子化和简单化的重要性


这篇文章咱们不说技术,而是来说说接口的设计,最近在做一个项目,遇到一个产品设计的问题,对前端的交互、后端实现带来很大的麻烦。在产品经理提出这样做的时候我就提出了很强的异议,但是技术经理觉得这样在技术上实现没有任何问题,最后只能屈服,完成这个功能的开发,现在随着版本的迭代,问题慢慢被放大,不但界面交互很low,后端数据存储和关联也隐藏了弊病。接下来就详细说一下这个过程,然后说说我对接口要原子化、简单化重要性的理解。

1. 我们项目是这么做的

这里涉及到公司项目机密,内容不能外泄,这里我就以示文字描述来说。

废话不多说,这里先说功能:

  • 在这个项目中有个产品的概念,每个产品都有自己的A列表、B列表、C列表
  • 在操作界面中可以编辑A列表、B列表、C列表,这个编辑包含增删改操作
  • 对这些列表一系列操作都是缓存到前端,然后由前端一次性提交到后端

这个功能算是常规操作,这个常规操作对后端是一个考验,因为前端提交是全量的,里面包含增、删、改三个操作,后端就需要进行复杂的判断操作。实现方式有两种。

1.1 第一种:先删再插

  • 接收到提交请求后,将库中该产品中存在A、B、C列表数据全部清理(逻辑清理)
  • 将前端提交来的数据全部直接插入数据库

这样就可以屏蔽增、删、改的检查逻辑,简单粗暴,但是这个是有问题的,后续来介绍。

1.2 第二种:逐步判断

  • 接收到请求后,将库中该产品中存在的A、B、C列表全部查询出来
  • 将前端提交的数据和存量数据依次对比判断,根据判断结果,确定是增、删、改中的哪个操作,然后做对应的操作

这样是对数据比较友好的操作,但是对开发人员是一种折磨,因为比对逻辑很复杂,特别是对于复杂的列表。如A列表中单个元素,然后元素内部又嵌套其他属性或元素,层层嵌套和关联。(我们项目就是这样)

两种方式都介绍完了,你觉得我们应该是选的那一种?以偷懒为第一准则,我们选择了第一种。

一开始功能不是很多,关联的逻辑不是很复杂,这种做法弊病并不明显。但是随着时间的推移,迭代更新添加了一个D列表,此时D列表中元素会关联A列表中的元素,那么问题来了,因为先删再插的第一个弊病就出来啦,自增ID滚动问题,当D列表中D1元素关联了A列表的A1元素,A1元素对应的ID是1,当下一次提交的时候原A1元素被删除,重新插入,ID已经不再是1,而是滚动到了n,这个时候D1元素原来的关联关系就无效啦,可能你会觉得直接把D1元素关联A1元素的ID改为n就好了,但是这里还是要注意,一次性提交,D1元素也会被删除重新插入,那要如何找到新的D1元素呢?整个实现过程逻辑繁杂无比,不但容易出错,还不利于后期维护。

2. 我觉得应该怎么做

下面来说说我个人的看法。在项目需求提出后我就提出这里列表过于复杂,不建议一次性提交,其实我第一的想法是上面第二种实现,提出比对过程过于复杂。后来经过技术经理、产品经理一起讨论,我最终失败,实现采用一次性提交,并使用了上面第一种实现方式。

2.1 弊端剖析

  • 增、删、改操作在一个接口实现,采用一次性提交,前后端实现难度都大,首先前端要缓存数据,后端不管采用先删后插还是逐步判断方式都不很友好,先删后插对数据库不友好,逐步判断对代码实现不友好;
  • 采用先删后插,其中删除的数据是逻辑删除,会一直保留在数据库中,会导致过多的冗余数据。以一个产品A、B、C、D列表中各有5个元素来算,是20个元素,每做一次修改相当于产生20条冗余数据,以一个产品平均修改2次来算,会冗余数据量为40条数据,再以整个项目100个产品来算,那就是4000条冗余数据。总的算下来,数据库中有6000条数据,只有2000条是有效的。也就是说有66%的数据都是无用的。
  • 采用逐步判断,首先需要将存量数据查出来,依次进行增、删、改操作的检查,接口处理效率、响应时间都会大打折扣,其中复杂程度不多说了,用心去体会。
  • 先删后插还有一个问题就是ID的滚动,导致之前关联数据的ID失效,需要重新更新关联,如果这个关联比较复杂,涉及数据量大,那将是很大的性能消耗和繁杂的操作。
  • 一次性提交,存在登录超时问题,因为真个列表编辑比较复杂,另外在编辑的过程可能受到外界干扰,在提交数据的时候,用户登录超时,导致之前辛苦填写的数据全部丢失,回到解放前。

2.2 我觉得怎么做

把操作原子化和简单化,就是这么简单,当操作A、B、C、D列表的任意一条数据,操作后立即提交,这样只会涉及到一条数据的操作,不管是增、删、改,都不会造成很大的影响面,除了删除操作需要做关联数据的变动,其他都不需要。它可以解决上面的所有问题,但是可能会说删除也可能导致关联数据的实现,需要对关联数据变动,但是这个时候变动量和操作的难度就很小啦,不管从代码层面还是从数据库层面都是友好的。

如何原子化,就是保证接口的原子性,让一个接口实现一个功能,功能接口中的操作是不可拆分的,但又有质疑,一次性提交里面的每个操作也是不可拆分的,应该也是原子化。但是上面还提到了另一个名词,那就是简单化,把多条增删改操作一次提交,改成单条增、删、改操作分别提交。

  • A、B、C、D四个列表,四对增、改接口,共8个接口;
  • A、B、C、D四个列表的删除功能综合成一个接口;

整体算下来是9个接口,从原来的一个接口变成9个,是不是很麻烦,其实不然,因为单个接口的业务代码会变的很简单,出现问题易于排查,业务逻辑清晰,后期如果涉及交接给他人,功能、逻辑清晰,易于理解,更便于上手。

3. 总结

在开发代码的时候很多人有很多不好的习惯,比如不写注释、一个方法几百行代码、多层代码嵌套等,都会让本来可以优雅的代码垃圾化。上面的原因有时候也不能完全归结于开发错误,部分也是产品设计上的问题,如上面我举得例子,单个操作很复杂,不得不写大量的代码,加上开发人员偷懒,几百行代码方法的出现很正常,同时多层嵌套判断也是不可避免的。所以从产品设计上来说,必须结合实际功能,做好产品交互友好,后端实现友好。这个就要产品经理懂技术,能够根据技术建议,在不影响正常功能的情况下优化前端和后端交互的合理性。


文章作者: 程序猿洞晓
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 程序猿洞晓 !
评论
 上一篇
Centos7系统出现ifconfig、yum命令不可用问题解决 Centos7系统出现ifconfig、yum命令不可用问题解决
Centos7刚安装好后,执行ifconfig出现命令无法找到问题,然后使用yum search ifconfig出现错误。其实主要的原因就是网卡没有配置好。这里其实很困惑,Centos6都是默认安装的,到Centos7虽然升级了,但是感觉还没有Centos6好用。另外还有一个防火墙,对应的命令也是发生了变化……
2020-04-02
下一篇 
数据结构和算法(三):常用对称加密算法之AES 数据结构和算法(三):常用对称加密算法之AES
摘要加密算法一般是用来保证数据的完整性和一致性,上一篇文章中提到了两个常用的摘要算法分别是SHA和MD5。在这篇里面,一起来学习一下一个常用的对称加密算法AES,它的主要作用是保证私密信息不被泄漏。对于这个应该都很熟悉,只要使用到对称加密,相信百分八十以上都是用AES。
  目录