写点什么

重构和代码异味——通往更整洁的代码

  • 2016-09-26
  • 本文字数:2156 字

    阅读完需:约 7 分钟

重构可以让代码更整洁,更易于理解和维护。“代码异味(code smells)”的辨别需要实践和经验:设计不良的表征说明代码存在更深层次的问题。工具可以帮助我们逐步重构,并防止破坏代码。

SwanseaCon 2016 大会上,Codurance 实习生 Halima Koundi 探讨了重构和代码异味。InfoQ 正以 Q&A、综述和文章等形式对大会进行跟踪报道。

Koundi 引用了 Martin Fowler 对代码异味的定义

代码异味是一种表象,它通常对应于系统中更深层次的问题。

如果重视不够,没有适当地维护或改进代码,那么代码质量就会下降。在演讲中,Koundi 总结了不同类型的代码异味,并阐述了如何辨别它们。她提到的其中一类代码异味是“面向对象滥用”;这类异味和面向对象设计的不完全或错误实现有关。辨别“面向对象滥用”异味有助于找出可能违反面向对象设计原则、可以导致错误的对象行为的代码。

Koundi 提到的另外一类代码异味是“变更障碍”,即代码的一处变更(例如,实现一个新特性或者调整一个现有特性)会影响许多类,需要对整个代码进行大量的修改。“平行继承层次”或“发散式变更”就是这类代码异味的例子。

Koundi 演示了如何使用 Jetbrains 的 ReSharper 安全地重构代码。在演示过程中,她示范了当需要添加新的支付方法时如何调整代码。她阐述了如何逐步重构代码以及如何确保所做的变更不会破坏代码。

演讲结束后,InfoQ 采访了 Koundi,内容涉及当前存在的不同类型的代码异味、开发人员如何辨别代码异味、消除代码异味的原则、代码重构实践、开发人员如何确保所做的变更不会破坏代码、什么时候应该重构及什么时候不应该重构、重构带来的好处。

InfoQ:代码异味有哪些不同的类型?

Halima Koundi:代码异味有多种类型。部分代码异味反复出现是因为开发人员不注意以及代码库的抽象不够;这包括过长的方法、过长的参数列表等。其他的代码异味是因为面向对象原则的不完全或糟糕实现,例如,“拒绝继承(Refused Bequest)”就是这样一种异味,该情况说明我们已经引入了错误的抽象。

向系统添加噪音的代码是另外一类。例如,即使不删除,你也应该减少代码中的注释,而为方法取一个更有意义的名字。无用的代码应该删除——即使你认为稍后可能需要。

InfoQ:开发人员如何辨别代码异味?

Koundi:代码异味可以通过代码的可见特征、有形特征和无形特征来辨别。可见特征包括:过长的方法或函数体、过长的参数列表、变量多次成组出现且模式类似——这些是职责混乱抽象缺失的表征。对于有形特征,一个例子是变更需要查看并修改许多文件。无形特征是当你提出类似这样的问题,“既然我需要的行为并不相同,我为什么还要继承这个父类”。

代码异味的辨别需要实践和经验。有许多方法和套路可以帮助你实践。代码异味是表征;它们通常说明你破坏了某些设计原则。了解这些原则有助于你理解代码库的问题。

InfoQ:消除代码异味的一般原则是什么?

Koundi:重构是指改变代码的设计,而不改变代码的行为。重构是平台无关的。代码异味是糟糕设计的表征。我的建议是,读下 Martin Fowler 的著作《重构:改善既有代码的设计》。需要注意的是,重构为抽象概念并不总是正确的方式,因为那会增加系统的复杂度,而且本身可能会变成代码异味。代码有可能不是特别复杂,并不能从一定程度的抽象受益。

InfoQ:您谈了重构代码的实践并进行了演示。您能举几个例子说明下如何重构代码吗?

Koundi:我发现,有两种非常强大而又相当简单的重构方法。

  • 方法提取:假如你有一些函数,它们做了太多的事情,而你希望能够让代码更简单易读,则可以按照算法的操作步骤把算法分解,并把每个操作都提取到自己的方法中,然后根据它们的行为命名这些方法。
  • 方法重命名:表现力不够的代码难以使用。例如,你发现,在查看一个方法时,你花了 10 多分钟才弄清楚它在做什么。如果你找到了一种更好的方法来描述代码的行为,那么你应该重命名那个方法,前提是该方法没有作为一个公共 API 暴露。

就像我所演示的那样,工具和重构知识本身一样重要。了解开发环境让你可以更轻松、更迅速、更安全地执行重构。Matthew Butt 整理了一系列的重构截屏视频。他在视频中演示了如何通过简单的步骤重构代码。

