大家好😁。
上上周,我们在例会上送别了团队里的一位技术大牛,阿K。
说实话,阿K 的技术底子很强。他能手写 Webpack 插件,熟读 ECMA 规范,对 Chrome 的渲染管线了如指掌。
但最终,CTO 还是决定劝退他了。

理由很残酷,只有一句话: 你的代码,团队里没人敢接手。🤷♂️
为了所谓的极致性能,牺牲代码的可读性,到底值不值?
事件的开始
我们有一个很普通的后台管理系统重构。
阿K 负责最核心的权限校验模块。这本是一个很简单的逻辑:后端返回一个权限列表,前端判断一下用户有没有某个按钮的权限。
普通人(比如我)大概会这么写:
JavaScript
// 一眼就能看懂
const hasPermission = (userPermissions, requiredPermission) => {
return userPermissions.includes(requiredPermission);
};
if (hasPermission(currentUser.permissions, 'DELETE_USER')) {
showDeleteButton();
}
但是,阿K 看到这段代码时,露出了鄙夷的神情😒。
includes 这种遍历操作太慢了!我们要处理的是十万级的用户并发(并没有),必须优化!
于是,他闭关三天,重写了整个模块。
Code Review 的时候,我们所有人都傻了。屏幕上出现了一堆我们看不懂的天书😖:
JavaScript
// 全程位运算,没有任何注释
const P = { r: 1, w: 2, e: 4, d: 8 };
const _c = (u, p) => (u & p) === p;
// 这里甚至用了一个位移掩码生成的哈希表
const _m = (l) => l.reduce((a, c) => a | (P[c] || 0), 0);
// 像不像一段乱码?
const chk = (u, r) => _c(_m(u.r), P[r]);
我问他:阿K,这 _c 和 _m 是啥意思?能加个注释吗?
阿K 振振有词: 好的代码不需要注释!位运算是计算机执行最快的操作,比字符串比对快几百倍!这不仅仅是代码,这是对 CPU 的尊重,是艺术!
我: 。 。 。 。🤣
在那个没有性能瓶颈的后台管理系统里,他为了那肉眼不可见的 0.0001 毫秒提升,制造了一个维护麻烦。
屎山💩崩溃的那一天
灾难发生在两个月后。
业务方突然提了一个需求: 权限逻辑要改,现在支持'反向排除'权限,而且权限字段要从数字改成字符串组。
那天,阿K 正好去年假了,手机关机😒。
任务落到了刚入职的实习生小李头上。
小李打开 permission.js,看着满屏的 >>、&、| 和单字母变量,整个人僵在了工位上。
他试图去理解那个位移掩码的逻辑,但他发现,只要改动一个字符,整个系统的权限就全乱套了------管理员突然看不了页面,实习生突然能删库了🤔。
这代码有毒吧...... 小李在第 10 次尝试修复失败后,差点哭出来😭。
因为这个模块的逻辑过于晦涩,且和其他模块高度耦合(阿K 为了复用,把这些位运算逻辑注入到了全局原型链里),我们根本不敢动。
结果是:那个简单的需求,被硬生生拖了一周。 业务方投诉到了 CTO 那里。
CTO 看了眼代码,沉默了三分钟,然后问了一句:
写这玩意儿的人,是觉得以后都不用维护了吗?😥
过早优化是万恶之源 !
阿K 回来后,很不服气。他觉得是我们技术太菜,看不懂他的高级操作。
他拿出了 Chrome Profiler 的截图,指着那微乎其微的差距说:看!我的写法比你们快了 40%!
但他忽略了软件工程中最重要的一条公式:
代码价值 = (实现功能 + 可维护性) / 复杂度
过早优化是万恶之源 ! ! !
在 99% 的业务场景下,V8 引擎已经足够快了。
- 你把
forEach改成while倒序循环,性能确实提升了,但代码变得难读了。 - 你把清晰的
switch-case改成了晦涩的lookup table还没有类型提示,Bug 率上升了。 - 你为了省几个字节的内存,用各种黑魔法操作对象,导致后来的人根本不敢碰😖。
这种所谓的性能优化,其实是程序员的自嗨。
它是用团队的维护成本 ,去换取机器那一瞬间的快感。它不是优化,它是给项目埋雷。
什么样的代码才是好代码?
后来,我们将阿K 的那坨代码 通过 chatGPT 全部推倒重写。
1️⃣ 权限定义(语义清晰)
ts
// permissions.ts
export enum Permission {
READ = 'read',
WRITE = 'write',
EDIT = 'edit',
DELETE = 'delete',
}
2️⃣ 用户模型
ts
// user.ts
import { Permission } from './permissions';
export interface User {
id: string;
permissions: Permission[];
}
3️⃣ 权限校验函数(核心)
javascript
// auth.ts
import { Permission } from './permissions';
import { User } from './user';
export function hasPermission(
user: User,
required: Permission
): boolean {
return user.permissions.includes(required);
}
4️⃣ 批量权限校验
ts
export function hasAllPermissions(
user: User,
required: Permission[]
): boolean {
return required.every(p => user.permissions.includes(p));
}
export function hasAnyPermission(
user: User,
required: Permission[]
): boolean {
return required.some(p => user.permissions.includes(p));
}
5️⃣ 判断方法
javascript
if (!hasPermission(user, Permission.DELETE)) {
throw new Error('No permission to delete');
}
用回了用户权限结构清晰可见的,权限判断,一眼就懂。甚至都不需要注释🤷♂️
虽然跑分慢了那么一丁点(用户根本无感知),但任何一个新来的同事,只要 5 分钟就能看懂并上手修改。
这件事给我留下了深刻的教训:
-
代码是写给人看的,顺便给机器运行。
如果一段代码只有你现在能看懂,那它就是垃圾代码;如果一段代码连你一个月后都看不懂,那它就是有害代码。
-
不要在非瓶颈处炫技。
如果页面卡顿是因为 DOM 节点太多,你去优化 JS 的变量赋值速度,那就是隔靴搔痒。找到真正的瓶颈(Network, Layout, Paint),再对症下药。
-
可读性 > 巧技。
简单的逻辑,是对同事最大的善意。
阿K 走的时候,还是觉得自己怀才不遇,觉得这家公司配不上他的技术🤣。
我祝他未来前程似锦。
但我更希望看到这篇文章的你,下次在想要按下键盘写一段绝妙的、只有你看懂的单行代码时,能停下来想一想:
如果明天我离职了,接手的人会不会骂娘?

毕竟,我们不想让亲妈都不认识代码,我们更不想让同事在那骂娘。
谢谢大家👏