2天时间,聊今年最热的 Agent、上下文工程、AI 产品创新等话题。2025 年最后一场~ 了解详情
写点什么

专栏:代码之丑(三)——switch 陷阱

  • 2010-11-24
  • 本文字数:1192 字

    阅读完需:约 4 分钟

又见 switch:

复制代码
switch(firstChar) {
case ‘N’:
nextFirstChar = ‘O’;
break;
case ‘O’:
nextFirstChar = ‘P’;
break;
case ‘P’:
nextFirstChar = ‘Q’;
break;
case ‘Q’:
nextFirstChar = ‘R’;
break;
case ‘R’:
nextFirstChar = ‘S’;
break;
case ‘S’:
nextFirstChar = ‘T’;
break;
case ‘T’:
throw new IllegalArgument();
default:
}

出于多年编程养成的条件反射,我对于 switch 总会给予更多的关照。在那本大名鼎鼎《重构》里,Martin Fowler 专门把 switch 语句单独拿出来作为一种坏味道来讨论。研习面向对象编程之后,看见 switch,我就会联想到多态,遗憾的是,这段代码和多态没什么关系。仔细阅读这段代码,我找出了其中的规律,nextFirstChar 就是 firstChar 的下一个字符。于是,我改写了这段代码:

复制代码
switch(firstChar) {
case ‘N’:
case ‘O’:
case ‘P’:
case ‘Q’:
case ‘R’:
nextFirstChar = firstChar + 1;
break;
case ‘T’:
throw new IllegalArgument();
default:
}

现在,至少看起来,这段代码已经比原来短了不少。当然这么做基于一个前提,就是这些字母编码的顺序确确实实是连续的。从理论上说,开始那段代码适用性更强。但在实际开发中,我们碰到字母不连续编码的概率趋近于 0。

但这段代码究竟是如何产生的呢?我开始研读上下文,原来这段代码是用当前 ID 产生下一个 ID 的,比如当前是 N0000,下一个就是 N0001。如果数字满了,就改变字母,比如当前 ID 是 R9999,下一个就是 T0000。在这里,字母也就相当于一位数字,根据情况进行进位,所以有了这段代码。

代码上的注释告诉我,字母的序列只有从 N 到 T,根据这个提示,我再次改写了这段代码:

复制代码
if (firstChar >= ‘N’ && firstChar <= ‘S”) {
nextFirstChar = firstChar + 1;
} else {
throw new IllegalArgument();
}

这里统一处理了字母为 T 和 default 的情形,严格说来,这和原有代码并不完全等价。但这是了解了需求后做出的决定,换句话说,原有代码在这里的处理中存在漏洞。

修改这段代码,只是运用了非常简单的编程技巧。遗憾的是,即便如此简单的编程技巧,也不是所有开发人员都驾轻就熟的,很多人更习惯于“平铺直叙”。 这种直白造就了代码中的许多鸿篇巨制。我听过不少“编程是体力活”的抱怨,不过,能把写程序干成体力活,也着实不值得同情。写程序,不动脑子,不体力才怪。

无论何时何地,只要 switch 出现在眼前,请提高警惕,那里多半有坑。

作者简介:

郑晔,ThoughtWorks 公司咨询师,拥有多年企业级软件开发经验,热衷于探索各种程序设计语言在真实软件开发中所能发挥的威力,致力于探寻合理的软件开发方式,加入 ThoughtWorks 公司后,投入到敏捷开发方法的实践之中,为其他公司提供敏捷开发方法方面的咨询服务。他的 blog 是梦想风暴

查看原文:代码之丑(三)

2010-11-24 17:557588
用户头像

发布了 22 篇内容, 共 14.8 次阅读, 收获喜欢 49 次。

关注

评论

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

【愚公系列】2022年10月 Go教学课程 027-深拷贝和浅拷贝

愚公搬代码

10月月更

QtCreator配置protobuf环境

中国好公民st

qt Qt Creator 10月月更

Java中的重载和重写的区别

共饮一杯无

Java 10月月更 重载重写

编程语言中 null 引用的十亿美元错误趣谈

汪子熙

Java JavaScript SAP abap 10月月更

【Ajv】JSON Schema Validator

小鑫同学

前端 Node 10月月更

标签与指标到底有什么区别?

雨果

标签 指标

谈谈前端性能优化-面试版

loveX001

JavaScript

SAP UI5 OData谣言粉碎机:极短时间内发送两个 Odata request,前一个会自动被 cancel 掉吗

汪子熙

JavaScript 前端开发 SAP UI5 ui5 10月月更

熬夜整理最近前端面试知识点

loveX001

JavaScript

从URL输入到页面展现到底发生什么?

loveX001

JavaScript

Qt | 实现动态创建多个Tab页,页中动态创建多个子部件

YOLO.

qt 10月月更 C++

技术分享 | 接口自动化如何处理 Form 请求?

霍格沃兹测试开发学社

构建工具Gulp-lesson4

小鑫同学

前端 Node 10月月更

正确发送统计数据到服务器

小鑫同学

前端 Node 10月月更

打包 Composition API、Vue3

小鑫同学

前端 Node 10月月更

Docker下Nacos持久化配置

程序员欣宸

Docker Spring Cloud nacos 10月月更

Docker load 大镜像(17G) 报错no space left on device

琦彦

Docker 10月月更 Base Device Size

通过linux-PAM实现禁止root用户登陆的方法

京东科技开发者

数据库 Linux 公有云 云主机 linux-PAM

【Java深入学习】线程状态

Geek_65222d

10月月更

如何搭建组件库的最小原型

小鑫同学

前端 Node 10月月更

西安交大谢涛:云上做实验,让计算机教学实现质的飞跃

Lily

20221013

留白的艺术

构建工具Gulp-lesson5

小鑫同学

前端 Node 10月月更

搭建组件库最小原型(支线)

小鑫同学

前端 Node 10月月更

Java数组详解

共饮一杯无

Java 数组 10月月更

Spring JPA 查询的时候提示错 org.hibernate.TransientObjectException

HoneyMoose

专访北大荆琦:产业前沿进课堂,通过产学合作培养开源贡献者

Lily

Vue2.x组件间通信汇总表

小鑫同学

前端 Node 10月月更

Java基础(四)| 数组及内存分配详解

timerring

Java 数组 内存分配 10月月更

HashSet源码全方位解读

知识浅谈

10月月更

Qt | 线程 QThread

YOLO.

c++ qt 10月月更

专栏:代码之丑(三)——switch陷阱_Java_郑晔_InfoQ精选文章