CH02_重构的原则(什么是重构、为什么重构、何时重构)

这篇具有很好参考价值的文章主要介绍了CH02_重构的原则(什么是重构、为什么重构、何时重构)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

什么是重构

重构(名词):对软件内部结构的一种调整,目的是在不改变软件可观察行为的前提下,提高其可理解性,降低其修改成本。

重构(动词):使用一系列重构手法,在不改变软件可观察行为的前提下,调整其结构。

重构的关键在于运用大量微小且保持软件行为的步骤,一步步达成大规模的修改。每个单独的重构要么很小,要么由若干小步骤组合而成。

可观察行为:整体而言,经过重构之后的代码所做的事应该与重构之前大致一样。

重构与性能优化有很多相似之处:两者都需要修改代码,并且两者都不会改变程序的整体功能。两者的差别在于其目的:重构是为了让代码“更容易理解,更易于修改”。这可能使程序运行得更快,也可能使程序运行得更慢。在性能优化时,只关心让程序运行得更快,最终得到的代码有可能更难理解和维护。

两顶帽子

这是一个比喻,使用重构技术开发软件时,我把自己的时间分配给两种截然不同的行为:添加新功能和重构。添加新功能时,我们不应该修改既有代码,只管添加新功能。重构时我们就不饿能添加功能,只管调整代码的结构。

实际开发过程中,我们可能需要经常变换帽子。如果把程序结构改一下,功能的添加会容易得多;新功能添加好了以后发现代码难以理解,则继续重构。

为何重构

我们之所以重构,因为它能让我们更快——添加功能更快,修复bug更快。

重构改进软件的设计

没有重构,程序的内部设计(架构)会逐渐腐败变质。当人们只为短期目的而修改代码时,他们经常没有完全理解架构的整体设计,于是代码逐渐失去了自己的结构。程序员越来越难通过阅读源码来理解原来的设计。

经常性的重构有助于代码维持自己该有的形态。

重构使软件更容易理解

写让计算机理解的代码很容易,只要能编译通过并运行;但写出让别人能理解的代码则需要下点功夫了。所以我们写代码要考虑以后那个修改的人,而且那个人很可能是哦我们自己。

开始进行重构前,代码可以正常运行,但结构不够理想。在重构上花一点点时间,就可以让代码更好地表达自己的意图。

重构帮助找到Bug

对代码进行重构,就可以深入理解代码的所作所为,并立即把新的理解反映在代码当中。搞清楚程序结构的同时,也验证了所做的一些假设, 更容易将Bug找出来。重构能够帮助我们更有效地写出健壮的代码。

重构提高编程速度

设计耐久性假说:通过投入精力改善内部设计,我们增加了软件的耐久性,从而可以更长时间地保持开发的快速。

CH02_重构的原则(什么是重构、为什么重构、何时重构),读《重构改善既有代码的设计第2版》,重构

行业的陈规认为:良好的设计必须在开始编程之前完成,因为一旦开始编写代码,设计就只会逐渐腐败。重构改变了这个图景。现在我们可以改善已有代码的设计,因此我们可以先做一个设计,然后不断改善它,哪怕程序本身的功能也在不断发生着变化。由于预先做出良好的设计非常困难,想要既体面又快速地开发功能,重构必不可少。

何时重构

三次法则

  • 第一次做某件事时只管去做
  • 第二次做类似的事会产生反感,但无论如何还是可以去做
  • 第三次再做类似的事,你就应该重构。

预备性重构:让添加新功能更容易

重构的最佳时机就在添加新功能之前。例如有个函数提供了我们需要的大部分功能,只是有几个变量跟我们需要的冲突,通常我们的做法使把这个函数复制过来,修改几个值。这样做会导致重复代码(将来有可能需要修改两处)。使用函数参数化(310)进行重构后,只需要调用这个函数,传入需要的参数。

修复bug时的情况也是一样。在寻找问题根因时,可能会发现:如果把3段一模一样且都会导致错误的代码合并到一处,问题修复起来会容易得多。

帮助理解的重构:使代码更易懂

重构带来的帮助不仅发生在将来——常常是立竿见影。先在一些小细节上使用重构来帮助理解,给一两个变量改名,让它们更清楚地表达意图,以方便理解,或是将一个长函数拆成几个小函数。当代码变得更清晰一些时就会看见之前看不见的设计问题。

