从心理学上来讲,当人们违反规则甚至破坏规则时,会感觉到有点儿刺激。
比如在限速 55 公里的地方,我们以 80 公里的速度行驶,或者让停车计费表失灵等等。
在软件开发领域,比方说在没有测试分母不为零的情况下将两个数字相除等。因此说来,程序员们与规则有着各种奇奇怪怪的关系。
一方面,代码包含着一大堆规则,这些规则被尽职尽责的开发者门无限放大地应用,没有恐惧或偏爱,我们总是希望没有奇怪的事情引起BUG。我们甚至希望硬件的晶体管也完美地遵循这些规则。
但还有另一层规则并不怎总那么“神圣”。
与我们向机器提供的指令不同,我们是人,那么为自己制定的规则应该是高度灵活的,就像弹簧一样。有些只是纯风格上的,另一些的目标是在为不规则的代码带来一致性。这套规则适用于我们所做的事情,而不是机器的响应方式。
真正的争论,人类能否打破自己的规则。我们有权利随时重新解释这些规则。也许是因为有些规则来自不同的时代。也许有些规则从一开始就是不成熟的概念,也许有些规则在当时看起来是个聪明的想法,还有一些规则最好是被称为“习惯”。
这里面,我们整理了一份开发者们“暗恋的”坏编程习惯清单。目标为了提高编程艺术,这里还包括另外 10 个编程习惯。
没有注释的编码
我们都知道,没有文档的代码很难阅读、理解和调试。
因此,我们的编程课除了教人们写好代码,还有写出好的注释也非常重要。文学式编程,即结合自然语言和代码的编程风格。
Don Knuth ,文学式编程提出者。著名计算机专家
这是最早由 Don Knuth 发明的,他可能是有史以来最伟大的程序员。我们还有什么资格可争论的吗?
但事实可能有点不一样,有时注释会让事情变得更糟糕。
有时,文档的内容与代码关联并一定大。有时写文档的人甚至远离编码团队,处于另一种状态。也许编码人员在没有告诉文档团队的情况下推出了一个关键补丁,或者文档团队知晓但尚未更新注释。有时,编码人员可能没有更新更改的方法顶部的注释。文档工程师只能自己解决这个问题。
还有其它一些问题。也许注释是用你不了解的自然语言写的。也许这个概念无法用少于七段的文字轻松概括,而程序员正处于敏捷冲刺阶段。也许注释写的就是错的。
出于以上这些原因,一些开发人员认为解决无用注释的最佳方法是少加注释,甚至不加注释。相反,他们更喜欢编写简单、较短的函数,并使用较长、描述性强的驼峰式变量名作为指导。如果编译器没有错误,代码应该最准确地反映计算机正在做的事情。
运行慢的代码
如果你希望你的代码运行速度变快,那就让它简单一点。如果你希望它运行得更快,那就让它复杂一点。
但是找到这个特定任务的最佳平衡点并不容易。
这对于开发者来说的确是一种平衡。一般来说,我们希望程序运行速度很快,但如果以后没人理解,那么复杂性就会成为累赘。因此上,如果速度不是必需的,那么编写速度稍慢点,但更容易理解的代码也是有意义的。
有时,简单、略慢一点比超级聪明和超级快速的代码,是更好的选择。
新奇古怪的代码
我的一位同事特别喜欢使用 JavaScript 中刚出来的新运算符,这些符号设计很巧妙,例如省略号(...)。这样让生成的代码更加简洁,在他看来这意味着更简单、更好看。而他们所有的代码审查都会返回给我,我会根据注释看到哪里重写了代码,以及使用新语法后的建议。
我的其他一些同事不太确定越简单就越容易理解。阅读代码需要理解新的运算符,其中一些运算符可能以各种不同的方式运用。理解运算符的使用方式需要停下来深入思考,而不是像他们习惯的那样快速浏览。这样,阅读代码变成了一件苦差事。
关于人们为什么不喜欢超前代码,也有一些历史争论。像 APL 这样的语言,由于其自定义符号设计得非常紧凑和高效,但实际上已经消失了。其他语言,如Python,它避开了大括号,如今继续在流行。
最新和最伟大的抽象爱好者,继续推动着简洁的新功能,并吹嘘简洁的优势。他们宣称自己是现代以及时髦的。然而,还是有人会继续将更长、更易读的代码偷偷地放入技术堆栈中;他们知道,最后这样才会更容易阅读。
古老的密码
设计编程语言的人喜欢发明巧妙的抽象和语法结构,以使解决某些类型的问题变得轻松一些。他们的语言充满了这些抽象,但这就是为什么有时他们的手册长达一千多页的原因。
有些人认为使用这些功能是最好的。毕竟他们说过,权力的首要规则是“使用它或失去它”。难道我们不应该使用那本一千页手册中描述的每一滴语法糖吗?
但是,这并不总是一个好规则。太多的功能可能会造成混乱。
现在有这么多巧妙的语法糖、编程花招,估计没有一个程序员能够完全精通它们。我们为什么要精通呢?比如说,我们需要多少种方法来测试无效性,或者使继承在多个维度上起作用?其中一种是正确的,还是比其他的更好?当然,团队中的一些程序员会想方设法通过争论这些来制造戏剧性游戏,从而毁掉你的午餐或站立会议。
至少有一组语言设计者决定了功能集的限制。
比如 Go 语言的创建者就表示,他们希望构建一些可以很快学会的东西,甚至可能在一天之内搞定。这意味着团队中的所有程序员都可以阅读所有代码。因为更少的功能可以减少混乱。
编写属于自己的代码
效率专家喜欢说:“不要重新发明轮子。” 也就是要使用经过充分测试,并准备好运行的代码库。
嗯,是的,请使用已经经过验证的遗留代码。
但是,有时候新方法也是有意义的。库通常是为通才和日常用例编写的,它们装载了安全带和吊带测试,能够确保数据一致,并且用户不会因为发送错误的参数而搞砸工作。如果遇到了特殊情况,几行专门的代码就会大大加快开发速度。它不会做代码库能做的所有事情,但它可以用一半儿的时间内完成你所需要的事情。
在某些情况下,这样做可能会带来“危险”。有些代码非常深奥与复杂,比如在加密系统中,即使你知道所有的数学知识,拼凑起来也不是一个好主意。但在适当的情况下,当库成为你工作量的最大瓶颈时,一些巧妙的替换函数便会产生奇迹。
代码优化的太早
程序员通常会将一些代码放在一起,并用“过早优化是浪费时间”这一旧的格言来证明他们的快速工作是合理的。
我们的想法是,在启动整个系统之前,没有人知道代码的哪一部分将成为真正的瓶颈。如果每年只调用一次,那么浪费时间来构建一个出色的函数是不明智的。
以下是一个很好的经验法则。有些项目因为太多的过度规划、过度优化而未能冲出起跑线。但在很多情况下,只要稍微深思熟虑,就可以产生很大的不同。有时,选择错误的数据结构和模式,会产生事后不容易优化的架构。有时,它们的结构已经融入到代码的许多部分中,以至于一些巧妙的重构并不能解决问题。在这些情况下,一些过早的优化最终是正确的答案。
疏忽
每个人都知道,优秀的程序员在穿过单行道之前,都会先看看两边。他们插入大量额外的代码行,在对数据进行任何操作之前总是对数据进行双重甚至三次检查。毕竟,空指针可能会滑入其中!
唉,所有这些额外的关注可能会减慢我们的代码运行速度。有时,出于性能原因,我们需要忽略一些直觉,只编写那些不太在意的代码。如果我们想要运行速度快的代码,我们应该只做最低限度的事情,不要做更多。
不一致
做技术的人们通常喜欢秩序。程序员们经常坚持一堆代码的每一部分都要使用相同的技术、算法或语法。我们这样的勤奋可以让后来理解代码人的工作变得容易。
但是从另一方面来讲,一致性需要付出时间成本,有时也会增加复杂性。修复差异意味着要回头重写所有“走错路”的代码。仅此一项就会给预算成本造成压力。
更深层次的问题还有不同部分之间的关系。有些项目依赖于遗留代码。其他依赖于库。如果没有来自不同公司中不同的人来编写 API,许多系统功能是无法运行的。
消除这些群体之间的差异通常是不切实际的,而且你想重写整个堆栈以适应最新愿景的次数有限。我们大脑的一个奇怪的角落渴望完美的秩序,但也许最好是与不一致和平共处。
追求花哨的东西
过于一致性的另一个问题是阻碍创新,它还鼓励严格遵守旧的做事方式。
有时添加新功能、加入新库或将堆栈与新 API 集成,这意味着打破旧模式。是的,这会让那些在阅读代码时必须换个思路的人的生活变得困难,但这是进步的代价。这也是让编码变得很有趣的一部分原因。
打破规则吧
为了让自己一笑,我询问了 Google 的 Gemini:“程序员在创建它的过程中是否违反了相关规则?”
Gemini 回答说:“与其说程序员违反了特定规则,不如说他们在创建像我这样的大型语言模型时可能突破了一些最佳实践的界限。”
“像我这样的大型语言模型需要训练大量数据,而模型如何从这些数据中学习存在一些“未知”因素。一些用于创建大型语言模型的技术可能非常有效,但很难准确理解模型如何得出答案。”
就这样吧,连大语言模型都比我们更清楚旧规则正在发生变化。
当你可以将大量训练集输入到盒子里时,你可能不需要花费太多时间来理解算法。所以,让大模型来遵守规则,我们继续做个真实的人吧!
作者:场长
本文为 @ 万能的大雄 创作并授权 21CTO 发布,未经许可,请勿转载。
内容授权事宜请您联系 webmaster@21cto.com或关注 21CTO 公众号。
该文观点仅代表作者本人,21CTO 平台仅提供信息存储空间服务。