写点什么

重构:“为什么”和“怎么做”

  • 2008-04-09
  • 本文字数:1252 字

    阅读完需:约 4 分钟

近日在“敏捷中国”讨论组展开了一系列关于重构的讨论。一种观点认为,对代码的重构是程序员出于对代码美感的追求而进行的行为。

重构更多的是基于激情,把代码做为艺术品来雕琢。但是不少软件公司工作环境可以很快摧残这种热情。

然而作为软件开发工作的一部分,重构行为显然不应该被归结于“激情”和“艺术”。之所以有这种想法,往往是由于没有一种有效的方式来衡量重构行为的成本和收益,从而不能有效地组织和管理重构行为。在同一组讨论中就有人提出了这个问题:

我想了解一下,大家是否把重构的时间放到 sprint 的估算里。假设到了代码用户案例测试通过了,操作文档也完成了,如果没有时间重构代码,你们会怎么办?重构的时间,跟追求的度成正比,怎么估算重构的成本?

来自 ThoughtWorks 的熊节认为,重构的收益体现为修改成本的降低,因此也是可衡量的。

从商业的角度,每段代码,每次修改都带来一定的商业价值,同时每段新代码,每次修改都有它的成本,这个成本随代码质量的下降而上升。当代码质量烂到一定程度,修改代码的成本超过收益,这个软件就没办法继续发展了。重构也有它的成本,它带来的收益是降低修改代码的成本。如果你发现一个程序员一方面抱怨面对变化的需求他不敢动手改代码,另一方面又不想通过重构改善代码质量,你就知道这里必定有什么问题了。

在一篇题为“在大型遗留系统基础上运作重构项目”的文章中,熊节详细说明了如何权衡重构的成本和收益:

  1. 和别的任何 story 一样,重构的 story(以及其他“技术债”类型的 story)也应该符合 INVEST 的标准。尤其是,它们的工作量应该得到估算,它们应该按照业务价值排列优先级。因为归根到底,重构(以及其他任何开发任务)都归结为“花在代码上的成本”与“对业务创造的价值”之间的权衡。
  2. 按照定义,重构意味着“在不改变功能性行为的前提下改进代码的组织结构”。如果代码基础本身脆弱而没有测试覆盖,重构的成本就会很高,因为你需要花很大力气来确认自己的修改没有改变功能性行为。
  3. 如果偿还“技术债”的成本非常高,那么与之对应的业务价值就必须更高,否则偿还这些债务就将得不偿失。其结果是:一段代码,从程序员的角度看来越糟糕,从商业的角度来说就越不应该去动它。
  4. 综上所述,如果有人说“这一大堆代码都需要重构”,这样的说法很有可能是值得商榷的。你需要把重构划分成细粒度的、可控的 story,为这些重构 story 制定验收标准,评估它们的优先级,估算它们的工作量,然后逐一实现它们,并且放弃一些得不偿失的重构。

这篇文章还介绍了对遗留系统进行重构的步骤:

经过这个咨询项目,eMAN 产品开发团队在原有代码的基础上划分了细粒度的重构 story,建立了持续集成环境,并按照共同探索出的节奏,以测试为驱动、以代码质量为导向,不断重构以改进代码质量,并且积累了一些常见问题的解决办法,为大规模遗留系统的重构找出了一条切实可行的路子。

和所有的敏捷实践一样,重构的原则说起来很简单,但实际操作起来总是会有很多困难,需要经验和权衡。你在尝试重构时遇到困难了吗?你有自己的重构经验想要与整个社区分享吗?

2008-04-09 23:481628

评论

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

Linux之ln命令

入门小站

Linux

Rust从0到1-面向对象编程-概念

rust oop 面向对象编程

Vue进阶(幺玖肆):localStorage应用总结

No Silver Bullet

Vue LocalStorage 7月日更

【LeetCode】两个链表的第一个公共节点Java题解

Albert

算法 LeetCode 7月日更

Python OpenCV 图像的几何变换,先说不平凡的 resize 函数

梦想橡皮擦

Python 7月日更

[翻译]innodb_ruby 项目简介

keaper

MySQL 数据库 后端 服务端 innodb

MERN堆栈

吴脑的键客

node.js mongodb React Express

Redis 的集群容错与故障转移

U2647

redis redis哨兵模式 集群 redis cluster Leader

浪潮云洲×天人集团:打通数据脉络 驱动降本增效

面向资源的架构(ROA)概述

码语者

SOA ROA

在线XML转CSV工具

入门小站

手把手教你在Modelarts平台上进行视频推理

华为云开发者联盟

视频 modelarts 推理 预处理 视频推理

微信朋友圈复杂度分析

桂阳

微信朋友圈高性能复杂度分析

木云先森

架构实战营

【架构训练营】模块二作业

zclau

Vue进阶(三十五):watch监听函数详解

No Silver Bullet

Vue 7月日更 watch

Go语言,什么情况下应该使用指针?

微客鸟窝

Go 语言

大数据实战训练营作业一

Clarke

【Flutter 专题】80 初识 Flutter Stream (一)

阿策小和尚

Flutter 小菜 0 基础学习 Flutter Android 小菜鸟 7月日更

云小课|ModelArts Pro 视觉套件:零代码构建视觉AI应用

华为云开发者联盟

AI 零代码 ModelArts Pro 行业落地 视觉套件

现代企业架构师的5大特征及六种方法

禅道项目管理

架构 数据 开发 创新 行业趋势

基于迁移学习的语义分割算法分享与代码复现

华为云开发者联盟

语义分割 modelarts 迁移学习 语义分割算法 迁移分割

char+char=number

喵叔

7月日更

使用dubbo-go搭建dubbo接口测试平台

捉虫大师

dubbo 接口测试 dubbo-go Go 语言

倒计时 | 7.24 阿里云 Serverless Developer Meetup 杭州站报名火热进行中!

Serverless Devs

阿里云 Serverless 云原生

🐬【MySQL技术导航】常用函数介绍(1)

洛神灬殇

MySQL 7月日更

“吴痛针灸”代言人翻车,为什么女性会重新定义品牌优势

脑极体

大数据实战训练营作业二

Clarke

华为云UGO正式公测:4大核心优势破解异构数据库迁移难题

华为云开发者联盟

数据库 华为云数据库 异构数据库 对象迁移 应用迁移

使用Docker运行OnlyOffice的Node.js示例

一个需求

onlyoffice

【从零开始学爬虫】采集西瓜直播视频

前嗅大数据

大数据 爬虫 数据采集

重构:“为什么”和“怎么做”_研发效能_林芷薰_InfoQ精选文章