如何写出让同事想拉黑你的代码:五个实用技巧

6,527 阅读10分钟

所有人都告诉你,要写干净的代码。要写容易维护的代码。他们说,代码是写给人看的,其次才是给机器执行的。

他们是对的。但他们没说,如果你不想让别人看懂,该怎么办。

这篇文章,就是关于“怎么办”的。它教你用五个简单又实用的技巧,把代码变成一座迷宫。一座只有你自己,在记忆力还好的时候,才勉强能走出来的迷宫。

命名,一场精心策划的迷失

混乱,是从一个名字开始的。一个好的名字像一盏灯,照亮一小块逻辑。而我们的目标,是关灯。或者,干脆把灯泡换成那种会闪的,舞厅里的那种。

代码的维护者,就像一个在黑夜里赶路的人。我们不必给他制造一堵墙。我们只需要把所有的路标都换成同一个方向。指向“迷路”的方向。

技巧一:用a, b, cdata构建你的词汇宇宙。

我刚开始工作的时候,总想给变量起个好名字。比如userProfileorderDetailList。后来我发现,这是在泄露天机。你的代码,三言两语就被人看穿了。这不行。

真正的大师,都用最简单的词。

a, b, c。这是基本功。在一个函数里,你可以有a, b, c, a1, b1, c1。它们之间可能毫无关系,也可能关系重大。谁知道呢。这不重要。重要的是,当你的同事看到变量c1时,他必须把整个函数的每一行代码都看完,才能猜出c1大概是个什么东西。

这强迫他进行深度阅读。你是在锻炼他的耐心和智力。他应该感谢你。

然后是进阶课:data

data这个词,妙就妙在它什么都说了,又好像什么都没说。它可以是一个从API返回的JSON字符串。可以是一个解析后的对象。可以是一个数组。甚至可以是一个布尔值,代表“有数据”这个状态。

我曾经写过一个函数,里面有个变量叫data。在函数的开头,它是一个整数ID。中间,它被查询数据库后的结果覆盖了,成了一个列表。在函数的结尾,它又被赋值为列表的长度。

后来,有个同事维护这段代码。他加了一个if (data)的判断。然后系统就崩溃了。因为他以为data是个列表,但他没料到,在某个分支里,data可以等于0。

你看。一个简单的data,就成了一个逻辑陷阱。这才是艺术。

函数,我的意大利面代码宣言。

我曾经也相信,函数应该像一块乐高积木。小,标准,功能单一。这样你才能搭建宏伟的城堡。

但后来我发现,一整块巨大的,未经雕琢的石头,更有纪念碑的潜质。它矗立在那里,无法被移动,无法被理解,只能被仰望。

这就是我们写函数的终极目标。

技巧二:一个函数解决所有问题,或者制造所有问题。

忘掉那些“单一职责原则”吧。那是给思想狭隘的人准备的。我们的目标是星辰大海,是一个能包罗万象的函数。一个“上帝函数”。

这个函数,它最好超过500行。1000行也不嫌多。它应该从接收用户请求开始,然后做身份验证,接着查询数据库,再调用三五个外部API,中间穿插着几十个if-else来处理各种业务逻辑,最后把数据格式化,记录日志,并发送一封通知邮件。

所有的事,都在一个地方完成。

这样做的好处是什么?

首先,是安全感。当所有逻辑都堆在一起时,你一眼就能看到所有东西。你不需要在几十个文件之间跳来跳去,那会让你头晕。所有代码都在这里,像一碗热气腾腾的意大利面,紧紧地缠绕在一起。很温暖。

其次,它能有效阻止重构。没人敢动这个函数。因为你只要轻轻拉起一根“面条”,比如修改一个数据库查询,可能就会导致邮件发送的逻辑出错。这种牵一发而动全身的精密设计,会让任何试图优化它的人望而却步。

你的代码,因此变得永恒。

我记得我写的那个process函数。它就是我的纪念碑。新人来了,看一周,不敢动。老人想重构,开三次会,最后决定“先别动,跑得好好的”。

它就在那里。处理一切。知道一切。它就是系统本身。

注释,沉默或谎言的艺术

技巧三:要么什么都不说,要么就误导他。

第一种境界:沉默。

“好的代码是自解释的。” 这是我最喜欢的借口。

所以,面对你那段包含五层嵌套循环和三个位运算的复杂算法,不要写一个字的注释。一个字都不要。

为什么?

因为这会激发后来者的探索精神。当他们看到这段天书时,他们不会轻易放弃。他们会花上几个小时,甚至几天,用纸笔,用debugger,去一步步追踪你的心路历程。这个过程,充满了发现的乐趣。他们会沉浸其中,忘记了时间,忘记了KPI,忘记了PM还在等着上线。

你给了他们一个纯粹的技术挑战。这是一种馈赠。

第二种境界:谎言。

沉默是金。但有时候,谎言是钻石。

写注释的最高艺术,不是解释代码做了什么,而是解释代码“曾经”做了什么,或者“将要”做什么,或者干脆解释一些完全无关的事情。

最经典的,是过期的注释。

那是一个周五的下午。我为了修复一个紧急bug,把一个函数的返回值从true/false改成了1/0/-1,分别代表成功、失败和待处理。我改了代码,测试了,提交了,发布了。世界恢复了和平。

