15

软件如何优雅地向前兼容?

 3 years ago
source link: https://zacharyfan.com/archives/1351.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

这里是Z哥的个人公众号

每周五11:45 按时送达

当然了,也会时不时加个餐~

我的第「163」篇原创敬上

大家好,我是Z哥。

应该有不少程序员受过这样的困扰,特别是做后端的。项目一直在持续不断的迭代,但是呢老版本的代码还不能直接删掉,因为不一定所有的调用端都能在同一时间点完成升级。

你是怎么处理这种情况的呢?

方法上增加参数?方法实现里增加if else?

论难度的话,这个问题是不难,肯定每个人都有办法解决。但是解决的是否优雅?是否会给后续带来更大的成本?有这考虑的人可能就不多了。

我看到过一些项目里做兼容的方法是真的粗暴,直接怼if else。

比如,原本创建一笔交易的时候,我们需要的数据是用户的姓名、收货地址、邮编。现在迭代的一个新版本需要增加手机号信息,并且不需要邮编了。

粗暴的写法怎么写呢?

if(postData != null ){
if(postData.mobile != null){  //新版本的处理方式  }  else{  //旧版本的处理方式  }  }

如果以后再新加了一个参数呢?if else再多嵌套一层……

你见过类似上面那样的代码吗?

这可能是最容易想到的改法,但针对向前兼容不仅仅只有这一种方式。容我一个个来说。

/01 通过接口上增加版本号/

最常用的增加版本号的方式是直接加到接口上。比如,

http://api.xxx.com/1/user/login

如果后续的改动完全是新业务的追加,那么可以继续沿用这个1版本的接口。如果有做删减,那么可以新增一个版本2的接口,调整后的业务逻辑在这个版本的接口里实现。

http://api.xxx.com/2/user/login

这样一来,你的项目中就同时存在了两个版本的接口。新的客户端调用2版本的,老的客户端调用1版本的。

在这个期间,让客户端尽快都升级到2版本,然后后续就把1版本的接口删掉。

有的人有代码洁癖,觉得一个项目里同时存在两个相同业务逻辑的接口不太舒服,那么可以试试下面这个方法。

/02 一个前端版本对应一个后端版本/

与上面的区别就是,在项目的代码里,你不用新增加一个接口出来,直接把原先的接口修改成新的业务逻辑即可。

但是呢,新版本上线的时候,老版本不能被全部替换掉,需要保留一段时间给旧版本的客户端使用。这件事的逻辑与前面一样,给客户端一段时间来升级。

其实所谓的「服务发现」或者说「服务治理」就是这类思想的体现,只是玩的更加体系化。

在服务发现的服务端,针对不同的服务本身就有版本的概念,比如:

OrderService/v1 : 192.168.0.1:8000 , 192.168.0.1:8001  OrderService/v2 : 192.168.0.1:8100 , 192.168.0.1:8101  UserService/v1 : 192.168.0.1:9000 , 192.168.0.1:9001  UserService/v2 : 192.168.0.1:9100 , 192.168.0.1:9101  ……

客户端调用的时候,根据其传入的版本号,自动路由到对应版本的服务目标地址。

当然这个方案有一个问题是,由于产生环境同时运行着多个版本的程序,所以数据库的字段只能增加,不能删除,并且增加的字段需要给上默认值。

删除字段只能随着后续旧版本的去除进行。

除了以上两种方案外,我们还可以做一些其他的工作以保障向前兼容更好地进行。

/01 数据库设计预留扩展字段/

我们在设计数据表的时候,如果对后续业务预判会扩展。那么可以在做数据表设计的时候预留几个扩展字段(ext1,ext2,ext3,……)。

这样的话配合上面提到的方案2能更好地进行,因为后续新增的字段可以暂时存在这些扩展字段里,不需要对表结构作出变更。

/02 APP提供强制更新功能/

如果是针对APP的向前兼容,那么务必在APP里留出一个强制更新的口子。以免有些用户长期不升级,导致你的旧版本迟迟无法去除。

针对你可以承受的多版本情况,可以给予提示性的更新提醒,由用户自行选择是否更新。如果针对少数隔了多个版本还未升级的用户,可以给出强制性的更新,让其无法继续在旧版本上操作。

强制更新也分局部更新和全量更新。现在针对局部更新的「热更新」受到了一些应用市场的限制,所以在用「热更新」之前谨慎了解对应平台的规则。

另外,向前兼容不可能是无止境,不丢掉一些包袱,不断的新增包袱只会让后续的维护成本不堪重负。

所以需要做好对各个版本使用情况的监控,一旦某个版本的使用量低于某个值,就应该给予强制更新的提醒。

其实类似的向前兼容问题,除了api之外,在对外提供的三方库SDK、公司内给其他项目调用的二方库SDK中,也有一样的情况。

他们的解决思路也是类似的。

最后我建议你多看一些知名的开源项目,从中你可以学到很多优雅的编程技巧和代码设计理念。

好了,总结一下。

这篇呢Z哥和你分享了软件向前兼容的一些方法。除了粗暴的if else之外,你可以尝试一下以下两种方法:

  1. 通过接口上增加版本号
  2. 一个前端版本对应一个后端版本

除此之外,以下这两件事也对做好向前兼容有很大帮助。

  1. 数据库设计预留扩展字段
  2. APP提供强制更新功能

希望对你有所帮助。

不要光顾收藏,记得用起来哦。

原创文章,转载请注明本文链接: https://zacharyfan.com/archives/1351.html

关于作者:张帆(Zachary,个人微信号:Zachary-ZF)。坚持用心打磨每一篇高质量原创。欢迎 扫描二维码~

Ab2ARjU.jpg!mobile

定期发表原创内容:架构设计丨分布式系统丨产品丨运营丨一些思考。

如果你是初级程序员,想提升但不知道如何下手。又或者做程序员多年,陷入了一些瓶颈想拓宽一下视野。欢迎关注我的公众号「 跨界架构师 」,回复「 技术 」,送你一份我长期收集和整理的思维导图。

如果你是运营,面对不断变化的市场束手无策。又或者想了解主流的运营策略,以丰富自己的“仓库”。欢迎关注我的公众号「 跨界架构师 」,回复「 运营 」,送你一份我长期收集和整理的思维导图。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK