热门搜索 :
考研考公
您的当前位置:首页正文

如何快速阅读老项目,并且完成维护和少量迭代任务

来源:东饰资讯网

如何快速阅读老项目,并且完成维护和少量迭代任务

前言

本人有幸参与一个生命周期以长达10年老项目的维护,并完成部分业务逻辑的重构,在这个过程中大大提高了自身阅读代码的能力。先说说所面对的问题

  1. 年代久远,中间经过了无数的人手,很多问题无法追溯
  2. 架构老化各种MRC,古老的API,以及非人类的架构设计
  3. 臃肿的代码,没有人能够真正的理解整个项目的运行机制,核心基类已达10000多行代码
  4. 没有文档,技术文档,测试文档什么的都没有,大部分已经失效了,有相当于没有

先整体后局部

其实当我拿到这份源代码的时候,内心是崩溃的,一种无从下手的感觉。没办法还是要硬着头皮干, 首先从APPDelegate 开始, 你们见识过一个AppDelegate超过1000行吗, didFinishLaunchingWithOptions 加载了十几个Services, 面对这种情况,就要多从整体上入手,先忽视具体细节,不要一行一行的阅读代码啦,从命名以及某些特征代码,判断具体某个Service是干什么的的。 经过上述操作大概得到类似的清单:

  • PushNotificationUtility: 推送消息工具(存储deviceToken, 配置远程推送信息,感觉不应该放在这个类里面,DataServices 没有对该类进行任何维护管理的操作)

  • WebtrendsService: 用户数据统计相关的

  • AppDynamics: 监控用户行为的工具类

  • AutoLogoffService: 日志开关

  • DataCacheUtility:存储一些全局参数,谁都可以存,谁都可以取,关键子没有详细的配置文件非常混乱

  • SoftTokenService: softTokenService:待了解 不知道干啥用的

.........

对各种Service 形成初步印象,做什么用,可能存在什么问题, 对于那些作用存疑先暂时打上标记

找到关键入口

不管didFinishLaunchingWithOptions怎么复杂,最终还是要进入ViewController的,这个时候需要弄明白什么时候会进入正常页面流程,什么时候进入异常页面流程。这里有一个拐点

  • 什么时候所有Services 加载完成,完成APP环境检测

一旦完成APP环境检测,通常就会加载UI了,找出关键代码,并总结形成流程图


UI入口.png

快速定位页面

如果你需要了解一个具体的页面,甚至修改,如何从茫茫文件中,快速定位到该页面?
借助Xcode自带工具Debug View hierarchy, 定位到该页面并且对整个UI层级有个初步了解。
[图片上传失败...(image-7668de-1539856111956)]


Debug View hierarchy.png

多做记录

有的时候你可能当时理解该流程,过段时间可能就忘了,或者变得不清晰了。这个时候保持良好的书写文档方式,能够避免重复的劳动。

  • 摘抄部分关键入口代码
  • 对于逻辑复杂的地方,截取关键的堆栈信息
  • 保存必要的网路日志
  • 建立UML 类图时序图流程图等,整体上理解APP结构
UI类图 预登录堆栈信息.png

如何修改

  1. 非必要不引入第三方库,本来就是一台拖拉机了,你还在上面加东西,就不怕他散架吗,尽量使用原生API开发功能,可以基于项目需要自己开发一些工具类,够用就好不需要像开源框架那么强大和全面的功能
  2. 慎重优化代码,因为你一旦改动可能会引发新的Bug,而测试人员根本就发现不了,因为他根本没法侧。有些代码里面可能看似没有用,却有可能是其他模块正常工作的必要条件。所以不要想当然去优化一些代码,除非你已经彻底搞清楚了该段代码的逻辑
  3. 对于修改的代码添加必须追加注释, 谁改的,什么时候改的,为什么要改,修改的代码从哪个位置开始到哪个位置结束,原来的代码逻辑是什么,这么做的原因在于使问题变得可追溯,一旦遇到问题可以快速定位是历史遗留问题,还是新代码所带来的问题。
    类似这样:
   //Bug Fix #1494.EULA issue Start: by Emmy Xiao on 10/08/2014
  //Description: French EULA should not be displayed if customer has accepted an English EULA previously
  [[ControllerManager getDataServices].regionDataSource checkUpdateEulaAcceptLanguage];
  //Bug Fix #1494.EULA issue End: by Emmy Xiao on 10/08/2014

主题,描述,code

  1. 对文件夹的管理, 通常情况我们都是按照功能模块,管理不同的文件。但是对于老项目的话,我们可以建立一个新的文件夹,用于存放新增的文件,达到新老文件分离的目标。 新增的文件可以考虑加个特殊标识符。

形成文档

  • 对于你要修改的部分,在理解完毕之后, 完成文档整理
  • 对新功能的设计,也要形成文档。

这样做的话,首先对原逻辑整理文档有利于加速你的理解, 同时也为自己的设计提供参考,更便于以后的维护。

networkQueue.png

这是一个原来网络底层实现时序图,可以看出逻辑非常的复杂,后来我直接设计了一个新的。
使得无论从使用上和实现上都变得无比简洁。

[[CHELoginSingleRequest shareInstance] getSaaS30MobileRequest:api completion:completion];

之前的API是这样的


    BOOL connectFlag = [self.dataConnection createHTTPFormProxyConnectionWithDictionary:urlWithAddressString
                                                                            requestDict:requestParams
                                                                          requestMethod:@"GET"
                                                                                timeout:http_con_default_timeout
                                                                         needHSBCHeader:NO];
                                                                         

回调是这样的。

-(void) receiveResponse:(NSData *)receiveData connectId:(NSString *)connectId
{
 ....
}

总结

任何一个APP都可以分层为UI层,网络层,数据层
网络层和数据层可以归结为: 数据从哪里来,又从哪里去
UI层: 可以描述为 事件从哪里开始,又从哪里结束。

UI 是一条明线, 数据是一条暗线。

通常我们要做的不是理解所有的代码和具体的实现细节,而是试图理解关键的流程,以及你改动时候涉及的一部分代码实现细节, 更多的是从整体上去理解它。就像看书一样有略读和细节,先略读得到整本书初步轮廓,然后再细读你需要深入理解的地方。

Top