遇到一个代码混乱不堪的Android项目该怎么办?

来源:互联网 发布:52单片机输出电压 编辑:程序博客网 时间:2024/04/30 06:49

转载请注明出处:http://blog.csdn.net/asdzheng/article/details/49403155

好久没写博客,这段时间换了工作,有很多事情需要学习和处理,现在终于有点时间来总结这段时间所做的事情。新东家是一家创业不久,正处于上升期的公司,我进去时刚好在扩招了四五人,目的很明显,我去之前也做好准备,上升期的公司应该有很多问题需要我去解决,也做好了应对初期留下各种脏乱代码的的准备;

可想象毕竟是想象,等进到公司,将代码迁移下来一看,尽管心中有备,还是抵不住的内心翻腾倒海脑海中无数只草泥马蹦腾而过,这样的代码也行。下面我就把我看到的代码总结一下:

问题总结

1、 同类型的处理,没有抽象,造成代码冗余

Android项目中最常见的的无非是网络接口请求,不同的业务对应不同的接口,处理流程就是 客户端操作业务 —> 客户端调用接口 –> 服务器接收请求 —> 处理完返回处理结果 —> 客户端接收结果 —> 客户端对结果做处理和显示; 这样一套流程,最常见的方式就是封装一套网络请求框架,业务代码只关注请求时传入对应接口关键字和参数,然后写几个回调方法等着接收数据就好。

但之前我们的框架并不是这样,每调一次接口都要新建两个方法,然后调用和处理代码一般都要写个100-200行模板代码,这框架直接导致的结果是,每个有请求网络的Activity,代码都至少要500行以上,大部分的界面都是上千行规模,可想而知,要熟悉这样的代码得多辛苦。

2、 不考虑性能,代码只要能用就行

例如数据存储,Android其实提供了4种不同的本地存储方式,特点各不相同,各有各得优劣势,适用于不同场景,这不做分析。这四种方式里,我想最容易使用当然是SharePrefences,没错,就是因为它容易使用,APP里的的所有存储都只用它,把它当作万能且用法极不规范。其中一点就是用它来保存大量列表对象,最大的一个数据保存完xml文件直接快100KB,如果要在这数据上做些增删改想想都觉得酸爽,但以前就是这么干的!不止如此,对于从prefence里拿数据的开销,此前根本就没在乎过,大量的如下代码:

if (PrefenceUtil.getD() != null) {        if (PrefenceUtil.getD().getD1() != null) {            if (PrefenceUtil.getD().getD1().getD2() > PrefenceUtil.getD().getD1().getD3()) {                doSomething();            }        } else {                doSomething();        }    } else {        doSomething();    }

其中PrefenceUtil.getD()是从sharePrefences里拿去拿数据,可以看到,一个判断,就操作了xml文件4次。

3、代码不规范,命名随意,到处的魔鬼数字

  • 大部分参数没有设置为private
  • 几乎没有注释,复杂逻辑代码只能靠猜
  • 布局的变量名没规则,例如每一个布局里的按钮都叫btn,代码里一关联上百个文件出来
  • 到处startActivityForResult(intent, 1001), 和setResult(1003)…
  • 工具有FileHelp有FileUtil…

4、相同的功能控件不做封装,每用到一处,复制一处

其中有一个条件筛选框,快上千行代码,逻辑复杂很容易出错,而且用处的地方很多,但是之前就是能够忍受,反正就是copy、copy、copy

以上这几点,每点都有无数的例子可拎出来暴尸几天,供大家笑话,但坏代码不重要,除非大公司有非常好的代码审核机制,不然坏味道的代码哪都能找出来,下面才是重点,面对这些代码时我们该用什么办法改进它们,让以后避免再出现这样的代码才是关键;

问题处理

1、针对我们项目的一些通用操作,我做了一些抽象:

  • 完备BaseActivity和BaseFragment和BasrAdapter,这三个抽象基类在Android项目真是太重要了,把这三个基类完善好,会让每个具体的业务界面少写几百行代码,而且不易出错,出错了又可根据业务需求统一界面修改和优化。以BaseActivity为例,我在里面放了请求接口的入口回调和销毁,TitleBar的统一构建,统一的错误页面和显示页面等等。

  • 将以前那个不知从哪里来的网络请求框架改为Volley,然后针对我们接口的做了自定义封装,例如通用参数底层封装好,请求前显示加载框,请求响应后消失,将网络回调分为三种类型,请求成功,请求数据异常和网络异常,具体业务根据请求结果做不同处理。

  • 建立类库,我们有三个项目,一主两副,以前各自为政,在我抽象了基础类和网络请求框架,发布了两个版本发现效果很好后,我就着手创建了类库项目,让这些每个项目都要用到的东西和一些自定义控件工具类放在类库里,让所有项目都能享受到我们优化和改进过的代码成果。

  • 当然还有一些比较细碎的抽象,如将类保存为数据库时都要经过一些列步骤的转换和解码转码为String类型在保存,更痛苦的是这些操作每个类都要来一次,我把它抽象成一个方法,然后再做一些优化。

