APP超过5年的产品或者公司业务几何倍增长的产品,不可避免的会需要重构来保证APP的性能和稳定性,可维护性。
从一个业务一个人完成变成了一个业务N个人协同合作完成。在代码层面就是去耦合模块化的过程。经历过一些过程留下一部分经验供大家参考。下边说的是个人感触,也许你不太理解,我会备注相关的工作场景一一举例。
1.减少对象的public属性
简单说,可读性,可维护性。复杂说,你能减少各种风险和坑,特别是多人协作的团队。
用一个工作场景说明:
一个VIewController(VC),早期1需求1.0版本:
VC:1.支持右滑关闭手势 2. 右上角带有详情按钮固定显示,3.一个webview可以通过sckem交互4.统计用户行为信息。你自己初步作出的类没有问题。
之后A同事来了2需求:
需要同样功能的VC,但要添加一个跳转二级页的按钮,并且和你的详情按钮互斥。时间紧,B稍微懒一点,拿你的VC用,.h里添加一个public BOOL类型,来解决这个互斥,并且把跳转二级页面的逻辑页加入你VC里,一大堆业务逻辑也在你这扎根。没有大改你的,他也OK。
之后B同事又来3需求:
需要同样功能的VC,他的业务逻辑是需要弹出一个弹窗,能直接进行支付,依然时间紧,还不敢大改你和B同事的代码,只添不改,肯定不会影响你们的逻辑,很快整上了,开发过程中它的业务逻辑出现一个幺蛾子,整了一个特殊逻辑,比如又需要详情按钮,但是点击详情按钮和你的逻辑完全不一样,这时候,你觉得B同事会怎么做?在加一个public枚举或者bool来区分你和他的逻辑啊。
之后CDE同事。。。他们只增加不修改源代码,肯定没有那么问题
突然你来了来个需求,之前需求2.0版本,你是不是要哭,稍微大动点就要兼容她们的逻辑是不,想直接抽取出一个VC,让他们继承,但是几个人开发任务也紧,都动也来不及,你怎么整尼。
工作教训告诉我们:当public属性多的时候,这里必是肮脏之地,也必会在不经意造成不必要的BUG,代码是种艺术需要被坑过无数次你才能明白,如果当时的B就抽出来一个基本功能VC,还有后边的坑吗?如果你的APP超过2年绝对有此问题,当APP初期都在赶业务的时候更明显。找一个维护同一APP3年以上的架构或者高级开发好处就在于他能提前避坑,保证你程序的健壮性,并且保证其扩展性。
2.基于自适配的 复杂的UI界面引用contenView区分上(左)下(右)
不要把所有的view都直接加在backgroundView上,特别是一些和业务逻辑紧密相关的View,把其上subviews独立出来,如果感觉delegate多,就使用block,可读性极高!
另外就算改动一个subview,其适配只仅限于contenView的范围内,影响小,维护成本低!
3.能用block解决的问题,不要单独去通过delegate来中转,
想象一下 一个VC既有request的回调,又有action回调,还有第三方库回调,日积月累,鸡毛一地!@weakify(self),@strongify(self)避免循环引用:__block。
4.UI开发中,创建view最好用getter/setter方法
简单明了,可读性高,代码整洁,无论你看别人 ,别人看你都是爽心悦目!使用GCC Code Block Evaluation C Extension ({…})语法,结构化局部变量初始化和处理的逻辑(如上图)
5. one method do one thing(一个函数只做一件事)
工作实例:今天又踩了一个坑,什么样的坑尼,原有的函数有两个
-(BOOL)showGuide;//显示引导图(当版本版本显示一次) 并且返回显示结果
-(BOOL)showAD;//里边的代码其实显示广告图,并返回显示结果
第一次安装肯定没有广告数据,原有逻辑是:首先判断是否有广告数据,如果没有广告数据显示引导图,如果有广告数据则判断是否此版本的第一次打开,如果第一次打开,依然显示引导图。这块代码已经2年没有动过,也没有详细产品文档来说明这块,目前出来一个BUG,如果版本升级,覆盖安装,上版本APP有缓存广告数据,这时候就出现先出广告再出引导图,体验有问题。
我就这么改的:
if(FirstLaunch){
[self showGuide]}
else{
[self showAD]}
结果踩上地雷了,因为什么尼? 请求广告的数据的逻辑放进了showAD中,请求广告的数据的策略是只要启动,请求下次的广告数据和广告角标。原有逻辑没有问题是启动就执行[self showAD]返回当前是不是有广告数据,所以再返回BOOL的同时去请求下次的广告数据,没有问题,但是修改BUG后逻辑明确,但是缺造成了第一次启动就不会请求广告数据,我的天啊,没有广告老板不杀了我,幸好发现的及时。
一方面是自己不细心,另一方面这得多坑人啊,你把showAD返回BOOL也就算了,你把请求的广告的函数放入这个函数,并且没有任何的注释说明,坑我的爽歪歪了。心有余悸!
保持健康的心态,相信当时同事可能想着开机广告的逻辑都放一起,言归正传由此得到的教训是一个“功能”函数极可能的只做一件事(此处不要一偏概全,不是说viewDidLoad内只放view加载,相关的统计就不能放入)。
自己亲自拆分其中的函数,把-(BOOL)showAD拆分成-(BOOL)checkShowAD,-(void)showAD,-(void)requestADData;