但我留下了那个函数的注释。

// 该函数处理完成后,返回布尔值。成功为true,失败为false。

这个注释,像一颗时间的琥珀,完美地封存了历史。几个月后,一个新同事接手这块逻辑。他看到了我的注释,深信不疑。于是,他写了大量的 if (result == true)

然后,系统在一个没人预料到的地方,开始出现一些没人能解释的奇怪行为。

我没有骗他。我只是没告诉他全部的真相。我让他通过自己的努力,学会了考古,学会了怀疑。我又一次,不动声色地,推动了一位年轻人的成长。

逻辑,欢迎来到我的思想迷宫

直线是两点之间最短的距离。但最短的,往往也是最无聊的。

好的逻辑,应该像一条清晰的河流,顺流而下。而我的逻辑,更像城市的下水道系统。它也能到达终点,但过程曲折,黑暗,且充满了惊喜。

技巧四:嵌套,能嵌套就别分开写。

我曾经看到过一种建议,叫“卫语句”。就是把错误的、异常的情况先处理掉,让主干逻辑保持干净,一路通畅。

我试过。感觉代码变得太直白了。像一杯白开水。没有回味。

我更喜欢另一种结构:嵌套。一层又一层的if-else

想象一个场景:你要检查一个用户是否有权限访问某个资源。

正常的写法可能是这样:

if user == nil return false;
if !user.isActive return false;
if !user.hasPermission return false;
// ... do the real work

太简单了。一眼就看完了。

我的版本是这样的:

if user == nil {
    if user.isActive {
        if user.hasPermission {
            if resource.isAvailable {
                // 在这里,在屏幕的最右边
                // 才是那行真正有用的代码
                return true;
            } else {
                // 资源不可用
                return false;
            }
        } else {
            // 没权限
            return false;
        }
    } else {
        // 用户不活跃
        return false;
    }
} else {
    // 用户不存在
    return false;
}

你看到了吗?

这是一种美。一种结构上的美。代码的形状,像一个箭头,或者一个金字塔。它在视觉上就告诉了你,这是一个重要的,层层保护的逻辑。

维护这段代码的人,必须在脑子里维护一个栈。他每读深一层,就要把上一层的条件压入栈中。当他读到最核心的那行代码时,他的大脑已经经历了一场艰苦的跋涉。

这种体验,能让他对这行代码心生敬畏。

而且,当需求变更,需要增加一个新的检查条件时,乐趣就来了。他是应该加在第三层,还是第四层?加在哪里,对整个金字塔的形状影响最小?

这不再是写代码。这是在玩叠叠乐。充满了挑战和不确定性。

配置,把秘密刻在代码的基因里

代码是代码,配置是配置。要分离。这样你的程序才能像变色龙,在开发、测试、生产环境里变换自己的颜色。

我不太同意。

我喜欢更纯粹的东西。一个整体。代码和它运行所需要的一切,都应该封装在一起。像一个琥珀里的昆虫,从被封存的那一刻起,就再也不会改变。

技巧五:没有什么配置是不能硬编码的。

忘掉.env文件。忘掉config.yaml。忘掉环境变量。那些都是身外之物。真正的核心,应该刻在代码里。

我记得那个数据库连接字符串。它不应该待在冷冰冰的配置文件里,任人修改。它应该有心跳,有温度。所以我把它放在了UserManager类的一个私有方法里,一个大概在文件第873行的地方。

还有那个超时时间,3000。我把它直接写在了网络请求的参数里。http.get(url, { timeout: 3000 })。为什么是3000?不是2000,也不是5000?这是我和那段代码之间的秘密。一种默契。

这样做,你的代码就有了身份。它不是一个可以随便部署的通用程序。它是“为测试环境1号服务器”量身定做的特别版。独一无二。

当同事问我,“程序的数据库地址在哪儿配?”的时候,我可以平静地告诉他:“你改不了。得找我。”

你看,这不仅仅是代码。这是一种权力。

每一次环境变更,都成了一次庄严的代码发布。需要我,这个唯一的祭司,来主持仪式。这大大提升了部署的仪式感。每一次上线,都是一次代码的重生。而不是一次无聊的文本编辑。

恭喜,现在你是这座代码孤岛唯一的居民。

就这样了。

从一个模糊的变量名开始,到一个深埋在代码里的配置。你用这五个技巧,为自己建造了一座堡垒。

现在,你的同事不再来打扰你了。他们会在你的代码周围,小心翼翼地,开辟出新的道路。他们会把你的模块,当成一个神秘的黑盒。一个上古遗迹。只调用,不触碰。

你赢得了宁静。

你打开代码。还是那个熟悉的编辑器,还是那个熟悉的字体。但你感觉,自己也像一个外来者。你不太记得那个if嵌套的第五层,是为了处理哪个特殊的边界情况。你也忘了那个叫data的变量,在第200行和第300行的时候,分别代表什么。

你花了半天时间,才想起那个硬编码的IP地址,是当年测试环境里,一台早就下线了的服务器。

没关系。

这很正常。你亲手建造了这座迷宫,然后,也把自己困在了里面。

恭喜你。现在,你是这座代码孤岛唯一的居民。只是偶尔,你也会忘记回去的路。