写点什么

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

  • 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:005847
用户头像

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

关注

评论

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

设计模式之假如需要一百万个对象

架构师修行之路

ChaosBlade:从零开始的混沌工程(五)

郭旭东

Kubernetes 云原生 混沌工程

设计模式中的单例模式并不完美

架构师修行之路

设计模式 单例模式 23种设计模式 高并发系统设计

InnoDB存储引擎简介

Simon

MySQL innodb

企业网站搭建避坑指南

姜奋斗

网站 新手指南 企业 网站搭建 避坑

【译】代码中如何写出更有意义的命名

Jackey

代码质量

联盟链有自己的路要走

Leonbond

区块链 联盟链 公有链

C/C++陷阱与套路,当年就是折在这些地儿…

华为云开发者联盟

c++ 设计 编辑 程序 陷阱

菊长说丨一文读懂MySQL4种事务隔离级别

华为云开发者联盟

MySQL 数据库 事务隔离级别 事务 华为云

有它的加持,单机玩转百亿大数据不是梦!

易观大数据

2.1 类加载器、 双亲委派模型 -《SSM深入解析与项目实战》

谙忆

Google Protocol Buffer 学习笔记

Geek_4z9ami

protobuf

Jessie’s产品经理系列1-基础能力篇

架构5班杨娟Jessie

产品经理 能力模型

如何将FastDFS存储数据平滑迁移至XSKY对象存储?

XSKY星辰天合

1.1 了解Spring框架 -《SSM深入解析与项目实战》

谙忆

1.2 了解MyBatis -《SSM深入解析与项目实战》

谙忆

秒懂云通信:如何使用阿里云号码认证服务(小白指南)

阿里云Edge Plus

云通信 通信云 号码认证

CDN百科10:快速上手阿里云DCDN全站加速,最新配置与购买优惠教程

阿里云Edge Plus

CDN 直播 网页加速

如何设计一个优秀的组件

Lee Chen

大前端

微服务架构下你的数据一致了吗?

码猿外

架构 微服务 数据一致性

JVM系列之:再谈java中的safepoint

程序那些事

Java JVM JIT safepoint

SQL的三十而已—SQL30问

大唐小生

sql 技术人生

计算机网络基础(十五)---传输层-TCP协议详解

书旅

计算机网络 网络 协议栈 协议族

数据处理能力相差 2.4 倍?Flink 使用 RocksDB 和 Gemini 的性能对比实验

Apache Flink

flink

LeetCode题解:24. 两两交换链表中的节点,迭代,JavaScript,详细注释

Lee Chen

大前端 LeetCode

操作系统和并发的爱恨纠葛

苹果看辽宁体育

Java 并发

视频会议专线部署不会?别急,我教你

华为云开发者联盟

网络 网关 华为云 高清视频 welink

设计模式之——单例模式你真的会吗?

诸葛小猿

设计模式 单例模式 Singleton 饿汉式 懒汉式

《SSM深入解析与项目实战》目录与说明

谙忆

七的婚姻生活

徐说科技

Java项目如何分层

老胡爱分享

分层架构 项目

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