捡垃圾式重构

帮助理解的重构还有一个变体:已经理解代码在做什么,但发现它做得不好,例如逻辑不必要地迂回复杂,或者两个函数几乎完全相同,可以用一个参数化的函数取而代之。有两种处理方式:如果垃圾很容易重构,马上重构它;如果重构需要花一些精力,记录下来,完成当下的任务再回来重构它。

有计划的重构

一般项目计划上没有专门留给重构的时间,绝大多数重构都在做其他事的过程中自然发生。如果团队过去忽视了重构,那么常常会需要专门花一些时间来优化代码库,以便更容易添加新功能。

长久以来,人们认为编写软件是一个累加的过程:要添加新功能,我们就应该增加新代码。但优秀的程序员知道,添加新功能最快的方法往往是先修改现有的代码,使新功能容易被加入。所以,软件永远不应该被视为“完成”。每当需要新能力时,软件就应该做出相应的改变。越是在已有代码中,这样的改变就越显重要。

何时不应该重构

如果有一块凌乱的代码,但并不需要修改它,那么就不需要重构它。如果丑陋的代码能被隐藏在一个API之下,暂时容忍它继续保持丑陋。只有当需要理解其工作原理时,对其进行重构才有价值。

另一种情况是,如果重写比重构还容易,就别重构了。

重构的挑战

延缓新功能开发

很多人认为,花在重构的时间是在拖慢新功能的开发进度。“重构会拖慢进度”这种看法仍然很普遍,这可能是导致人们没有充分重构的最大阻力所在。

重构的唯一目的就是让我们开发更快,用更少的工作量创造更大的价值。

有一种情况确实需要权衡取舍:有时会看到一个(大规模的)重构很有必要进行,而马上要添加的功能非常小,这时可以先把新功能加上,然后再做这次大规模重构。

测试

如果开发环境(开发工具)能很好的支持自动化重构,则可以信任这些重构;如果不能最好有完备的测试套件(测试环境、测试代码、单元测试等)。

遗留代码

遗留代码往往很复杂,可能也没有充足的测试,关键还是别人写的。如果不幸遇到,没有什么好办法:没测试就加测试、随时重构相关的代码(不建议尝试一鼓作气把复杂而混乱的遗留代码重构成漂亮的代码)。

重构、架构和YAGNI

