从业 20 年的程序员,“盘”出来的 5 种编程经验
一个拥有 20 年编程经验的“熟手”,编程干货有多少?本文的作者是一名从业 20 年的程序员,在本文中,他分享了自己这 20 年来学到的 5 种编程经验:重复的知识最糟糕、把代码当成一种债务、对高级开发人员信任但去验证、使用 TDD、用“证据”证明自己的代码更好。下文是关于这 5 种经验的具体描述。
今年,我对 DEV 开发平台越来越熟悉。众多激愤的 Reddit 评论者和“不过如此”的鉴赏家们构成了一片荒漠,在这片荒漠之中,DEV 已经成为了一个令人耳目一新且充满积极力量的绿洲。
这个社区有着很有趣的一面,它似乎非常注重初学者。我经常在这里看到行业新手写的帖子。我所说的新手是指那些在训练营中寻找入门级工作,或者那些在不幸的“初级”程序员岗位上工作的有抱负的程序员。
我觉得这很有趣。相对的新手,通常对这个行业充满着热情和激情,这种激情是有感染力的。但这也让我觉得自己是这个行业的熟手。
我想起鲍勃·马丁在播客或演讲中说过的话。
在过去的四、五十年里,行业对程序员的需求急剧增长,以至于程序员的数量总是每五年翻一番。因此,拥有 5 年经验的程序员占据着整个行业一半以上的职位。
熟手的地位
我在这个行业已经快 20 年了。其中 10 年,我的主要职责是编写代码。另外 10 年包括管理程序员、指导他们、向组织咨询如何管理他们、施行代码库评估实践以及当前从事的内容营销。
但在所有这些角色中,我或多或少地也都会编写代码。
根据我的计算,程序员数量呈几何级增长,这让我比这个行业中 94% 的人头发更白。
所以我们的差距并不大。我是混迹在编程新手周围中一名的“职业”程序员。
于是,我提醒自己说:“如果我能把这段经历进行简明扼要地总结(假设真的有人关心的话),我会向他们提些什么建议呢?”
所以,就产生了这篇文章。以下是我认为自己在 20 年编程生涯中最重要的经验和收获。
1. 重复的知识最糟糕
“避免复制粘贴式编程!”
当你在应用程序中复制、粘贴代码,然后调来调去的时候 (“复制、粘贴、调整”反模式),如果没有人打你的手,那么现在就考虑举起这根“戒尺“吧。
阻止它!立即!这种做法很糟糕,也很随意。
假设,你有一个用得好好的 CalculateBill() 方法,但是产品经理却走过来说:“我们正在墨西哥接待新客户,与你那个计费的方式有点不同。”因此,你可以复制当前这个方法,粘贴它,将其重命名为 CalculateBillMexico(),并根据需要对其进行调整。
以下是使用这种方式所产生的问题:
- 如果将来的变更需要对核心逻辑进行调整,你现在必须额外去修改这两个方法。
- 在做此类变更的时候,现在你就有 2 个引入 bug 的可能。
- 你现在已经建立了一个“设计模式”,随着在全球的继续扩展,你的代码需要一个又一个新的、冗余的方法。
- 你的工作量将会急剧增加。
- 忘记修改需要修改的地方,从而引入 bug,这种情况只是时间问题。
- 最终,所有这些方法都会有一定的差异,这些差异足以令你无法合理地将它们合并起来修复这种混乱,但是差异又没有大到可以避免有人在更新一条计费规则时改上 20 次。
这是一个烂摊子。然而,“复制 - 粘贴”只是表层问题。
复制 - 粘贴只是开始
真正的问题是系统中的知识重复。
在你的系统中,知识的复制可以以多种方式出现,蹩脚的复制 - 粘贴是最明显和最笨拙的。看看其他知识重复的例子:
- 一个 for 循环,在它的正上方有一个解释开始、结束和递增的代码注释。
- 为一个全局变量内联赋值,然后 (可能) 从配置文件中取一个值重新赋给它。
- 包含“PretaxTotal”、“Tax”和“Total”列的数据库表
- 一个范围很广的 ERP 系统,它将客户存储在 CRM 模块中,然后再存储在计费模块中。
有了以上所有这些,最好的情况是,你有适当流程和系统来努力地跟踪副本,并确保同时更新它。
如果缺乏代码注释,可能团队的首席唠叨官在你更新代码时就会一直在你耳边念叨,检查注释、检查注释。
或者,以那个 ERP 系统为例,它可能是一个严格的部门备忘录,告诉销售和会计,他们都需要发送正式的电子邮件,以确保客户信息保持同步。
记住,这些已是最好的情况。
当你开始构建复杂的逻辑 (之后你必须维护它,请参阅下一节) 以确保同步时,会出现更糟糕的情况。
也许你可以实现一个数据库触发器,在“total”列发生更改时确保 PretaxTotal + Tax 仍然等于 total。或者,你可以编写一些笨拙的状态检查逻辑,当默认的全局变量值与要赋的配置文件中的值不匹配时,记录一个警告。
最糟糕的情况是数据不同步。那么,你作为一名程序员,可能不用担心它,因为你拿的那份工资所要承担的工作不包括搞清楚为什么你们从来没有给客户开过发票,或者为什么多年来一直多收客户的钱。
但是,面对藏身于系统各处的知识重复,无情地根除和积极地抵制可以帮你避免所有这些问题。
2. 代码是一种债务
作为开发人员,我们要学会热爱代码。编写代码感觉很好,创造些什么出来也很令人兴奋。
此外,我们寻找新的语言、范例、框架、堆栈、工具、api 和库来学。我们沉浸在自己的世界里,并为“心流”而欢呼,因为在这种状态下,我们可以愉快地生产代码。
在这场庆典中,我们并不孤单。
误入歧途的极端分子甚至把每小时生成的代码行数作为生产力的度量标准。但即使你没有达到武器级的愚蠢程度,也很容易认为代码越多越好。代码是你们杀手级应用程序和业务的 DNA,公司认为它是有价值的知识产权。
然而,忘了这一切吧。
我能理解为什么我们把代码看作资产。但事实是,代码完完全全就是一种债务。
少即是多
你知道什么比用 10 行代码来编写别人用 100 行代码来完成的事情更好的吗?那就是用 0 行代码。
写这么一行代码:
复制代码
printf("Hello World!");
你认为有多少事情会出错?
- 这段代码会在允许控制台打印的环境中运行吗?
- 那段神奇的字符串以后不会成为问题吗?
- 你不应该记录日志吗?这是一条最佳实践。
- 你有没有想过这对安全的影响?
保守地说,这行代码中有 10 个地方可能出错。现在,我们加上第二行。
你觉得这会导致总共 20 件可能会出错的事情吗?
我认为几乎得有 100 件。你可以叫我是悲观主义者,但我认为潜在问题与代码行之间的关系更接近于组合而非线性。
实际上,我做过几年管理顾问,具有特别的职业特殊性。我做数据驱动的代码库评估,并帮助 IT 领导层制定代码库相关的战略决策。
所以我看过、分析并收集了大量代码库的统计数据。
如果算上在客户那儿自动分析的代码库,那么我已经收集了 1000 多个代码库的详细统计信息。然后,为了寻找相关性我对这些数据进行了回归分析。
你知道什么与不良的代码库的相关性更强吗?那就是代码库的大小。
几乎关于代码库的所有坏事都与代码库的大小有很大的关系(以代码的逻辑行来衡量)。
我爱代码,我喜欢写它、研究它、分析它,和用它做东西。但毫无疑问,它是一个巨大的债务。我们应该总是努力用尽可能少的代码来做每件事。
3. 高级开发人员:信任但验证
在我 23 岁时做了第一份软件工程工作,当时我对那里的高级开发人员怀有一种近乎狂热的崇敬。保罗、雷蒙德、克里斯、肯,平均每个人大约有 20 年的从业经验,我可以生动地描绘出他们所有人的样子,我发现他们对多种编程语言的熟练程度令人惊叹。
我从他们身上学到了很多。
我提到这些是因为我想适当地铺垫一下接下来要说的话。
如果你是这个行业的新手,你可能会像我一样,认为团队中资深开发人员的每一句话都是智慧的结晶。而且,如果你幸运的话,他们中的很多人的确是这样的,特别是一开始的时候。
但是并不是所有的高级开发人员都如此。
回想起来,我上面列出的那些人实际上都是很好的程序员,我从他们身上学到了很多东西。但我也认识到,在我的职业生涯中,我幸运地摆脱了最初的影响。
既有优秀的、乐于助人的高级开发人员,也有能力并不出众的小人物,这些人的主要资历不是技术专长,而是在那儿很长一段时间无所事事,设法不被解雇,并靠混资历晋升为“资深”或“高级”之类的头衔。
这种现象非常普遍,几年前我编造了一个词来描述它,现在每个月都有数百条谷歌搜索。当我创造了“专家级初学者”这个术语时,它引起了人们的强烈共鸣,最初的帖子像病毒一样得到了一遍又一遍地传播。
戴尔将告诉你所谓的专业的对象关系映射是怎么回事。
我说这些不是为了炫耀。我这样说是为了提醒你,许多高级开发人员表面上看起来名副其实,但实际上并不是。
所以,当你是新人的时候,要相信前辈的说法,尊重他们,但不要想当然地认为他们说的就是对的。自己得验证一下,当然了,最好不要在当着他们的面验证。
4. TDD 真的行,它改变了游戏规则
当涉及到任何编程,甚至只要是与技术相关的事情时,我们往往会因为带有偏见的主观选择而发疯。
- IDE 与轻量级编辑器的讨论?
- 苹果、Windows 还是 Linux?
- 你怎么看 PHP?
- 制表符(tab)还是空格(space)?
拿出其中任何一个,看看那些持明确观点的人愚蠢的争吵。因此,考虑到所有这些,我意识到我正在陷入类似的境地,那就是“做 TDD 还是不做 TDD”。
我的目的不是说教,而是分享我自己的经验。
大约 10 年前,我是 TDD 怀疑论者。我并不是单元测试的怀疑论者,提醒一句,我从一开始就接受了它,并将其作为一种有用的实践。
但 TDD 呢?我不太确定。
我决定写一篇博客来解释为什么 TDD 没那么好。
但我不想就这件事写一篇站不住脚的、蹩脚透顶的评论文章。所以我决定做一个严格遵循 TDD 的小型客户项目 (顺便一提,固定价格),这样我就可以写一篇文章,但这篇文章的前提是“我花几周时间做纯粹的 TDD,但发现它并不好”。
但是,命运另有安排。
我的天啊!时时刻刻与 TDD 相伴
这是尴尬而怪异的一天。实际上,可能是好几天。
每件事都要花很长时间,我感觉做每件事都很麻烦,很不自然。我只是一桩一桩地把它们记录下来,以证明为什么这是一种糟糕的做事方式。
但是,有趣的事情发生了。
我对这个笨拙的范例如此着迷,以至于有一天我花了 4-5 个小时编写代码,却没有实际运行应用程序来查看我的更改是否有效。通常,我会每隔 10 分钟左右运行一次应用程序的,以检查我的更改是否真正有效。
意识到我已经工作了几个小时,我启动了应用程序,叹了口气,感觉必须得调试上几个小时了。毕竟,以前的我至少需要调试 30 多回。
但是,不可思议的事情发生了。一切都能正常运转。
一切都运转得很完美,第一次没有任何异常。绝对没有任何意外。我花了几个小时编写代码,没有查看自己的 GUI,也没有在运行时验证任何东西,但所有的一切都运转正常。
我写了另一篇关于 TDD 的文章。这一次,我再也没有反悔。
我学习了这种技术,掌握了它,还讲授了它的相关课程,做了它的相关咨询,并围绕它进行了开发人员培训。但除此之外,我调查了单元测试对代码库的影响,发现这些影响无疑都是好的。
学习 TDD 的知识技能吧。你不会后悔的。
5. 证据为王
到目前为止,在这篇文章中,我已经提到了我的代码库评估实践,并讨论了经验数据。让我们正式来聊聊我目前职业生涯收获的最后一点经验。
证据就是一切。
代码评审可以作为一种教育性的、赋能的活动,或者他们可以处决你的灵魂。
然而,他们很可能会在启发性的体验和无意义的争吵之间来回摇摆。
你会听到诸如“那不是一个好的设计”或“那没有效率”之类的话。你可能也会说这些话。你很可能在没有任何证据的情况下听到或说出这些话。
解决这个问题。
证据的重要性
如果在代码评审过程中,或者你的团队或组织内的任何其他形式的协作过程中,有人对你横加指责,那么证据就是你的朋友。如果你试图向管理层或领导层解释任何事情,证据就是你的朋友。
证据会为你赢得争论、尊重、领导角色和职业晋升。
你是否认为团队大量使用全局变量会害死你们?不要争论——证明它。
我所说的“证明”,并不是指找一篇关于罪恶的全局状态的文章,把它当作权威拍到我的面前。我的意思是,在你的代码库中找到有全局声明和没有全局声明的模块,然后将 JIRA 问题单的事故率或者其他数据作为参考依据。
你的团队中是否有人要求你使用与你的选择相左的库或 API,因为它们具有“无凭无据”的良好性能?你接受他所说的吗?
证明他说的是错的。进行实际的时间测试。
让你自己习惯于做实验,而不是大声地表达和重复你的观点。以实证验证你的想法,这种做法具有直接价值。
面对质疑时,有时你会发现你是对的,而有时候你会意识到是你错了,这也是很有价值的。
但除此之外,你会开始用一种其他人无法匹敌的方式进行辩论,从而树立起自己的品牌,那就是勤奋和正确。这可以帮助你克服一些看似不可逾越的障碍,比如“我只是个初学者,而他是个专家”。其实,他不过是一个专家级初学者而已。
眼光再放长远一点来看,这会让你在事业上有更好的发展。
能够编写代码确保你会有一个回报丰厚的职业生涯。能够编写代码并能够使用证据来为行动过程提供技术和业务用例,这将确保你的事业蒸蒸日上。
以健康的方式使用 (或不使用) 这些
写这篇文章的时候,我觉得自己富有哲理。事实上,我是在从芝加哥飞往休斯顿的飞机上写完这篇文章的,当时我手里拿着一杯酒,选择不使用 wifi。所以我除了和空乘聊天 (我坐在第一排,所以他们都在这里),回忆我的职业生涯之外,几乎没什么事可做。
如果你足够努力地做过尝试,我想你可以反驳这些观点。
但我并没有把这些作为一成不变的编程法则或某种专业的行为准则。我只是把它们作为在职业生涯中自己学到的经验教训提供给大家,它们只是我的个人观点,请大家谨慎选择。
希望这些观点能对你们有所帮助,使你们能够根据自己的需要以健康的方式采用它们,或者,不采用它们。
作者介绍
Erik Dietrich,DaedTech LLC 的创始人、程序员、架构师、IT 管理顾问、作者和技术人员。