当前位置: 首页 > news >正文

坏的代码如何坏

这篇文章觉对不是 AI 写的

坏的代码如何坏。

它们常常不是一眼就能看出问题,而是让人眼神游离、心口发紧,在注释和变量名之间来回打量,始终搞不清楚「这玩意到底在干嘛」。


一、坏的命名让人晕头转向

int x, y, z;
if(x) y += z;

你知道 x 是不是代表「游戏结束」?不知道。y 是不是得分?不知道。z 是不是行数、奖励值、满行计数器?还是不知道。

这样的代码就像一个没有标签的药瓶,服了可能治病,也可能直接去世。特别是对于一个月后要调这个 bug 的你自己。

坏命名例子:

  • tempflagcnt1cnt2val1val2posxpozy
  • map1map2q1q2pppppp
  • CC2C3CCCCC(洛谷特别高发)

这些命名并没有犯错,但只要你忘了上下文,它们就像一只披着布的幽灵——你知道它在场,但你不知道它是谁。


二、结构混乱导致依赖地狱

for(int i = 23; i >= 0; i--) {if(full(i)) do_down(i);
}

这段代码单看没毛病。逻辑是「从下往上检查每一行,满了就往下压」。但实际运行时,i = 21 时那一行是不是已经被之前的 do_down(22) 改了?我们不知道。

这种 “后面代码依赖了前面代码修改的数据结构” 的模式最容易出问题。

改法是将操作“纯化”,用临时数组替代原数组写入。每个步骤都在自己的宇宙中运行,不踩别人脚。


三、重复代码藏 Bug

void moveUp() { ... }
void moveDown() { ... }
void moveLeft() { ... }
void moveRight() { ... }

四个方向写了四个函数,看起来清爽,但改一个忘一个。稍微加点规则,比如不能穿墙,你要记得改四处。

理想方式是抽象成一个 move(dx, dy),将方向变成参数控制。甚至进一步抽象成 (x + dx, y + dy) 向量,配上一个方向数组。

const int dx[4] = {-1, 0, 1, 0};
const int dy[4] = {0, -1, 0, 1};

循环统一逻辑,维护成本立刻降低。


四、没有封装,满地 if else

if(state == 1) doA();
else if(state == 2) doB();
else if(state == 3) doC();
...

当你的状态变得多、行为变得复杂之后,这种代码就像一个长满瘤子的章鱼——每一只触手都在乱动。

封装是解药,状态转移表或者 switch 配合函数指针,甚至用面向对象都能清晰表达。


五、一锅烩函数让人迷路

void process() {...if(...) { ... }for(...) { ... }if(...) { ... }for(...) { ... }...
}

函数太长、做太多事。你无法复用,无法测试,无法理解这个函数的意图。

拆成多个小函数,每个函数有清晰名字,是最基本的自救方式。


六、误导性的注释

// delete the last row
for(int i = 0; i < n; i++) {a[i] = a[i+1];
}

问题一:这段代码其实是把所有行往上移。
问题二:a[n] 越界没看到。
问题三:注释和行为不一致。

这类注释非但不帮忙,还在挖坑。

注释的原则是:「要么准确,要么闭嘴」。


七、魔法数字满天飞

for(int i = 0; i < 23; i++) { ... }

23 是啥?底部?高度?地图宽度?没人知道。

改成:

const int Bottom = 23;
for(int i = 0; i <= Bottom; i++) { ... }

这时候你看到“23”,知道它不是随便拍脑袋拍出来的。更重要的是,你不会在十几个地方反复写错。


八、奇怪缩写,让人做梦都想不明白

int cmpf;
bool spt;
unordered_map<int, pii> ct2sz;

看起来像密码。缩写是对自己方便,但对读者是迷宫。

用完整命名,哪怕长一点,读得懂比省几个字母更重要。


九、结构乱到无法测试

每次你想「调一下这里看看问题在哪」,但这个地方引用了另外一个函数,这个函数还依赖全局变量、还涉及别的模块,最后发现你根本无法 isolated test(隔离测试)一个模块。

写代码时不考虑「如何测试」,调 bug 就像在黑夜里找丢了的头发。


十、无条件 return 或 continue,偷懒导致的 bug

for(...) {if(fail) return;do_something();
}

你以为 return 后面什么都不重要了,但其实可能打断了整个流程。上一个输入的数据影响了下一个输入,比赛直接罚时。

这种「流程跳转」要极其小心,return、continue、break 都是潜藏炸弹。


所以说,好代码的反面不是“写得烂”,而是“写得让你自己都不敢碰”。你会发现每次改动都小心翼翼,生怕哪个 if 被炸飞,哪个变量名让你看错。写得像是埋雷,不像在种花。

我们都写过坏代码,但我们都能改,哪怕一点点变清晰,都是好事。写得让自己未来回头看也会觉得:“诶,还行嘛。”就已经很厉害了喵~

http://www.sczhlp.com/news/6727/

相关文章:

  • 硅空位中心实现量子网络化的新突破
  • linux gpio-leds 作为硬盘指示灯
  • Goframe框架SetFileServerEnabled关闭静态服务不生效
  • 线段树算法:结合水果成篮的初步理解
  • 批量生成多个excel文件数据
  • Python多进程写入文件
  • CSP 镇
  • P10831
  • SPA单页面是什么,它的优缺点分别是什么?
  • 8/6
  • CF1396C Monster Invaders
  • 从零到英雄:掌握神经网络的完整指南 - 详解
  • ARC 203 C(组合计数+容斥)
  • CF1693C Keshi in Search of AmShZ dijkstra好题
  • git分支
  • 模拟赛SXJ202507300900比赛记录题解
  • 【算法】Hungarian Algorithm 匈牙利算法
  • 03.接口vs抽象类比较
  • python中的列表
  • function calling的简单实现
  • 数论反演、变换这一块
  • 广义串并联图
  • 【渲染流水线】主线索引-从数据到图像以UnityURP为例
  • CodeChef-SAFPAR
  • 给定二叉树的根节点 root,判断它是否 轴对称(镜像对称)
  • 工具
  • C# CIP协议2
  • AI应用开发-从Python入门到GPT集成实战 - IT
  • CI2306 开发套件
  • 【UEFI】启动项