V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
pupboss
V2EX  ›  程序员

从重构到吐血 - 我是如何删掉 6 万行代码并且不删减原有功能的

  •  6
     
  •   pupboss ·
    pupboss · 2017-12-10 16:42:44 +08:00 · 10603 次点击
    这是一个创建于 2549 天前的主题,其中的信息可能已经有所发展或是发生改变。

    原文发表在我的博客 近期重构工作的一点收获

    主要重构工作如下

    • 删除没用到的第三方库
    • 删除不合理的第三方库,使用系统自带的或者自己造轮子
    • 删除定义好但是没有用到的变量
    • 删除 import 进来但是没有用到的头文件
    • 删除更旧项目留下来的用不到的逻辑
    • Controller 层不合理的层级结构重构,无用代码清理
    • View 层不合理的结构重构
    • Service 层冗余的写法重构
    • Model 层不合理的写法重构
    • 拆开不合理的耦合
    • 耦合一个类别的模块
    • 修复了多处内存泄露
    • 修复了多处循环引用
    • 优化编译速度
    • 消除项目中的 warning

    关于删除代码,在某个项目里,Pods 文件夹那些第三方库的代码删了 9 万多行(那个目录没有被 git ignore 掉),项目里面删除了大约 4 万行,其中大量代码是该项目之前的项目里面留下来的东西,只不过没人清理。在删了 4 万行之后,程序仍然能完整的跑。

    接下来是做了部分重构,把一些第三方库删掉,自己造轮子,在这个过程中,累计删除了 1.2 万行代码,增加了 1100 行左右。

    整个重构工作下来,编译速度从 2-3 分钟减小到了 40 多秒( 13 寸 2 核心机器),warning 从 70 多减少到了 0,第三方库的数量从 51 个减少到了 13 个,安装包从 22.1M 减小到了 3.7M ,功能反而比之前还要多。

    原文发表在我的博客 近期重构工作的一点收获

    第 1 条附言  ·  2017-12-10 18:11:53 +08:00
    文中没有说清楚啊,这是一个 iOS 项目,哈哈,不少朋友当成是 Golang 了
    80 条回复    2017-12-12 11:07:32 +08:00
    WangYanjie
        1
    WangYanjie  
       2017-12-10 16:45:57 +08:00
    我更好奇,过程中是如何保证重构代码的功能正确性的?
    Rorysky
        2
    Rorysky  
       2017-12-10 16:49:03 +08:00
    看着都好累……
    pupboss
        3
    pupboss  
    OP
       2017-12-10 16:56:16 +08:00
    @WangYanjie 不是很会用单元测试,所以靠的是人肉 debug,其实如果遵循规范的话,比如布局全部用 AutoLayout,基本上不会出问题。测试的过程中发现部分 UI 不对劲,是因为那个 UITableVIew 的 cell,没有用 AutoLayout 算高度。

    功能方面,3.7M 的安装包已经很能说明问题了,一共就 20 多个页面,不是像淘宝那样复杂,重构的过程又是基本相当于重写,一个个页面挨着测过一遍,功能就很正确了,没有很复杂的页面,最多也就是下单页面动态加载用户优惠券这个级别的
    pupboss
        4
    pupboss  
    OP
       2017-12-10 16:57:46 +08:00
    @Rorysky 😂累是一方面,以*万行为单位,删代码的感觉,是真的爽
    pie
        5
    pie  
       2017-12-10 17:00:59 +08:00
    只能说 lz 太强大了
    pupboss
        6
    pupboss  
    OP
       2017-12-10 17:02:40 +08:00   ❤️ 7
    @pie 我想说句政治不正确的话。。。不是我太强大,全靠队友衬托
    Loyalsoldier
        7
    Loyalsoldier  
       2017-12-10 17:16:03 +08:00
    请问博客主题是什么,有开源吗?挺好看的~
    pupboss
        8
    pupboss  
    OP
       2017-12-10 17:22:57 +08:00
    @Loyalsoldier 有的,我是基于 https://github.com/kelyvin/caffeine-theme 修改,因为修改的项目很多,和我自己耦合太强不适合分享,你可以基于他这个再定制你自己的,这是我当初优化的点供参考:[本博客优化点总结]( https://www.pupboss.com/summary-of-my-blog-optimization/)
    firefox12
        9
    firefox12  
       2017-12-10 17:26:14 +08:00 via iPhone   ❤️ 3
    只想说改好了是牛逼 幸运 不成功才是正常。没有设计文档 测试文档 单元测试自动测试 联合测试 层层把关 你怎么敢说自己的重构是成功的呢?
    jpmorn
        10
    jpmorn  
       2017-12-10 17:31:46 +08:00
    删除没用到的第三方库 这点就是 golang 好了 引入了不必要的库,直接编译不通过!!!

    变量未使用,直接编译不通过!!!!

    之前写的时候是一脸懵逼,goland 提示我的时候我还嫌他多事!!!哈哈哈
    RorschachZZZ
        11
    RorschachZZZ  
       2017-12-10 17:34:26 +08:00
    我手上也有一个比较复杂的交易系统。没有单元测试,文档也不是最新的。每改一个地都提心吊胆的。。。
    pupboss
        12
    pupboss  
    OP
       2017-12-10 17:39:33 +08:00
    @firefox12 哈哈,多谢前辈指教,重构的绝大部分还是成功的吧,因为每次重构,都是只针对一个模块,不会说一下把所有东西都重写一遍,再就是可能前辈公司的业务复杂度比较高,就我们这个项目而言,登录 注册 录音 识别 查看商品 下单 收藏,功能还是比较单一的,所以会出问题的地方不多

    @jpmorn Go lang 还有这么个功能,下周我也会去看看哈哈哈哈

    @RorschachZZZ 对的,我在上家公司,页面的业务非常复杂,重构过一个页面,感觉也是提心吊胆,重构完一个页面,有别处又用到这里面一个 View,一般都会出布局错误😂
    forestyuan
        13
    forestyuan  
       2017-12-10 17:40:03 +08:00
    重构过程中引入了多少个 BUG 就只有天知道了
    pupboss
        14
    pupboss  
    OP
       2017-12-10 17:41:25 +08:00
    @forestyuan 重构完之后的上线,肯定会安排大量的测试的嘛,重构也是两个月前的事情了,现在才分享出来,所以根据这期间的 issue 来看,问题不算多,还修复了很多莫名其妙的问题
    hilow
        15
    hilow  
       2017-12-10 18:01:14 +08:00 via Android   ❤️ 1
    看到你的描述,我第一时间想到的也是 golang
    只要是不实用的库或者变量,直接编译失败
    开始感觉很烦,后来感觉很爽
    尤其看到你重构过程删除那么多代码,如果用 golang 做的,肯定会好很多
    WispZhan
        16
    WispZhan  
       2017-12-10 18:22:33 +08:00
    能给时间重构,只能说项目组也算靠谱了。
    WeberXie
        17
    WeberXie  
       2017-12-10 18:24:25 +08:00
    好奇楼主 [Project Officer] 这个工作,可以介绍下吗
    pupboss
        18
    pupboss  
    OP
       2017-12-10 18:25:40 +08:00 via iPhone
    @hilow 不得不说 Golang 这一点真的不错

    @WispZhan 对呀还是不错的,当时也不断有新需求,都被我用重构的借口给他延期了……
    pupboss
        19
    pupboss  
    OP
       2017-12-10 18:26:56 +08:00 via iPhone
    @WeberXie 就是 NTU 在社会上招聘一些人过去做项目,签证上面的 title 是 Researcher
    zj299792458
        20
    zj299792458  
       2017-12-10 18:33:17 +08:00
    这么大的人力投入,没有增加任何新功能,没有提高用户体验,要是我们老大肯定不会允许的😄
    sobigfish
        21
    sobigfish  
       2017-12-10 18:34:38 +08:00
    上线的 app 么?发个 itunes 地址?
    760974873
        22
    760974873  
       2017-12-10 18:52:31 +08:00 via Android
    你的博客访问很快,也好看
    pupboss
        23
    pupboss  
    OP
       2017-12-10 19:03:29 +08:00 via iPhone
    @zj299792458 初创团队嘛,用户量不大,灵活度方面比较有优势

    @sobigfish 我没找到分享的链接,商店搜 HEY!Shake 吧,这个 app 曾经到过新加坡区商务榜第一的哈哈,你下载了应该用不了,app 做的是声音识别方面,需要特定的音频才能实现功能

    @760974873 谢谢谢谢
    likuku
        24
    likuku  
       2017-12-10 19:06:19 +08:00
    [不是很会用单元测试,所以靠的是人肉 debug].... 刚开始学用单元测试的野生 pyer 表示 up 主耐力超凡,技艺超群...

    用起 单元测试,马上发现自己写的代码真是超级渣,重构的动力爆棚。
    pupboss
        25
    pupboss  
    OP
       2017-12-10 19:32:30 +08:00
    @likuku 单元测试这么强大吗😳我也去学一下,多谢🙏
    asj
        26
    asj  
       2017-12-10 19:55:36 +08:00
    删代码比写代码爽多了
    missdeer
        27
    missdeer  
       2017-12-10 19:57:24 +08:00
    没看 append 之前我以为是 Java 项目,哈哈
    onikage
        28
    onikage  
       2017-12-10 20:32:34 +08:00
    我们之前的项目也是类似, 现在重构后体积只有之前的一半.
    虽然业务不是很复杂, 代码量不多. 但是之前的一位大神写出了理论仅能支持 1 路并发的新高度.
    这项目现在我在帮擦屁股...
    pupboss
        29
    pupboss  
    OP
       2017-12-10 20:38:14 +08:00
    @asj

    @missdeer 哈哈,主要是现在项目差不多都是这么个层级结构,MVC

    @onikage 一路并发😂重构大法好,重构完按照新的结构来写,当然也不排除其他大神继续走以前的老路
    rails3
        30
    rails3  
       2017-12-10 20:44:03 +08:00 via Android
    大神
    vagranth
        31
    vagranth  
       2017-12-10 20:45:57 +08:00
    最近也在做类似的重构工作,5w 多行代码,我估计 2k 行能搞定。
    真是无法想象之前的代码是怎么写成那样的。
    carlclone
        32
    carlclone  
       2017-12-10 20:59:21 +08:00 via Android
    没单元测试真的敢保证正常啊
    pupboss
        33
    pupboss  
    OP
       2017-12-10 21:30:40 +08:00
    @rails3 哪里哪里,都是被逼的,不然谁愿意重构代码😂

    @vagranth 可能不是人人写代码都有洁癖吧。。。

    @carlclone 已经很多前辈提到过单元测试了,这个真得研究下怎么用,多谢🙏
    blless
        34
    blless  
       2017-12-10 21:46:11 +08:00
    我也重构过别的组的代码,看他们的代码能让我气得冒烟。。语言的特性不会用,代码乱七八糟 除了强制划分\写好的模块 其他都是写到哪放到哪 写好的基础库根本就不用。根本不懂正确处理内部错误跟逻辑校验错误。。
    akring
        35
    akring  
       2017-12-10 21:58:25 +08:00
    讲真,现在没有单元测试我一般都不敢动
    Jverson
        36
    Jverson  
       2017-12-10 22:17:11 +08:00
    @RorschachZZZ 我比你更惨,手上的购物系统我一个人在维护,用的老框架,代码都是六七年前的,关键是本地还跑不起来,产品还不断的加需求,我觉得我离离职不远了🤣
    jhdxr
        37
    jhdxr  
       2017-12-10 22:45:57 +08:00
    咦?也是 SCSE 的?你在哪个 lab ?但为什么你会从 RA 变成 Project Officer 的,这不是降了一级么。。。
    jhdxr
        38
    jhdxr  
       2017-12-10 22:50:44 +08:00
    好吧搜到了,我在你的正上方的 lab _(:з」∠)_
    cabing
        39
    cabing  
       2017-12-10 22:56:39 +08:00
    没有单元测试,一点都不敢动~~
    pupboss
        40
    pupboss  
    OP
       2017-12-10 23:04:25 +08:00 via iPhone
    @blless 语言特性不去用……基础组件不去用……全中,定期开分享会,严格 code review,应该能有点作用

    @akring @cabing 我们做 iOS 的可能还好点😂页面能跑通,UI 不错位,就算测试通过了
    pupboss
        41
    pupboss  
    OP
       2017-12-10 23:07:06 +08:00 via iPhone
    @jhdxr 哇这么能遇到,师兄好,系统里登记的我是在 DMAL,实际上一般都在 Innovation Center
    pupboss
        42
    pupboss  
    OP
       2017-12-10 23:08:52 +08:00 via iPhone
    @jhdxr RA 是当时用交换生身份过来的,PO 是毕业之后转的,其实从待遇上看不是降级😂
    oswuhan
        43
    oswuhan  
       2017-12-10 23:19:18 +08:00
    @forestyuan 哈哈
    cnTangLang
        44
    cnTangLang  
       2017-12-10 23:25:23 +08:00 via Android
    重构最痛苦的,不一定是程序员,极大可能是测试。
    pupboss
        45
    pupboss  
    OP
       2017-12-10 23:32:01 +08:00 via iPhone
    @cnTangLang 我们公司没测试,我自己就是测试😷
    beimenjun
        46
    beimenjun  
       2017-12-10 23:41:06 +08:00
    其实 YYText 应该还是蛮稳定的,如果有大量 Crash,必须认真查下根本原因了。
    z1s23
        47
    z1s23  
       2017-12-10 23:51:45 +08:00
    请问楼主是忙里偷闲来进行重构的吗?
    以前做项目,进度很赶,感觉都没时间做代码重构,但是觉得这个重构还蛮有必要!
    pupboss
        48
    pupboss  
    OP
       2017-12-11 00:13:21 +08:00
    @beimenjun 正文里好像有点诋毁 YYText 了,我不是这个意思啊希望不要误会,当时的情况是活动现场几千人下载,Fabric 统计到了 iOS9 设备上面百分之百 crash,调用栈是 YYText 有一个函数,可能是旧系统不兼容,因为那个功能本来就是打算用 attributedStringWithAttachment 写的,就没细查 YYText 的具体原因,我给 YYText 的作者道个歉,写博客的时候没想那么多
    pupboss
        49
    pupboss  
    OP
       2017-12-11 00:15:17 +08:00
    @zs8861 忙里偷闲也有,然后就是把产品提出来的需求 delay 了😂借口就是不重构完成,新需求没法开发。因为我们是初创团队,用户数量等同于没有,这些方面比较好协商
    likuku
        50
    likuku  
       2017-12-11 00:28:40 +08:00   ❤️ 1
    @pupboss 是的,当用上单元测试后,才发觉之前一遍一遍自己手工肉测实在太傻...

    简单举个例子,使用某语言自带 /第三方提供 单元测试库 /框架 来单独写一个 /一组专用的测试程序,

    里面可以写测试用函数 /方法 /类 ,它们再去引用 /调用 你正式代码 /dev 分支代码 里各个功能函数 /方法 ,自己设定给的运行参数等等,还有预计 /设计好的运行结果,让单元测试程序自己比对运行结果是否符合设计,最后给出运行结果(是否通过测试 /报错)
    pupboss
        51
    pupboss  
    OP
       2017-12-11 08:58:00 +08:00 via iPhone
    @likuku 原来如此,受教了😀
    ljsh0102
        52
    ljsh0102  
       2017-12-11 09:20:07 +08:00
    牛逼
    dangge
        53
    dangge  
       2017-12-11 09:22:00 +08:00
    比如布局全部用 AutoLayout,基本上不会出问题。

    曾经的安卓开发表示羡慕。。。
    qsnow6
        54
    qsnow6  
       2017-12-11 09:34:01 +08:00
    @likuku 这不是 unittest 吗
    pupboss
        55
    pupboss  
    OP
       2017-12-11 09:41:56 +08:00
    @qsnow6 客户端开发应该还要集成 UITest 的,这个也要好好研究下了

    @dangge 在 AutoLayout 出来之前我是很羡慕安卓开发者的。。。可以很方便的适配各种尺寸的安卓手机
    eddiechen
        56
    eddiechen  
       2017-12-11 09:46:33 +08:00
    warnings 为 0 是怎么做到的,一些第三方库自带大量 warnings,特别 xcode 版本升级后
    mritd
        57
    mritd  
       2017-12-11 09:48:12 +08:00 via iPhone
    日常月经贴

    看我如何 xxxx
    我是如何 xxxx
    对 xxxx 怎么看
    fenglangjuxu
        58
    fenglangjuxu  
       2017-12-11 09:57:07 +08:00
    我也遇到过这种情况,代码用的都是别人的项目给改的,然后一堆遗留,好多没用的都在,强迫症看着就不舒服.
    xrlin
        59
    xrlin  
       2017-12-11 10:00:09 +08:00 via iPhone
    服务端代码,没有完善的单元测试根本不敢大规模重构 T_T
    HelloiWorld
        60
    HelloiWorld  
       2017-12-11 10:02:36 +08:00
    import 这种深度耦合是真的烦,一层一层的引用,想明白用途的时候发现很多都没用到,处理起来也特麻烦,至今项目里也有这么一些类懒得动,简单处理过一次也就少了几 M,然后在一次又一次的迭代中又加回来了(主要是偷懒用 sb 和 xib 画的界面,相对是比纯代码大一点)
    pupboss
        61
    pupboss  
    OP
       2017-12-11 10:03:18 +08:00
    @eddiechen 这个文章记录的是两个月以前的重构,那个时候 Xcode 还没升级呢,目前的那些 block void 检查,我是把能删掉的库都删掉,删不掉的只好留着 warning 了,MJExtension 引入进来的比较多,其他的一共在 3 个左右,一些小的年久失修的库我会把他的源码直接放到项目里,不用 Pod
    pupboss
        62
    pupboss  
    OP
       2017-12-11 10:04:41 +08:00
    @mritd 不要这么拆穿嘛,就是想蹭个热度
    HelloiWorld
        63
    HelloiWorld  
       2017-12-11 10:05:41 +08:00
    顺便使用 LSUnusedResources 项目清除了 无用的图片资源,个人感觉整个项目清爽了不少(其实是更贴合了自己的开发习惯 😄)
    pupboss
        64
    pupboss  
    OP
       2017-12-11 10:07:50 +08:00
    @fenglangjuxu 大公司的还是不要重构了😂我之前在扇贝单词,有些旧代码也很不友好,但是看了看我放弃了重构。这个项目很小,所以重构起来,勉强能搞定

    @xrlin 对的....我也做过一点点后端的开发,改起来心惊胆战的,贼鸡儿刺激

    @HelloiWorld 握爪。。从重构到放弃
    cnanyi
        65
    cnanyi  
       2017-12-11 10:08:34 +08:00
    曾经在上家公司重构过一个软件的后台, 大概删除了 80%的代码, 并不影响使用, 被删掉的部分是主要是产品经理为了软件的前瞻性设计的功能, 大部分是开发了一半逻辑走不通就不管了, 还有一部分是为了让后台操作界面更炫而设计的样式和动画, 运营同事经常在操作数据时要各种等待界面渲染完成而抱怨系统太慢, 能不能优化, 有时也因为在复杂的菜单项目找到一个功能入口而头疼。
    后来我终于离开了
    eddiechen
        66
    eddiechen  
       2017-12-11 10:14:32 +08:00
    好吧,看来 pod 引入 warnings 这个还是没啥好办法解决
    SunnyCoffee
        67
    SunnyCoffee  
       2017-12-11 10:16:32 +08:00
    我手头也有这样的一个项目,之前是外包做的。没算第三方库,删了也差不多有 1w 行代码了
    pupboss
        68
    pupboss  
    OP
       2017-12-11 10:18:09 +08:00
    @HelloiWorld 这个肯定要做的,哈哈

    @cnanyi 其实我们也有这类代码。。。开发的时候以为用得上,结果写完没集成进去。大的项目无力回天,还是离开比较好😂

    @eddiechen 我试过 Pods 提供的一些和 warning 相关的设置,都没用,或许我们可以给开源库提 PR 来修复这个,强迫症看见警告确实不能忍
    pupboss
        69
    pupboss  
    OP
       2017-12-11 10:41:21 +08:00
    @SunnyCoffee 都有一个共性,就是之前更早项目的代码,不管用不用得上,先拖进去再说
    hujianxin
        70
    hujianxin  
       2017-12-11 10:47:28 +08:00
    厉害了!!
    RubyJack
        71
    RubyJack  
       2017-12-11 11:04:26 +08:00
    重构先写测试...
    hantsy
        72
    hantsy  
       2017-12-11 11:13:00 +08:00
    @likuku 非常欣慰,能够看到一些写测试的同学。

    可惜我工作十几年,国内没遇到一个公司硬性要求测试。

    几年前还在最后一家不小的公司上班时,曾经想全公司推广单元测试,结果遇到开发人员一致反对,公司决策层不得不放弃。大部分公司还是习惯人肉 Debug,然后天天和测试组扯皮,或者一个人提交代码把所有人的功能都捅破了,然后全公司加班去修复,还在埋怨公司没人性。

    还好离开公司后,现在 Freelancing,写测试已经成为习惯。不写测试的项目不会参与,不写测试的团队不会加入,实在没法忍受烂泥一样没测试的代码。
    assad
        73
    assad  
       2017-12-11 12:05:39 +08:00
    6 万行有多少是复制粘贴出来的?
    pupboss
        74
    pupboss  
    OP
       2017-12-11 12:31:47 +08:00 via iPhone
    @RubyJack @hantsy 多谢指教,单元测试是必不可少的

    @assad 复制的代码是一部分,更多的是更旧项目留下来的用不到的,直接放到项目里的库,和代码文件
    RubyJack
        75
    RubyJack  
       2017-12-11 12:58:35 +08:00
    @hantsy @likuku @pupboss ,我也是重构我司 Rails 写的后端服务到吐血,不过自从看完了《重构》,掌握一些套路就轻松很多了
    hantsy
        76
    hantsy  
       2017-12-11 15:17:04 +08:00   ❤️ 1
    @RubyJack Refactoring,Junit in action (第一版) 我很早就买了。
    @pupboss 看了上面很多认为重构是为了清理遗留项目。

    其实对于新开发的项目而言,重构也应该贯穿整个项目开发过程。新项目架构应该一般认为不会被技术债务所困扰,但 API 设计一开始要做到尽善尽美很难,不断完善的过程也需要不断的重构代码。在每个 Sprint 中应该清理掉哪些无用的代码,对于一些业务重新实现代替了某些已有代码,标记(@Deprecated )提示调用方(其他开发人员)他们在将来会被删除,并可以使用新的方法替代。
    pupboss
        77
    pupboss  
    OP
       2017-12-11 16:23:43 +08:00
    @hantsy Deprecated 这点确实很有用,目前我们还都是一刀切,多谢您的见解
    minininja
        78
    minininja  
       2017-12-11 18:15:21 +08:00
    听说重构都是大神才能干的活,摩拜楼主。
    sagaxu
        79
    sagaxu  
       2017-12-11 18:23:38 +08:00
    之前把一个后端项目从 Java 重构到了 Kotlin,删除了一半以上代码,性能还 double 了一下。还好不是动态类型语言,重构会死人的
    v2ewonder
        80
    v2ewonder  
       2017-12-12 11:07:32 +08:00
    之前,同事离职了,接手了他的项目。
    代码那个恶心啊,然后我吐槽了。那位同事来了一句:删了重写啊。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3611 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 04:40 · PVG 12:40 · LAX 20:40 · JFK 23:40
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.