YAGNI:“你不需要它(you are`t going to need it)”。YAGNI并不是“不做架构性思考”的意思,不过确实有人以这种欠考虑的方式做事。

重构对架构最大的影响在于,通过重构,我们能得到一个设计良好的代码库,使其能够优雅地应对不断变化的需求。“在编码之前先完成架构”这种做法最大的问题在于,它假设了软件的需求可以预先充分理解。但经验显示,这个假设很多时候甚至可以说大多数时候是不切实际的。只有真正使用了软件、看到了软件对工作的影响,人们才会想明白自己到底需要什么。

重构与软件开发过程

重构是否有效,与团队采用的其他软件开发实践紧密相关。

重构的第一块基石是自测试代码。

如果一支团队想要重构,那么每个团队成员都需要掌握重构技能,能在需要时开展重构,而不会干扰其他人的工作。

自测试代码、持续集成、重构三者之间有着很强的协同效应。

重构与性能

重构可能使软件运行更慢,但它也使软件的性能优化更容易。先写出可调优的软件,然后调优它以求获得足够的速度。

编写构造良好的程序,不对性能投以特别的关注,直至进入性能优化阶段——那通常是在开发后期。一旦进入该阶段,再遵循特定的流程来调优程序性能。

在性能优化阶段,首先应该用一个度量工具来监控程序的运行,让它告诉我程序中哪些地方大量消耗时间和空间。这样就可以找出性能热点所在的一小段代码。然后集中关注这些性能热点,并使用持续关注法中的优化手段来优化它们。文章来源地址https://www.toymoban.com/news/detail-673869.html

到了这里,关于CH02_重构的原则(什么是重构、为什么重构、何时重构)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Elasticsearch专栏 02】深入探索:Elasticsearch为什么使用倒排索引而不是正排索引

    Elasticsearch选择使用倒排索引而不是正排索引,主要是基于倒排索引在处理全文搜索和大规模数据集时的优势。下面将详细解释为什么Elasticsearch更倾向于使用倒排索引,并提供一些简化的代码片段来说明这两种索引结构的基本差异。 正排索引是一种将文档映射到其包含的单词

    2024年02月22日
    浏览(49)
  • Netty为什么高效,为什么这么受欢迎?

    上篇文章通过 Java NIO 的处理流程与 Netty 的总体流程比较,并结合 Netty 的源码,可以更加清晰地理解Netty。本文将结合源码详细解析Netty的高效和强大功能的设计原理,学习 Netty 是如何实现其卓越的性能和功能特性,也希望可以在日后工作中利用到 Netty 的设计思想。 我们先看

    2024年02月12日
    浏览(70)
  • Redis—Redis介绍(是什么/为什么快/为什么做MySQL缓存等)

    一、Redis是什么 Redis 是一种 基于内存的数据库 ,对数据的读写操作都是在内存中完成,因此读写速度非常快,常用于 缓存,消息队列、分布式锁等场景 。         Redis 提供了多种数据类型来支持不同的业务场景,比如 String(字符串)、Hash(哈希)、 List (列表)、Set(集合)、

    2024年02月10日
    浏览(67)
  • AIMD 为什么收敛(tcp reno/cubic 为什么好)

    TCP 拥塞控制目标是缓解并解除网络拥塞,让所有流量公平共享带宽,合在一起就是公平收敛。 AIMD(几乎所有与拥塞控制相关的协议或算法都有 AIMD 的影子,包括 RoCE,BBRv2) 为什么收敛?我一般会给出下面的老图: 虽然只展示了两条流的收敛,但 n 条流收敛的展示无非就是将

    2024年02月06日
    浏览(76)
  • tcp 为什么要三次握手,两次不行吗?为什么?

    TCP使用三次握手(Three-Way Handshake)的过程是为了确保双方建立起可靠的通信连接,并在连接的建立过程中协商必要的参数。两次握手是不够的,原因主要有以下几点: 防止已失效的连接请求被接受: 假设有A和B两台主机,A向B发送了一个连接请求,但由于某些原因导致连接建

    2024年02月20日
    浏览(64)
  • 为什么美国加息,会让硅谷银行破产?美联储为什么要加息?

    所有回答由 AI 生产 答 : 美国加息会导致国债利率上升,此时购买国债的银行获得的利息收益会比利率较低时少,因此国债的市场价格就会下降,从而导致银行持有的这些国债资产减值。 答 : 美国加息意味着美国央行(即联邦储备委员会)将提高其官方基准利率,这意味着

    2023年04月23日
    浏览(65)
  • 为什么用python做人工智能,为什么人工智能用python

    大家好,给大家分享一下python人工智能为什么放到最后才学,很多人还不知道这一点。下面详细解释一下。现在让我们来看看! Source code download: 本文相关源码 一、为何人工智能(AI)首选Python? 读完这篇文章你就知道了。我们看谷歌的TensorFlow基本上所有的代码都是C++和Python,

    2024年02月22日
    浏览(73)
  • 重构改善既有代码的设计-学习(一):封装

              一些记录性结构(例如hash、map、hashmap、dictionary等),一条记录上持有什么字段往往不够直观。如果其使用范围比较宽,这个问题往往会造成许多困扰。所以,记录性结构应该被封装成为一个类。         例如:         应该被重构为:           我们通常鼓

    2024年01月21日
    浏览(35)
  • 【PDF密码】PDF文件为什么无法修改?为什么PDF文档不支持编辑?

    pdf文件大家应该都经常接触,但是不知道大家会遇到这种情况:有些PDF文件打开之后无法编辑?是什么原因呢?今天我们来分析一下都是那些原因导致的。 首先我们可以考虑一下,PDF文件中的内容是否是图片,如果确认是图片文件,那么我们想要编辑,就可以先使用PDF编辑器

    2024年01月22日
    浏览(68)
  • I2C中为什么线与?为什么要有上拉电阻?

            首先,连接到 I2C 上的设备是开漏输出的。以漏极开漏输出(OD)为例,是指将输出级电路结构改为一个漏极开路输出的 MOS 管。这样做的好处在于: 防止短路。 可以实现 “线与”逻辑 ,可以减少一个与门的使用,简化电路。 结论: I2C支持多个主设备与多个从设

    2024年02月09日
    浏览(55)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包