V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
mitu9527
V2EX  ›  程序员

对于重构有几个疑问,希望能过来人能解答一下!

  •  
  •   mitu9527 · 2020-05-05 21:56:47 +08:00 · 4107 次点击
    这是一个创建于 1689 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我最近在读《重构:改善既有代码的设计》这本书,马上就看完了。对于重构的思想我是非常认同的,但是对于这些重构手法的落实却有一个疑问。

    作者介绍了 60 多种重构手法,每种重构手法都配有非常具体的、标准的、安全的重构步骤。那些重构手法的动机我基本上都能理解,也知道最终代码大概会重构成什么样子,但是那些重构手法的具体步骤我是真的没记住几个。虽然作者自己也说,他平时开发中也不会完全参照这些步骤,只有重构出了问题时,才会按照这些步骤进行。但我还是有几个疑问,想问问大家:
    
    1.大家能记住那些重构手法的具体步骤么,还是说重构多了就会自然而然的记住了?
    2.大家进行重构时,会参照这些具体步骤么,还是按自己的想法来?如果会的话,相似到什么程度呢?
    
    35 条回复    2020-05-07 15:51:27 +08:00
    lhx2008
        1
    lhx2008  
       2020-05-05 22:02:56 +08:00 via Android
    没有看过这本,我理解的话,首先是要保证旧代码的的测试用例完善,然后是按高内聚,低耦合的思想重新划分功能类,拆掉或者组装一些现有代码。识别新增的扩展点,运用一些常见的设计模式来提高代码的扩展性(开闭原则)。
    xuanbg
        2
    xuanbg  
       2020-05-05 22:41:22 +08:00   ❤️ 1
    看过这本书,很赞同作者的理念和方法。但具体的真的是一点都没记住。反正我重构就一招,原先的不动,新项目慢慢替换老项目。也许能替换完,老项目下线,也许不能替换完。但那又怎样,反正我看不见的屎就不存在。。。
    mitu9527
        3
    mitu9527  
    OP
       2020-05-05 22:49:20 +08:00
    @xuanbg 看样子不止我一个人这样,安心了!我感觉没有多少人能做到照着作者介绍的步骤去重构的。
    yesterdaysun
        4
    yesterdaysun  
       2020-05-05 22:53:52 +08:00
    我的理解就是重构是需要反复刻意练习的, 就是有的时候对着一段代码刻意的练习怎么重构的更好, 练多了, 平时自然而然就能用上, 忘了是哪本书提到的概念了, 代码的坏味道 code smell, 当你能意识到一些坏味道的时候, 如果之前有练过相应的重构方法, 自然就能用上.

    具体的话还是用 IDE 现成的重构工具, 比如 IDEA 的全套工具, 基本上改名, 提取方法之类的最常用, 其他的多少也会用到, 但是全用到也不太现实.

    但是上面有人提到的测试也很重要, 能保证重构的时候即使步子大一点, 也能确保功能没有被破坏掉.

    可以找一些讲 TDD 的资料看看, 那里重构应该用的挺多的, 但是可以先不管 TDD, 那个确实还是有点难的
    mitu9527
        5
    mitu9527  
    OP
       2020-05-05 23:02:12 +08:00
    @yesterdaysun 我们两个想法大体类似,看样子我还没跑偏。昨天刚看完 Kent Beck 写的 TDD 的书,如果把写代码比作练九阳真经,那么我们平时都是郭靖,正着练; TDD 就要求我们变成欧阳锋,要倒着练。TDD 该了解的我都了解了,不过实践起来确实有难度,完成这种思维转变需要还一些时间。
    52coder
        6
    52coder  
       2020-05-05 23:49:53 +08:00
    这本书断断续续看了一年多,有的方法看的时候会产生共鸣,有的可能没有实际操作过,虽然明白作者目的,但感触不深。
    vitoliu
        7
    vitoliu  
       2020-05-06 00:13:20 +08:00
    小改动直接替换,大改动 facade+开关
    hangszhang
        8
    hangszhang  
       2020-05-06 08:32:56 +08:00
    这本书太屌了,但是我看我就忘记了...
    watzds
        9
    watzds  
       2020-05-06 09:00:48 +08:00 via Android
    不能说全记住,还是能用到不少
    mitu9527
        10
    mitu9527  
    OP
       2020-05-06 09:05:49 +08:00
    @hangszhang 嗯,看完之后感觉自己提升不少 @watzds 手法比较容易记住,或者说即使记不住名字其实也在用这些手法,我主要是感觉我自己在执行某项重构手法的时候是肯定不会参考作者的那些具体步骤的,这些具体步骤是真记不住。
    ligiggy
        11
    ligiggy  
       2020-05-06 09:26:31 +08:00 via iPhone
    做笔记,当工具书。这是作者开头就强调了的,没仔细看哦,哈哈哈。
    mitu9527
        12
    mitu9527  
    OP
       2020-05-06 09:33:32 +08:00
    @ligiggy 确实,我也是打算当做工具书来用了。
    ligiggy
        13
    ligiggy  
       2020-05-06 09:40:22 +08:00
    @mitu9527 毕竟是工具书嘛,翻多了,就像单词一样的,印在自己的脑子里,形成了自己的理解。PS:这本书的价值确实很高,我看的 Java 的,后面好像改成了 JS,有机会要多买几本收藏。
    mitu9527
        14
    mitu9527  
    OP
       2020-05-06 09:54:53 +08:00
    @mitu9527 我看的就是第二版,示例都是 js 的。虽然我没看过第一版,但我个人觉得示例用 js 真不如用 java 合适。不过还是可以考虑收藏一本。
    mitu9527
        15
    mitu9527  
    OP
       2020-05-06 09:55:34 +08:00
    @ligiggy 我看的就是第二版,示例都是 js 的。虽然我没看过第一版,但我个人觉得示例用 js 真不如用 java 合适。不过还是可以考虑收藏一本。
    wu67
        16
    wu67  
       2020-05-06 10:05:54 +08:00
    你只要记住一个原则就好了. 代码是写给人来阅读的, 偶尔才给机器跑一跑.
    wu67
        17
    wu67  
       2020-05-06 10:07:15 +08:00
    你可以尝试把一段代码介绍给小黄鸭, 如果你觉得某种写法小黄鸭可能理解不了, 或者会造成歧义, 那就需要重构, 或者需要添加注释说明
    ayase252
        18
    ayase252  
       2020-05-06 10:09:21 +08:00 via iPhone   ❤️ 1
    保证测试用例完善和小步 commit 怎么重构都不会坏。实在搞不定了可以翻书。
    mitu9527
        19
    mitu9527  
    OP
       2020-05-06 10:16:52 +08:00
    @ayase252 嗯,我也是这么想的,就算不按标准的步骤重构,大多数情况下也能以自己习惯的步骤搞定。就像 Kent Beck 说的,重构步骤选多大要看你自己的能力,还有就是出问题时要有能切换道更小的步骤的能力,这时就得参考这些工具书了。
    asj
        20
    asj  
       2020-05-06 11:21:26 +08:00
    做到构重的一第点,是看当前到的码代是什么。我们往往惯习于看到的是它应是该什么,而它非实际是么什。
    就像这句两话,有很的多序顺错误。但我们脑的子照按它该的应样子去组重了。这对于机器是行不通的。
    重构的起点就是看到现在现实的代码是什么,从中发现改变为另一种现实的可能性。
    而不是按照脑子里代码现在“应该是”的样子,去做些修改以期它变成另一种“应该是”的样子。
    重构中所有的小步骤都是为了修改不脱离现实的代码。
    “应该是”和现实的代码脱节的一个标志就是 debug,debug 相当于让机器帮程序员读代码。破除修改中由于错觉引入的错误。
    evilic
        21
    evilic  
       2020-05-06 12:33:15 +08:00
    不过早的重构。

    这是我一直对重构的看法……
    sumarker
        22
    sumarker  
       2020-05-06 13:00:30 +08:00
    《重构》这本书据说很厉害,所以买了,但是一直没看。
    关于重构,其实我蛮同意楼上等观点
    @evilic 经历过的几个公司也都是 “项目出现了一些问题才考虑重构的”
    一方面是考虑到成本(时间 /人工)
    另一方面也是考虑到,代码可能已经经历了不知多少人到修改,一些历史功能连文献都缺失了,重构可能会导致现在已经上线运行都项目不可用。
    所以,宁愿选择“重写” 也不去“重构”
    dany813
        23
    dany813  
       2020-05-06 13:07:20 +08:00   ❤️ 1
    重构的前提是知道以前的逻辑,接受老项目不知道逻辑的,想重构,不如重写
    mitu9527
        24
    mitu9527  
    OP
       2020-05-06 14:57:54 +08:00
    @evilic 当然,如果代码工作的好好的,而需求又没变化,当然不需要重构。不过现实中,更常见的是重构不足甚至是从来没有重构,重构过多还是比较少见的。
    mitu9527
        25
    mitu9527  
    OP
       2020-05-06 15:03:09 +08:00
    @sumarker 不是我炫技哈,从你留言里面的一些回复来看,你确实还不了解重构。你可以先去看一下《重构》的第二章,希望能帮到你。
    mitu9527
        26
    mitu9527  
    OP
       2020-05-06 15:11:06 +08:00
    @dany813 那要看老项目的质量如何了,如果能满足重构的前置条件,就可以重构。当然,现实中确实大多数项目做得都乱七八糟,连测试都砍掉了,当然也就不能进行重构了。
    taaaang
        27
    taaaang  
       2020-05-06 16:23:38 +08:00
    步骤只是让你有一个清晰的思路,如果你对代码足够熟悉,你的编码能力足够好,直接跳过细节到结果也当然是可以的。自信点,老弟。
    mitu9527
        28
    mitu9527  
    OP
       2020-05-06 16:42:45 +08:00
    @taaaang 因为刚看完重构,还没实践过,所以没信心,担心就我自己是这样。听你这么一说就放心了,谢了!
    liununu
        29
    liununu  
       2020-05-06 16:52:52 +08:00
    重构是可以随时进行和停止的。
    大型重构想要一步到位太难了,想套书里的手法也是比较麻烦的,可以先解决一些简单的 Code Smell,一步步来化简问题。
    312ybj
        30
    312ybj  
       2020-05-06 17:57:26 +08:00
    目前正在重构同事的代码, 主要是更改逻辑,优化速度, 还有不规范的语法。
    感觉就是这个代码健壮性太低,可读性太低, 问题客户要抓紧要,不能自己重写,只能重构。
    这本书我只看了一点, 主要是改代码的时间居多,
    我现在的做法是:
    1. 不改变原有功能完整性
    不改变软件可观察行为的前提下改善其内部结构
    首先保持代码功能的有效性
    确保代码功能没有变化的情况下再进行重构

    2. stop over-engineering
    停止过度工程
    实用代码为主,代码得能跑起来业务

    书中的方法论是
    在脑子里记录 “坏味道” 与 “重构方法”的对应表,就是改的多了,自己就熟了。
    等功能改得差不多了,我再优化下细节,能抽成函数的抽成函数,毕竟 idea 重构功能挺多的
    jones2000
        31
    jones2000  
       2020-05-07 00:59:02 +08:00   ❤️ 1
    重构最最重要的 1 件事就是要写单元测试, 否则你重构的越多,可能出现 bug 的机率也最大, 如果你们老板给你们的配置是 1 个开发配 2 个外包的自动化测试的人员,那这个重构是轻松的。 否则要很小心, 可能会把好的功能改坏了。尤其的底层的重构,这些模块可能其他业务部门也用了。 如果没有完整的单元测试和整体的功能测试,就算改完了, 上线都是提心吊胆的。
    javaWeber
        32
    javaWeber  
       2020-05-07 10:32:04 +08:00
    我就只是把超过 100 行的方法抽取成多个方法,方法参数太多的就抽取成对象,然后把类的变量名改成好理解的。

    其他的,好像都没怎么用到啊。。
    johnsona
        33
    johnsona  
       2020-05-07 11:05:45 +08:00
    @wu67 小黄鸭调试法
    namelosw
        34
    namelosw  
       2020-05-07 14:20:35 +08:00
    这本书是之前同事翻译的,我司常年聊这种话题,也做过挺多培训,还做过很多重构的项目。其实有两种不同的看法都有:

    1. 一种是掌握思想就好,目的是如果你想加功能,发现可能需要调整设计,那么可以先重构,让后面的设计可以自然地加进来。

    2. 另外一种看法是需要掌握所有的 code smell 和重构方法,目的是如果重构大型项目(我司之前有很多重构遗留代码库的项目)很多时候测试不足或者太烂没法测试,这些重构方法有相当一部分是比较安全的( IDE 不红,绝大多数情况等价)。所以按照书上背熟可以直接无脑批量重构,即使是代码特别烂或者混淆过全是 ABC,不理解代码不看业务也可能开始重构,在过程中翻来覆去地调整,调整的过程中理解业务和各种坑,最后达到一个不错的状态。Kent Beck 之前还设想搞一个全结构化的编辑器,只允许重构,不允许手敲代码,听起来有点像 Paredit 的 Java 版。

    有时候某些持第二种看法的同事会认为第一种看法根本就不是重构,而是重写。这个见仁见智,大家各取所需。


    另外重构的核心是发现一个 code smell 开始,消灭一个 code smell 结束,这样的好处:
    1. 随时可以停,没时间继续重构就赶紧赶功能
    2. 避免漫无目的瞎重构,开始和截止都很清晰
    3. 避免一边加功能一边重构,不然 commit 也乱,也经常把功能搞坏
    4. 重构完发现还有 code smell 可以继续这个循环消除下一个,一般来说刚开始重构经常可以消灭 code smell,或者以多换少,到后面可能就只能变成一个 code smell 换另外一个,或者更差,这时候就可以考虑结束了。


    对于帖子里的“我感觉没有多少人能做到照着作者介绍的步骤去重构的。”
    这个其实没那么难,看好了步骤,去 Intellij 里面对号入座,其实 Intellij 的重构功能大多直接照着这本书写的。所以不用记步骤,只用记你需要啥,按个快捷键填空就行了。有的时候需要多步组合起来的重构的可能需要记下,或者用几次就熟了。


    对于“不过早的重构”。
    一般重构的粒度很小,做每个小功能的时候可以中间可能穿插几个重构循环,一般小的可能就几分钟。做某个功能,最熟悉的时候是比较好的时机,毕竟过一段时间陌生了重构效率反而不高。这个也是作者说“不要告诉经理”的原因,因为这样重构就是开发的一部分,所以没必要专门和他们说了。


    对于“这本书太屌了”
    这本书比较朴实,不用太捧,跟 CLRS 之类的书不是一个高度的。也有一些缺点,或者这个重构话题本身就不能覆盖的东西。

    比如新版的 JS 重构,很多代码风格就有点过时,里面虽然一笔带过函数式编程,但是内容里并没有。重构只能改善已有设计,并不能突破出革命性的设计,所以 React 这种现代设计是不能从旧代码中重构出来的。

    还有就是书里面一个缺点是对怎么写测试语焉不详,实践里重构只能用大粒度测试,因为如果你要重构的模块变化,针对这个模块本身的测试重构的时候需要被改的话,这个测试对重构就没意义了(因为你重构的时候正好重写了这个测试你也不知道是不是跟以前一样)。所以一般推荐针对行为和业务的大粒度测试,或者至少比你打算重构的范围要大。
    mitu9527
        35
    mitu9527  
    OP
       2020-05-07 15:51:27 +08:00
    @namelosw 受教了,谢谢!
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1279 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 17:57 · PVG 01:57 · LAX 09:57 · JFK 12:57
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.