2、性能的优化

  • 由于之前的数据都是统一保存在prefence里,现在一下子要换成别更合理的方式保存,要做的工作和测试量会比较大,在没有充足的时间下,不敢轻易更换存储方式。我分析了一下数据存储和获取的主要性能瓶颈是在那几个常用的和数据量比较大的类,像问题2举得例子,比较省时间的和立竿见影的优化方法,并不是先用一个变量来接收prefence里的值
    Data data = PrefenceUtil.getD() 然后再用data去做判断。这样做只会让一处地方得到优化,遇到一处改一处,只会忙死,更好的办法是优化PrefenceUtil.getD()方法里的内容。我把那几个数据量大的类,都用静态类缓存起来(占用内存并不大,可能比以前更省内存,因为不用每次都new 出来好多类和数据流),这样只需在进入欢迎页时,获取一次,以后都从内存区域拿就好,这样所有用到的方法都能得到优化。(当然还有去掉一些根本不需要保存在prefence里的类,只需静态缓存就可以)

  • 优化了progressbar,这家伙也是到处再用到,但之前项目为了酷炫,从github上搞来一个Material Design效果的progressBar,效果虽炫,但是有些情况下却非常卡,看了一下日志才知道,这圈圈一转,后台日志就能看到在疯狂的GC。我看了源码才知道,这家伙,在onDraw()里new Bitmap(),能不耗内存跟cpu吗。后来经过几天的调研和分析,对比了不同的progressbar,最后发现还是用原生的最好(holo风格也不难看),第三方不是内存和cpu占有率过高,就是有些机器不兼容,酷炫效果虽好,但也不能为了效果牺牲太多性能。

  • 把首页之前在首页加载的一些非即时性接口放到了欢迎页加载,以前所有接口都是等到进到首页才调起,请求完所有接口再显示界面,结果可想而知,首页每次都要等个几秒才能看到,调整了一下,效果还是很明显,速度快了很多。

3、 代码规范

相较于前两个优化,这是最难的。前面两个你只要有时间,就可以动手干,但代码规范是需要你整个团队配合,和一套代码审核流程才能做好的事。这种团队协作的事,如果老员工不遵守或者主管没有强力实行,靠我这样一个有代码洁癖的新同事来劝,效果肯定不怎样,大家还会怎么方便怎么来。我只能保证在我完成的所有功能里,做到规范,然后看到一些极不合理的地方,在群里拿出来鞭打一下,好言好语恳求大家以后不要这样,逻辑复杂的地方多点注释。。。(不过最近话事人被我的整洁代码打动了,在会上要求大家以后都照着我的风格来写。PS: 我也没什么风格,谷歌和Java的一些常见规范而已,只是大家都遵守并不易)

4、控件封装

之前说的progrssbar算一个,还有个主要的就是下拉刷新和下拉加载更多控件,因为这个好多地方用到,一个APP里好几种下拉刷新效果显然不是一个靠谱公司该干的事,我github上选了一个还算可以得框架(它是封装了swiperefreshlayout加上下拉加载),自己完善了一下,改进了一些bug,加上了延迟消失加载框功能,现在公司所有需要下拉刷新的地方已经统一成我的这一款,内心还是很欣慰的,毕竟自己的努力一直能得到别人的认可。

针对这篇博客提出的问题说我几点建议

无论代码多烂性能多遭,只要代码能够正常编译,App还能正常运行,在时间充裕的情况下就不是什么事。只是选择优化和重构时需要注意一些点:

  • 最先优化和重写那些最常用的代码,如Android项目里的网络请求部分,几乎是每个界面都会用到的。

  • 如果没有专门一个版本来优化性能,那就先高质量的完成你即将要开发的新功能或者重构好你要维护的就功能。

  • 看不懂的代码先不动,如果有些旧代码实在搞不清楚,老员工也说不出所以然,这样的代码先留着,也可以先用一个wapper方法封印起来,等有足够时间才一句句调试它。

  • 善于利用久项目里留下的那些问题不大的代码,例如之前写的一些工具帮助类,如果没有发现大的性能问题,里面代码写得差一点没关系,这些代码先用着,优化等级可放在最低。

  • 多从架构方面(这需要你有的抽象编程能力)方面入手,具体代码的优化既耗时测试工作量大,一般没有那么多时间可折腾,最有效的方法是搭一个架子,然后具体功能按照你提供的接口往里填参数就可。例如每个Activity,一般都用统一样式TitleBar,你可以将TitleBar封装在BaseActivity里,然后提供一个自定义TitleBar的接口,默认就用你提供的TitleBar,这样大部分TitleBar的代码都是控制在基类里,出不了大问题。

  • 对于像网络请求,下拉刷新控件,图片显示框架这些通用功能,能用原生的尽量使用原生的,没有再考虑第三方框架,使用第三方框架也找那些比较多人使用和作者一直维护的框架,不到万不得已不要自己写,再不济也可以拿来改嘛。另外,一旦你使用了框架,就要熟悉它,作者的wiki的一定是要看的,有时间也要看看源码,不然出问题了很容易找不到北。

最后说点实际的,上面的这些建议都是建立在你的公司愿意在优化代码和性能这上面花时间的情况下才有用,如果只是说说而已,开发时间掐得死死,不留空隙的逼你们开发新功能,完全不考虑性能代码质量,那上面的建议都将作废,以下的建议可能才最有用:

多到100Offer,拉钩,51job,猎聘网,内推网看看。
0 0