红帽白皮书新鲜出炉!点击获取,让你的云战略更胜一筹! 了解详情
写点什么

把同事的代码重写得干净又整洁,老板却让我做回滚?

  • 2020-02-06
  • 本文字数:2847 字

    阅读完需:约 9 分钟

把同事的代码重写得干净又整洁,老板却让我做回滚?

夜深了。


我的同事把这周写的代码提交了。我们在开发一个图形编辑器画布,已经实现了形状调整功能,即通过拖拽形状边缘的手柄来调整形状(比如矩形和椭圆形)。


代码可以运行。


但重复代码有点多。每一种形状(比如矩形和椭圆形)有不同的手柄,往不同方向拖拽手柄对形状的位置和大小影响也不一样。如果用户同时按住 Shift 键,在改变大小的同时要保持比例不变。这里涉及了很多数学运算。


代码看起来像这样:


let Rectangle = {  resizeTopLeft(position, size, preserveAspect, dx, dy) {    // 10行重复的数学运算代码  },  resizeTopRight(position, size, preserveAspect, dx, dy) {    // 10行重复的数学运算代码  },  resizeBottomLeft(position, size, preserveAspect, dx, dy) {    // 10行重复的数学运算代码  },  resizeBottomRight(position, size, preserveAspect, dx, dy) {    // 10行重复的数学运算代码  },};
let Oval = { resizeLeft(position, size, preserveAspect, dx, dy) { // 10行重复的数学运算代码 }, resizeRight(position, size, preserveAspect, dx, dy) { // 10行重复的数学运算代码 }, resizeTop(position, size, preserveAspect, dx, dy) { // 10行重复的数学运算代码 }, resizeBottom(position, size, preserveAspect, dx, dy) { // 10行重复的数学运算代码 },};
let Header = { resizeLeft(position, size, preserveAspect, dx, dy) { // 10行重复的数学运算代码 }, resizeRight(position, size, preserveAspect, dx, dy) { // 10行重复的数学运算代码 }, }
let TextBlock = { resizeTopLeft(position, size, preserveAspect, dx, dy) { // 10行重复的数学运算代码 }, resizeTopRight(position, size, preserveAspect, dx, dy) { // 10行重复的数学运算代码 }, resizeBottomLeft(position, size, preserveAspect, dx, dy) { // 10行重复的数学运算代码 }, resizeBottomRight(position, size, preserveAspect, dx, dy) { // 10行重复的数学运算代码 },};
复制代码


这些重复代码看起来真的很碍眼。


这样的代码不够干净。


大部分重复是因为朝相同方向调整形状的代码都差不多,比如 Oval.resizeLeft()和 Header.resizeLeft()就很类似。


其他重复是因为同一种形状的方法之间很相像,比如 Oval.resizeLeft()和 Oval 其他的方法就很类似。另外,Rectangle、Header 和 TextBlock 之间也有重复的地方,因为文本框也是矩形。


我想到了一个办法。


我们可以给代码分组,把重复代码移除掉,比如像下面这样。


let Directions = {  top(...) {    // 5行不一样的数学运算代码  },  left(...) {    // 5行不一样的数学运算代码  },  bottom(...) {    // 5行不一样的数学运算代码  },  right(...) {    // 5行不一样的数学运算代码  },};
let Shapes = { Oval(...) { // 5行不一样的数学运算代码 }, Rectangle(...) { // 5行不一样的数学运算代码 },}
复制代码


然后,把它们的行为组合起来。


let {top, bottom, left, right} = Directions;
function createHandle(directions) { // 20行代码}
let fourCorners = [ createHandle([top, left]), createHandle([top, right]), createHandle([bottom, left]), createHandle([bottom, right]),];let fourSides = [ createHandle([top]), createHandle([left]), createHandle([right]), createHandle([bottom]),];let twoSides = [ createHandle([left]), createHandle([right]),];
function createBox(shape, handles) { // 20行代码}
let Rectangle = createBox(Shapes.Rectangle, fourCorners);let Oval = createBox(Shapes.Oval, fourSides);let Header = createBox(Shapes.Rectangle, twoSides);let TextBox = createBox(Shapes.Rectangle, fourCorners);
复制代码


代码量减少了一半,重复代码完全消失了!多么干净。如果要修改某个形状或方向的行为,只需要在一个地方做出改动,不需要修改所有的方法。


夜已深,我把改好的代码提交到 master 分支,然后上床睡觉。因为帮同事把杂乱的代码清理干净了,我心里还引以为豪。

第二天

事情并没有像我期待的那样发生。


老板找我谈话,他们希望我把代码回滚回去。我感到很惊讶,毕竟原先的代码简直就是一团乱麻,而我改得很干净啊!


我很不情愿地答应了,但几年之后,我才意识到他们其实是对的。

必经之路

痴迷于“干净代码”和删除重复代码是我们很多人都会经历的一个阶段。当我们对自己的代码不是很自信时,就很容易将自我价值感和职业自豪感与一些可以被衡量的东西联系在一起,比如严格的 lint 规则、命名模式、文件结构、不重复代码实践。


我们没办法自动去除重复代码,但可以自己动手做。每次修改代码之后,我们可以很容易地知道重复代码是少了还是多了。所以,去除重复代码感觉就像是在改进代码质量。更糟糕的是,它扰乱了人们的认同感,让他们觉得“我是那种编写干净代码的人”,但这其实无异于自我欺骗。


一旦学会了抽象,我们就很容易对这种能力产生很高的期望,每当看到有重复代码就会想要对它们进行抽象。在写了几年代码之后,我们发现重复代码到处都是,而抽象成了我们获得的一项超级能力。如果有人告诉我们说抽象是一种美德,那我们肯定会深信不疑,并且会因为别人不崇尚“干净代码”而对他们品头论足。


现在,我知道之前的代码重构就是一个灾难,原因如下。


  • 首先,我没有事先和写代码的人沟通。我直接修改了他们的代码并提交,没有和他们讨论。即使这是一种改进(但我现在不这么认为了),但我这样的行事方式并不值得称道。一个健康的工程团队应该以信任为基础,不经过讨论就修改他人的代码会对团队协作造成沉重的打击。

  • 其次,天下没有免费的午餐。我以牺牲灵活性为代价,以此来减少重复代码,这算不上是一个好的权衡。例如,后来我们要求不同形状的不同手柄具备一些特殊的行为,被我重构过的代码需要修改多次才能满足需求,而原先“杂乱”的代码却可以很容易实现这些需求。


那么,我的意思是我们应该尽量写“脏”代码吗?当然不是。我只是建议大家在考虑什么是“干净”或“脏”代码时进行深度思考。你当时有什么样的感觉?厌恶?正义?美丽?优雅?你可以肯定这些品质会带来实质性的工程成果吗?它们又是如何影响代码的编写和修改方式的?


我确实没有深入思考过这些事情。我只考虑到代码本身,但从来没有想过代码与团队之间的演化关系。


编码就像是一段旅程,想想你从写第一行代码到现在走了多远。当第一次通过提取函数或重构类让复杂的代码变简单,我觉得那是一种乐趣。如果你对自己的“杰作”感到自豪,那么就很容易掉入追求干净代码的旋涡。


但请不要止步于此,不要只做一个干净代码狂热者。写出干净的代码并不是我们的终极目标,我们只是通过这种方式尝试找到处理系统复杂性的方法。当你不确定代码改动会对代码库造成怎样的影响,在未知的海洋中需要灯塔的指引,那么这不失为一种防御机制。


写出干净的代码可以作为一种指引,但后面的路还是要自己走。

原文链接

Goodbye clean code!


2020-02-06 14:5212827
用户头像
小智 让所有人认同的文字称不上表达

发布了 408 篇内容, 共 376.0 次阅读, 收获喜欢 1972 次。

关注

评论 6 条评论

发布
用户头像
有道理,虽然代码目前看着一样,但是如果含义和应用场景不同的话,迟早要分化,不要一开始就瞎jb整在一起
2020-09-16 11:45
回复
用户头像
对于第二点原因不太认同。我的经验是,当工程达到一定规模,代码越多反而灵活性越差
2020-02-18 13:15
回复
用户头像
如果是技术leader的话,这件事是需要先跟下面人一起讨论如何去优化代码,而不是自己去做,这种行为就是一种自私不信任,不然下面的人来了是当摆设,来衬托自己很牛吗?如果是员工的话,只需要负责好自己的那部分代码就可以了,因为代码的整体执行方案还是需要技术leader去领导的,不然百花齐放,每个人心里都有自己的完美
2020-02-17 09:39
回复
用户头像
直接改是不太好,最好能提PR,讨论之后再合并,不然别人维护了一年的代码,被你随手改的妈妈都不认识了,换谁不一肚子火。
2020-02-15 23:54
回复
用户头像
这个理由有牵强得一笔。。。继承一个实现接口,使用装饰器不就好了
2020-02-09 09:55
回复
你读过人家的源码?
2020-02-11 16:17
回复
没有更多了
发现更多内容

开源大数据Meetup回顾 | 第四范式:现代存储架构下的系统优化实践

AI自助帮你换背景,超强实时人像扣图算法开源啦!

百度大脑

人工智能

仓储管理系统开发介绍

(王经理)专业app小程序开发

从350ms到80ms,揭秘阿里工程师 iOS 短视频优化方案

阿里云视频云

ios 短视频 视频 视频处理 视频流

这一次!我在百度告诉你,当你请求百度时都发生了什么...

程序员 架构 面试 计算机

如何支持亿级用户分流实验?AB实验平台在爱奇艺的实践

爱奇艺技术产品团队

测试 开发 精准测试 AB testing实战

算法推荐规制!《互联网信息服务算法推荐管理规定(征求意见稿)》公开征求意见

郑州埃文科技

Python代码阅读(第19篇):合并多个字典

Felix

Python 编程 Code Programing 阅读代码

最佳实践 | 单元测试+回归测试在SRS代码提交中的实践总结

腾讯云音视频

SRS

APP DIFF自动化解决方案

爱奇艺技术产品团队

测试 开发 精准测试 Diff i技术会

基于 Formily 的表单设计器实现原理分析 ​

全象云低代码

JavaScript 低代码开发 表单设计

常用正则表达式最强汇总(含Python代码举例讲解+爬虫实战)

Python研究者

8月日更

培训教育系统开发

(王经理)专业app小程序开发

阿里第七次更新的Java面试突击宝典,已累计拿到759份Offer

Java 程序员 架构 面试 后端

Shopee物流业务核心数据库架构演变——权衡取舍的艺术

Shopee技术团队

架构 #数据库 #物流 #供应链 #Shopee

比POSTMAN更好用!在国产接口调试工具APIPOST中使用Mock

Proud lion

大前端 后端 Postman 开发工具 接口文档

使用接口文档快照机制,让接口文档不在频繁变动

CodeNongXiaoW

大前端 测试 后端 接口文档

👊【SpringCloud技术专题】超级详细的Gateway网关的技术指南

洛神灬殇

网关 SpringcloudGateway SpringCloud Gateway 8月日更

今天我们来谈谈Golang的同步等待组

Regan Yue

Go 语言 8月日更 同步等待组

你还在认为TypeScirpt 是 AnyScript ?

程序员海军

typescript 大前端 javascri

秋招开局痛击!迷惑的阿里三面反手一个感谢信,最终被字节捞起

编程susu

Java 编程 面试 计算机 技术宅

ipfs矿机怎么买?ipfs矿机怎么获取?

ipfs矿机怎么买 ipfs矿机怎么获取

24位出品人已确认,开放原子全球开发者峰会(OADC)分论坛速览(更新中)

开放原子开源基金会

模块六作业

燕燕 yen yen

架构实战营

是的你没看错,HTTP3来了

程序那些事

HTTP 程序那些事 http3

开源应用中心|这款纯手工打造的开源博客平台,大佬们都在用!

开源

ZEGO 教程 | RTC + AI 视觉的最佳实践(移动端)

ZEGO即构

AI RTC 滤镜

ipfs矿机怎样选?ipfs矿机多少钱一台?

分布式存储 IPFS ipfs挖矿 ipfs矿机 filecoin挖矿

ARM工控主板比X86工控主板好吗?

双赞工控

小数据与业务的毛细血管

boshi

大数据 深度思考

课程排课软件开发

(王经理)专业app小程序开发

把同事的代码重写得干净又整洁,老板却让我做回滚?_文化 & 方法_Dan Abramov_InfoQ精选文章