我们都曾偷偷做过这样的事情:趁妈妈不注意,偷偷品尝糖果零食,结果蛀牙上门。同样,我们在编程的世界里,也曾违背过一些基本规则,然后坚定地认定这样的行为不妥。但我们就是无法抗拒这些不良的编程习惯的魅力。
我们对编程规则嗤之以鼻,写出的代码也常常是“糙汉子”风格——但我们依然活得很好。编程之神没有降下闪电劈死我们,我们的电脑也没有因此爆炸。事实上,只要我们的代码能够编译并发布,客户似乎就很满意了。
这并非意味着糟糕的编程没有危害,只是它的危害并不像安装电路或摸老虎屁股那样直观。大部分时候,代码也能正常工作。规则往往被视为指导性的建议,不遵守也不会立刻导致代码死亡。你的代码可能会被人嘲笑,甚至公开受到嘲讽,但违背规则的行为能带来一种颠覆传统的快感,让人难以抗拒。
更有趣的是,有时候违反规则反而能带来更好的效果。(一般人我不告诉他!)这样的代码更简洁,甚至可能更快、更简单。规则有时候显得过于笼统,而有技巧的程序员可以通过打破规则来提升代码质量。别告诉你的老板,这样做对你的编程生涯大有裨益。
接下来,我要介绍的这9个编程习惯,虽然在编程规则中被批评,但很多人还是不由自主地使用它们。
编程习惯No. 1:使用goto
关于禁止使用goto可以追溯到很多结构化编程工具还未出现的时代。那时,程序员如果想创建循环或跳转到程序的其他部分,需要使用goto加上行号。几年后,编译器团队引入了字符串标签来替代行号,这在当时被视为一项创新。
有人认为这会导致“意大利面条式代码”,让代码变得难以阅读和理解执行路径。Edsger Dijkstra曾多次强调禁止使用这个命令,他有一份幽默的手稿,标题是《Goto语句害人不浅》。
绝对的分支并没有问题。这就让人很纠结。通常情况下,巧妙的break语句和return语句可以清晰地表明代码在那个时候的执行情况。有时候,在case语句中添加goto比用多层嵌套的if-then-else语句块更容易理解。
编程习惯No. 2:成功避开文档
我有个朋友有个精明的老板,他坚持每个功能都必须有文档。不写注释的程序员会受到惩罚。我的朋友在编辑器里用了一种类似人工智能的东西来生成“文档”。结果他的代码经常被当作正式文档使用。我觉得他可能快要升职了!
很多函数、方法甚至类都能自我文档化。一个名为insertReservation或cancelReservation的函数不需要额外的注释来解释其功能。给函数起个恰当的名字就足够了。实际上,这比写长篇大论的注释要好,因为函数名会在代码中出现,而文档通常默默地呆在角落。自文档化的函数名可以改进每个文件的使用体验。
有些时候,写文档反而会弄巧成拙。比如当代码快速变化、团队进行大规模重构时,文档很容易产生分歧。代码已经更新了,但文档还停留在几个版本之前的状态。这种情况下,良好的自文档化代码显然更有优势。
编程习惯No. 3:一行写太多代码
他认为他的法令将简化调试过程,让调试步骤像单步进行代码一样流畅。调试器将逐个动作进行,避免程序卡在某一行,让执行过程更加顺畅。
有时,在同一行内声明多个变量反而更加高效;有时将多个布尔子句组合在一起也更为简洁。这意味着我们可以在屏幕上看到更多的逻辑代码,无需滚动鼠标。代码的简洁性使得阅读和理解速度更快,这才是编程的真谛。
关于编程习惯No. 4:隐式类型声明
一些人坚持认为,明确为每个变量添加类型声明可以编写出更优质、更无误差的代码。花费一些时间来正确拼写类型,有助于编译器在代码运行前发现潜在错误。虽然这可能会让人感到痛苦,但确实很有帮助,是预防编程错误的一种有效方法。
时代在进步。许多现代编译器已经足够智能,可以通过查看代码来推断变量类型。它们会前后浏览代码,确定变量的类型,如字符串或整数。如果检测到的类型不匹配,编译器会发出错误提示。我们不再需要手动输入变量类型。
这意味着我们的代码可以省略一些最基础的声明,变得更加简洁清晰。阅读代码的人也能轻易理解循环中命名为i的变量代表整数类型。
关于编程习惯No. 5:灵活多变的代码
一些程序员在编写代码时犹豫不决,频繁更改数据类型的存储方式。虽然这看起来低效,有时甚至能感觉到CPU的负载浪费,但这种做法在某些情况下也是合理的。
想象一下,你正在使用一个出色的库,这个库内部包含许多智能操作。如果库需要字符串数据,即使你刚将数据存储为整数,你也应该直接提供字符串。
关于编程习惯No. 6:自定义数据结构的权衡
有一个通用的规则是鼓励程序员尽可能使用现成的数据结构,而不是自己编写。大多数所需的数据结构都已经经过长时间的测试和优化。但有时,标准库提供的数据结构可能不够高效,或者不符合我们的特定需求。
在这种情况下,编写自己的数据结构可能是必要的。这可以让我们更快地完成任务,并且避免包含不必要的代码。自定义数据结构可以让代码更加简洁高效。
关于编程习惯No. 7:循环中的中断
有一种观点建议在循环中使用“常量”来决定循环何时结束。这个理论有助于理解复杂的循环逻辑,但有时会导致代码过于复杂。例如,在遍历数组并测试每个元素的场景中,“常量”方法可能要求增加额外的布尔变量和逻辑判断。虽然适当的命名可以使代码更易于理解,但这增加了代码的复杂性。在某些情况下,使用goto语句或中间跳转可能更加简洁高效。需要在保持代码清晰和追求效率之间取得平衡。编程习惯No. 8:利用简洁的变量名——理解"i"、"x"背后的意义
正如Edgar Allan Poe的诗篇所述,故事中的每个词汇都有其内在含义。在编程的世界里,这一规则同样适用。变量名应该准确反映其代表的内容。虽然Java程序员经常使用驼峰式命名法,将变量的详细性质融入名称之中,但有时短小的变量名反而更加便捷。
在循环迭代中,"i"或"j"的使用已经深入人心,简单明了。字母"a"代表数组,"l"代表列表,尽管在某些情况下,字母和数字的相似性可能会带来困扰。这些短小的变量名同样具有自解释性,正如良好的编程习惯所倡导的,让代码自我说明,而非依赖冗长的注释。
编程习惯No. 9:重新定义运算符与函数——玩转编程语言的魔力
一些颇具魅力的编程语言允许你进行一些看似古怪的操作,如重新定义元素的值,就像处理常量一样。在Python中,你可以互换TRUE和FALSE的值(在Version 2.7及之前的版本),这并不会导致逻辑崩溃或宇宙终结,只是改变了这两个值的意义。类似的游戏也可以在C预处理器或其他语言中尝试。
请注意,这些编程习惯虽然引人入胜,但并非轻易可以尝试。无论它们看起来多么惊人,都可能带来潜在的风险。在尝试之前,务必谨慎评估其影响。
作者:码农网 – 小峰原文链接: |