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

2020 年 2 月 06 日

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

夜深了。

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

代码可以运行。

但重复代码有点多。每一种形状(比如矩形和椭圆形)有不同的手柄,往不同方向拖拽手柄对形状的位置和大小影响也不一样。如果用户同时按住 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);

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

原文链接:【 https://www.infoq.cn/article/dNO484YEeumvC6b6ZNWL 】。未经作者许可,禁止转载。

登录后可解锁全站优质内容

免费畅享技术公开课、顶尖技术团队访谈、一线互联网大厂技术实践

文章
视频
电子书
研究报告
立即登录
2020 年 2 月 06 日 14:52 11907
用户头像
小智 InfoQ高级编辑

发布了 180 篇内容,共 4032 次阅读,收获喜欢 23 次。

关注

评论 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
回复
没有更多评论了
发现更多内容

跨专业学习6个月,成功上岸阿里|滴滴,分享学习路线供大家参考

小Q

Java 学习 架构 面试 基础

实战案例丨GaussDB for DWS如何识别坏味道的SQL

华为云开发者社区

数据库 sql 算子

数字货币交易所技术开发,交易所源码

13530558032

天猫成立房产部门,利用区块链承载交易多项服务功能

CECBC区块链专委会

区块链 房地产

卧槽!牛逼了!40K+Star!Mall电商实战项目开源回忆录!附源码、教程合集

云流

架构师 计算机 程序员成长 编程学习

HTTP必知必会

陈靓-哲露

未来已来!全球一流科技盛会——云栖大会9月17日线上隆重举办

北柯

数字资产钱包开发方案,区块链数字钱包软件源码

13530558032

区块链支付系统开发技术方案,USDT支付系统搭建

13530558032

入行架构师之前,这7项技能你要先了解一下

华为云开发者社区

架构 架构设计 架构师

Spring-boot 单元测试

陈靓-哲露

本以为自己MySQL够牛逼了,直到亲自去阿里受虐了一次!

Java架构师迁哥

数字经济时代来临 区块链护航数字资产安全

CECBC区块链专委会

金融 数字时代

银行数仓体系发展之路

易观大数据

易观方舟Argo+CRM | 让企业数据发挥更大价值

易观大数据

git的几种实用操作(合并代码与暂存复原代码)

良知犹存

git

当代开发者的好帮手,浅析.NET敏捷开发框架的优势与特点

Philips

敏捷开发 软件开发 .net core 开发工具

Java异常面试题(2020最新版)

Java架构师迁哥

区块链技术智能合约有哪些实际的应用场景

CECBC区块链专委会

智能合约 区块链技术

DDD+微服务实战:什么是DDD?

深度码农

微服务 领域驱动设计 DDD

为什么企业需要CRM系统?CRM的作用及其重要性分析

力软.net/java开发平台

软件开发 信息化 CRM

TCP和HTTP中的KeepAlive机制总结

陈德伟

nginx TCP 性能 网络 HTTP

Java-技术专题-JMX超详细解读

李博@Alex

面试官:你说说互斥锁、自旋锁、读写锁、悲观锁、乐观锁的应用场景

小林coding

乐观锁 高并发 操作系统 计算机基础

AWS在线技术峰会2020探班回顾,四大看点不容错过

Yumiko

云计算 AI 云原生 金融 医疗

QPS、TPS、RT、并发数、吞吐量理解和性能优化深入思考

科技缪缪

架构 编程语言

从想当亿万富翁到职场、创业、爱情、抑郁、学医学武,我的程序人生

陆陆通通

Java 创业 程序员 爱情 程序员生活

LeetCode题解:622. 设计循环队列,使用双向链表,JavaScript,详细注释

Lee Chen

LeetCode 前端进阶训练营

智慧公安重点人员管控系统平台开发,智慧警务系统

13530558032

Spring Boot CLI 介绍

hungxy

Spring Boot Spring Boot CLI

Java-技术专题-AQS和Volatile和Synchronized实现原理

李博@Alex

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