整洁的代码,再见!

点击上方“Python大本营”,选择“置顶公众号”

python大本营  IT人的职业提升平台

作者 | Dan Abramov

深夜。

同事刚刚提交了他们编写了一整周的代码。我们在编写一个图形编辑器,他们实现了通过拖动矩形和椭圆的边缘来调整图形大小的功能。

他们的代码运行良好。

但代码中有重复。每种形状(如矩形或椭圆形)都有一组不同的拖动点,而且沿不同方向拖动也会以不同的方式影响形状的位置和大小。如果用户按住Shift键,我们还需要在调整大小时保持比例。这其中涉及很多数学运算。

他们的代码如下:

let Rectangle = {
  resizeTopLeft(position, size, preserveAspect, dx, dy) {
    // 10 repetitive lines of math
  },
  resizeTopRight(position, size, preserveAspect, dx, dy) {
    // 10 repetitive lines of math
  },
  resizeBottomLeft(position, size, preserveAspect, dx, dy) {
    // 10 repetitive lines of math
  },
  resizeBottomRight(position, size, preserveAspect, dx, dy) {
    // 10 repetitive lines of math
  },
};

let Oval = {
  resizeLeft(position, size, preserveAspect, dx, dy) {
    // 10 repetitive lines of math
  },
  resizeRight(position, size, preserveAspect, dx, dy) {
    // 10 repetitive lines of math
  },
  resizeTop(position, size, preserveAspect, dx, dy) {
    // 10 repetitive lines of math
  },
  resizeBottom(position, size, preserveAspect, dx, dy) {
    // 10 repetitive lines of math
  },
};

let Header = {
  resizeLeft(position, size, preserveAspect, dx, dy) {
    // 10 repetitive lines of math
  },
  resizeRight(position, size, preserveAspect, dx, dy) {
    // 10 repetitive lines of math
  },  
}

let TextBlock = {
  resizeTopLeft(position, size, preserveAspect, dx, dy) {
    // 10 repetitive lines of math
  },
  resizeTopRight(position, size, preserveAspect, dx, dy) {
    // 10 repetitive lines of math
  },
  resizeBottomLeft(position, size, preserveAspect, dx, dy) {
    // 10 repetitive lines of math
  },
  resizeBottomRight(position, size, preserveAspect, dx, dy) {
    // 10 repetitive lines of math
  },
};

这些重复的数学计算看着真碍眼。

这种代码不整洁。 

大部分重复都发生在相似方向的拖动。例如,Oval.resizeLeft() 与 Header.resizeLeft() 很相似。这是因为这两个方法都是向左拖动。

另一个相似之处出现在同一个形状的方法之间。 例如,Oval.resizeLeft() 与 Oval 的其他方法都很相似。这是因为它们都是处理椭圆的方法。Rectangle、Header和TextBlock之间也有一些重复,因为文本块都是矩形的。

突然,我想到了一个好主意。

我们可以像下面这样将代码分组,然后就可以删除所有的重复代码:

let Directions = {
  top(...) {
    // 5 unique lines of math
  },
  left(...) {
    // 5 unique lines of math
  },
  bottom(...) {
    // 5 unique lines of math
  },
  right(...) {
    // 5 unique lines of math
  },
};

let Shapes = {
  Oval(...) {
    // 5 unique lines of math
  },
  Rectangle(...) {
    // 5 unique lines of math
  },
}

然后是它们的行为:

let {top, bottom, left, right} = Directions;

function createHandle(directions) {
  // 20 lines of code
}

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 lines of code
}

let Rectangle = createBox(Shapes.Rectangle, fourCorners);
let Oval = createBox(Shapes.Oval, fourSides);
let Header = createBox(Shapes.Rectangle, twoSides);
let TextBox = createBox(Shapes.Rectangle, fourCorners);

改完以后,代码行数只有原来的一半,重复完全消失了!好整洁的代码!如果我们想更改某个方向的行为或某个形状的行为,则只需要修改一个地方即可,不像原来的代码需要修改所有类似的方法。

修改完代码后我才发现已经很晚了,我完全忘记了时间。提交完重构后的代码后,我心满意足地上床睡觉了,内心因为帮助同事整理代码而充满了自豪。

第二天早上

情况与我预想的完全不一样。

老板找我去谈话,他们很客气地要求我把代码改回去。我吓傻了。原来的代码一团糟,而我的代码非常整洁!

我很不情愿地答应了,但是直至几年后,我才幡然醒悟:他们是正确的。

这是每个人都经历过的一个阶段

相信每位痴迷于“整洁的代码”,希望消除重复的人都经历过这样一个阶段。当我们对代码不自信时,很容易将自我的价值感和专业自豪感附加到某种可以衡量的事物上:一组严格的lint规则、命名架构、文件结构、没有重复代码。

你无法自动删除重复代码,但是通过练习确实很容易实现。通常,在修改完代码后,你很容易看出代码行数是增加了还是减少了。于是,消灭重复代码就成了改善代码的客观指标。更糟糕的是,它混淆了人们的认同感:“我就是那种编写整洁代码的人”。这是一种强大的自我欺骗。

在我们学习了如何创建抽象后,很容易痴迷于这种方式,每当看到重复的代码时,就忍不住想提取抽象。在积累了若干年的编程经验后,我们看到重复无处不在,而抽象就成了“超能力”。如果有人告诉我们抽象是一种美德,我们就会全盘接受。而且我们还会开始评判其他人是否不崇尚“整洁”。

回头再看当年我的“重构”完全是一场灾难,原因主要有两个方面:

  • 首先,我没有和编写这段代码的人沟通。我重写了代码,并提交了代码,而他们却毫不知情。即便这是一种改进(虽然我不觉得),但这也是一种很糟糕的解决问题的方法。一个健康的工程团队需要不断地加强信任。不经讨论就重写队友的代码,这会重重地打击团队的协作能力。

  • 其次,天底下没有免费的午餐。我的代码虽然消除了重复,却以改变需求作为代价,而且这笔买卖并不划算。例如,之后我们需要处理针对不同的形状的不同操作,而且还有很多特殊情况。在我的抽象代码中实现这样的变更必须付出数倍的努力,而在原来那个“凌乱”版本中进行此类修改就非常容易。

那么,你应该编写“脏乱”的代码吗?当然不应该。我建议你仔细思考“整洁”和“脏乱”的含义。你有什么感觉?革命?正义?美丽?优雅?你如何确定这种质量会带来怎样的结果?而它们又会对编写和修改代码的方式造成怎样的影响?

我相信很多人都没有仔细思考过这些问题。我曾经深思过代码的外观问题,但是没有考虑过为什么他们会采用这种方式编写这些代码。

编程是一次旅行。想一想从第一行代码到如今,你走过了多少崎岖。当第一次通过提取函数或重构类将复杂的代码简单化时,我的内心也非常高兴。如果你对自己的代码感到自豪,那么也很容易抵制不住诱惑追求代码的整洁性。你可以进行一些尝试。

但你所做的努力不能仅限于此。不要成为一个执着于追求代码整洁的人。整洁的代码不是目标。这只是我们为降低系统巨大的复杂性而做的尝试。如果你不确定你的修改对代码库会造成怎样的影响,但你需要从千头万绪找到一个切入点,那么“整洁的代码”可以成为你的方向指导,但你必须学会及时放手。

原文:https://overreacted.io/goodbye-clean-code/

本文为 CSDN 翻译,转载请注明来源出处。

@所有人,别怕,疫情终会消失,而我们的陪伴才刚刚开始~!

武汉加油!中国加油!

爱你的CSDN~

你点的每个“在看”,我都认真当成了喜欢

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值