前言
最近一年工作,见识到了非常多的新东西,也学到了很多开发时要注意的要点,之前一直很忙没有时间总结,趁现在难得有空把这个东西重新记一下。
正文
1. 接口/请求
对于一个项目来说,接口是一个特别令人头疼而又马虎不得的东西,特别是对于规模比较大的项目来说更是如此,每次涉及到接口相关的需求都需要做非常多相关的内容确认。
-
某个接口升级到新版本,一定要考虑旧版本升级的影响,比如说某个接口原先有3个字段,且缓存到本地,更新后有5个字段,那么在开发的时候,就一定要考虑到获取不到5个字段的情况,并作出对应的业务处理。
例:拥有缓存功能的接口A返回有三个字段,升级后返回五个字段,那么在实际场景中可能会有这样的场景,用户在刚刚升级之后取了缓存的内容,发现过期,想要去请求,结果请求挂了,那么用户此时就只剩下三个字段的接口A,如果没有考虑到这种场景,可能用户就没办法继续执行后面的业务了。
虽然每个用户也许只会经历一次这种场景,但是用户是不会管你这些的,他就觉得你这个APP,升级之后,功能没了,莫名其妙的,就会来反馈来说。为了用户体验的角度还是要考虑好这种场景。
-
对于所有的请求,都一定要考虑他不可靠的情况,比如说请求延迟或者请求失败的情况。如果有必要甚至可以把UI的业务处理放到等待请求结束之后。
所以对于请求A的数据 -> 更新UI -> 用请求A的数据再去请求B -> 再次更新UI,类似这种场景,一定要考虑到请求A挂了的情况。 -
对于规模大的项目来说,每次要新增请求或者请求场景的时候,都要对这个请求做一次QPS的评估,算一下在最高峰值的情况下,服务器还能不能顶得住,当日服务器能承受多少QPS要找服务端去问,但是客户端应该是可以统计某场景下的QPS峰值的。
2. 沟通
- 产品思维:这里不是说我们开发要去替产品做些什么事情,而是我们从产品手上接任务的时候,要仔细的去了解这个需求的背景和产品眼中用户(当然也有可能是用户自己提)的需求点,这样我们在做需求的时候,才会知道对于产品来说,这个需求最核心的目标是什么,这样我们在做开发过程中,就有可能主动的去注意到一些产品无法注意到的细节(毕竟产品又不是写代码的那个人);或者在无法完美的做完这个需求的时候,可以知道什么点是可以暂时被放弃,后续再优化的。
- 测试:开发的时候对于代码的影响面需要仔细的评估,在把任务交给测试和的时候将影响面还有内部的一些细节全部说明。如果无法说明,就代表着自己也不清楚为什么要写这段代码,只有自己搞懂了才能说给别人听。
- 和别人沟通的时候,最好是确认一下彼此之间的理解是否已经达成同步了,我刚到新公司的时候,有时候会出现一些明明我和测试说的都是同一个词,但是理解的确实两个意思的奇妙现象,在那之后,我在和产品或者测试沟通的时候,我都会尝试重新复述一下他们的观点(特别是当内容说的很多的时候,本来听着就比较乱,不整理一下完全搞不清楚),看看我是否有真的理解对方的意图。
3. 灰度
灰度是一个有意义而且重要的功能,当项目规模越大的时候,越需要灰度,来控制新编写的代码,这样在功能失控的时候还有一个回退的手段。
- 在有灰度的基础上,如果要重新迭代一个旧的模块,要做的应该是将旧模块中的主要方法抽象成接口,然后用依赖注入的方式去编写新的模块,这样做的好处就是调用方只需要生成不同的接口实例,就可以直接操作新旧模块,而不需要关注模块内部具体的区别。且在有灰度的情况下,模块根据接口区分清除的情况下,也可以简单明确而又快速的编写灰度开关代码。
- 灰度有一个比较麻烦的地方,就是如果在你删除旧的灰度功能之前,你的相关业务都需要对灰度做开关的判断,很麻烦。而且作为后面来的开发者,还有可能不清楚该功能有灰度的情况,就容易失误
例:有个功能A0,打开灰度之后是A1。然后有个功能B,他的一部分功能需要调用功能A才作用,那再调用的时候,就要判断A的灰度是否打开来调用A0或者A1。
4. 模块化
-
尽量避免去写一个Manager类,后续不好维护,很容易加着加着就膨胀了(因为从类的职能上来说貌似所有方法都可以加到这个Manager类中),最好将一个管理类,以内部方法的职责区分成几个类(对外服务类,对内数据维护类,本地存储,请求,工具类等)且对于一个单独的模块来说,除非必要否则尽量不要去import外部的包,尽量做到功能的独立性。
-
同样的模块绝对不要写两个,如果他们只是有一部分功能不同,就在模块内部自己区分。一旦一模一样的东西出现了两个,紧随而来的问题就是:开发的时候要用哪个模块才好。我开发的时候总是会不自觉的去看以前别人写过的代码,这就会导致用模块的时候用的不一样,万一其中一个有什么问题用的时候又没看仔细的,就容易出问题。
如果这个模块本身有点缺陷,无法满足现在的业务需求,最优的做法就是去迭代这个模块,但是可能会出现该模块是好几年前写的,没人看得懂也没人敢改的情况,这种时候就要重新写个新的模块,用@Depreciated将旧的模块全部关闭,让后面的开发者不再使用旧的模块。
-
在有灰度的基础上,如果要重新迭代一个旧的模块,要做的应该是将旧模块中的主要方法抽象成接口,然后用依赖注入的方式去编写新的模块,这样做的好处就是调用方只需要生成不同的接口实例,就可以直接操作新旧模块,而不需要关注模块内部具体的区别。且在有灰度的情况下,模块根据接口区分清除的情况下,也可以简单明确而又快速的编写灰度开关代码。
-
开发功能的时候要有组件化的思维,想想自己这次需求的功能,有没有可能在未来以另一种形式再次被用到,这样的话就可以一开始就将代码中可以重复利用的部分挑出来,就是一个好用的工具类,如果之后再让他支持不同的参数设定的话,就可以算是一个组件了。