InfoQ:开发人员怎么做才能确保他们正在进行的重构不会破坏代码?

Koundi:在开始重构之前,有几个方面需要确认。

  • 你可以核实系统的其他部分不受重构影响。这是通过测试完成的。
  • 关于如何使用这段代码,有一份清晰的文档。那份文档是由测试提供的。
  • 你所重构的系统部分不会遭受衰退。你猜,那是谁的工作?测试!

在重构代码之前,一定要确保自己已经有了各种测试。

InfoQ:什么时候应该重构?什么时候不应该?

Koundi:重构,像编写测试一样,应该成为同一个特性实现活动的一部分。它不是一个独立的活动。当你希望修改代码,而代码本身尚未做好变更准备时,重构它。重构是测试驱动开发(TDD)的一个重要步骤。

代码审查也是重构执行的上佳选择。

另一方面,为了实现“完美的代码”而在整个代码库上进行大量低价值的重构被称为镀金。这有损于代码整洁,因为它削弱了重构的真实性需求,盲目地为了重构而重构。如果代码正常,就不需要修改,不要碰他。

InfoQ:重构可以带来什么好处?

Koundi:重构的目标是更整洁的代码,就是说,重构旨在让代码更容易理解,降低变更成本。

查看英文原文: Refactoring and Code Smells – A Journey Toward Cleaner Code

2016-09-26 19:005198
用户头像

发布了 1008 篇内容, 共 387.7 次阅读, 收获喜欢 344 次。

关注

评论

发布
暂无评论
发现更多内容

MPEG-TS封装格式

Loken

音视频 5月月更

k8s client-go源码分析 informer源码分析(3)-Reflector源码分析

良凯尔

容器 云原生 Kubernetes 集群 Client-go

15-操作DOM对象

爱好编程进阶

Java 程序员 后端开发

Java进阶备战金九银十88道真题:多线程+集合

爱好编程进阶

Java 程序员 后端开发

mykit-lock之——分布式锁插件正式开源

爱好编程进阶

Java 程序员 后端开发

架构实战营 - 毕业总结

smile

架构实战营

ElasticSearch 概述

爱好编程进阶

Java 程序员 后端开发

有了测试组,为什么还要QA?

高山

测试 QA CMMI

架构训练营毕业设计:电商秒杀系统

AragornYang

架构训练营 架构实战营

AI简报:图像超分模型RCAN+SRResNet

AIWeker

人工智能 深度学习 5月月更 超分

Java 集合看这一篇就够了

爱好编程进阶

程序员 后端开发

Java字节流和字符流,是时候总结一下IO流了

爱好编程进阶

程序员 后端开发

KMP子字符串匹配算法学习笔记

爱好编程进阶

Java 程序员 后端开发

Mybatis源码学习(二)缓存和别名处理器

爱好编程进阶

程序员 后端开发

Druid连接池源码阅读05

石小天

架构实战营模块5作业

天琪实刚亮

5分钟学会 Vim 分屏操作方方面面

爱好编程进阶

Java 程序员 后端开发

SpringWebFlux中WebClient怎么打印日志?

编号94530

spring 日志 WebFlux WebClient

设计模式之代理模式

乌龟哥哥

5月月更

架构训练营 毕业总结

AragornYang

架构训练营 架构实战营

Dart 2.17发布,新特性速递

岛上码农

flutter ios 安卓开发 跨平台开发 5月月更

IntelliJ IDEA如何clean或者install Maven项目

爱好编程进阶

程序员 后端开发

LeetCode - 1629 -按键持续时间最长的键 - Java - 细喔

爱好编程进阶

Java 程序员 后端开发

数据库连接池 -Druid 源码学习(五)

wjchenge

Druid 数据库连接池

网站开发进阶(六十四)CSS 属性选择器讲解

No Silver Bullet

CSS 属性选择器 5月月更

从AI数羊到“相牛”:人工智能应用如何低门槛化?

脑极体

K8S 准入控制器有哪些是默认的?

baiyutang

Docker Kubernetes 云原生 k8s 5月月更

Go Web 编程入门:快速了解Fiber框架

宇宙之一粟

Go 语言 Fiber 5月月更

JDBC访问数据库的一些小技巧

爱好编程进阶

程序员 后端开发

Linux宝塔面板命令大全

爱好编程进阶

Java 程序员 后端开发

druid 源码阅读 5——讨论下druid为什么不用AtomicLong

张大彪

重构和代码异味——通往更整洁的代码_JetBrains_Ben Linders_InfoQ精选文章