我编程生涯中最尴尬的错误(迄今为止)

我编程生涯中最尴尬的错误(迄今为止)
正如他们所说,如果你不为自己的旧代码感到羞耻,那么你就没有成长为一名程序员——我同意这个观点。 我 40 多年前开始编程只是为了好玩,30 年前才开始专业编程,所以我犯了很多错误。 非常。 作为一名计算机科学教授,我教我的学生从错误中学习——他们的、我的和其他人的错误。 我想是时候谈谈我的错误了,以免失去谦虚。 我希望它们对某人有用。

第三名——微软C编译器

我的学校老师认为,《罗密欧与朱丽叶》不能被视为悲剧,因为剧中人物没有悲剧性的罪恶感——他们只是表现得愚蠢,就像青少年应该做的那样。 当时我并不同意他的观点,但现在我看到了他的观点有一定道理,尤其是在编程方面。

当我在麻省理工学院读完大二时,我还很年轻,在生活和编程方面都缺乏经验。 夏天的时候,我在微软的 C 编译器团队实习,一开始我做一些常规的事情,比如分析支持,然后我被委托从事编译器中最有趣的部分(正如我所想的)——后端优化。 特别是,我必须改进分支语句的 x86 代码。

决心为每种可能的情况编写最佳的机器代码,我一头扎进了泳池。 如果值的分布密度很高,我将它们输入 转换表。 如果它们有一个公约数,我用它来使表格更紧(但前提是可以使用除法来完成) 位移位)。 当所有的值都是XNUMX的幂时,我又做了一次优化。 如果一组值不满足我的条件,我就把它分成几个可优化的情况,并使用已经优化过的代码。

这是一场噩梦。 许多年后我被告知继承我代码的程序员讨厌我。

我编程生涯中最尴尬的错误(迄今为止)

学过的知识

正如 David Patterson 和 John Hennessy 在《计算机体系结构和计算机系统设计》中所写的那样,体系结构和设计的主要原则之一是通常使事情尽快运行。

加速常见情况比优化罕见情况更有效地提高性能。 讽刺的是,常见案例往往比罕见案例更简单。 这个逻辑建议假设您知道哪种情况被认为是常见的 - 这只有通过仔细的测试和测量过程才能实现。

在我的辩护中,我试图弄清楚分支语句在实践中是什么样子的(例如有多少个分支以及常量如何分布),但在 1988 年,这些信息不可用。 但是,每当当前编译器无法为我提出的人工示例生成最佳代码时,我就不应该添加特殊情况。

我需要打电话给一位经验丰富的开发人员,与他一起思考常见情况并具体处理。 我会编写更少的代码,但这是一件好事。 正如 Stack Overflow 创始人 Jeff Atwood 所写,程序员最大的敌人是程序员自己:

我知道你有最好的意图,我们也一样。 我们创建程序并且喜欢编写代码。 我们就是这样被造的。 我们认为任何问题都可以通过胶带、自制拐杖和一些代码来解决。 尽管程序员承认这一点很痛苦,但最好的代码就是不存在的代码。 每条新线路都需要调试和支持,需要被理解。 当您添加新代码时,您应该不情愿和厌恶地这样做,因为所有其他选项都已用尽。 许多程序员编写了太多代码,使其成为我们的敌人。

如果我编写了涵盖常见情况的更简单的代码,那么在必要时更新会更容易。 我留下了一堆没人愿意处理的烂摊子。

我编程生涯中最尴尬的错误(迄今为止)

第二名:社交网络广告

当我在 Google 从事社交媒体广告工作时(还记得 Myspace 吗?),我用 C++ 写了这样的东西:

for (int i = 0; i < user->interests->length(); i++) {
  for (int j = 0; j < user->interests(i)->keywords.length(); j++) {
      keywords->add(user->interests(i)->keywords(i)) {
  }
}

程序员可能会立即看到错误:最后一个参数应该是 j,而不是 i。 单元测试没有发现错误,我的审阅者也没有发现错误。 发射进行了,一天晚上我的代码到达服务器并导致数据中心的所有计算机崩溃。

没有什么不好的事情发生。 任何人都不会受到任何影响,因为在全球发布之前,代码已在一个数据中心内进行了测试。 除非SRE工程师暂时停止打台球,做一点回滚。 第二天早上,我收到了一封包含故障转储的电子邮件,更正了代码并添加了可以捕获错误的单元测试。 由于我遵循了协议 - 否则我的代码将无法运行 - 没有其他问题。

我编程生涯中最尴尬的错误(迄今为止)

学过的知识

许多人确信,如此重大的错误肯定会导致罪魁祸首被解雇,但事实并非如此:首先,所有程序员都会犯错误,其次,他们很少会犯两次同样的错误。

事实上,我有一个程序员朋友,他是一位出色的工程师,却因为犯了一个错误而被解雇。 之后,他被谷歌录用(很快就升职了)——他在面试中诚实地讲述了自己所犯的错误,这并不被认为是致命的。

这就是 告诉 关于 IBM 传奇掌门人托马斯·沃森 (Thomas Watson):

一项价值约一百万美元的政府订单被宣布。 IBM 公司——或者更确切地说,老托马斯·沃森本人——真的很想得到它。 不幸的是,销售代表无法做到这一点,IBM 失去了投标。 第二天,这名员工来到沃森先生的办公室,将一个信封放在他的办公桌上。 沃森先生甚至懒得看它——他正在等一位员工,他知道这是一封辞职信。

沃森问出了什么问题。

销售代表详细介绍了招标的进展情况。 他列举了一些本来可以避免的错误。 最后,他说:“沃森先生,谢谢你让我解释。 我知道我们多么需要这份订单。 我知道他有多重要。”然后准备离开。

沃森走到门口,看着他的眼睛,把信封还给他,上面写着:“我怎么能让你走? 我刚刚在你的教育上投资了一百万美元。

我有一件T恤,上面写着:“如果你真的从错误中学习,那么我已经是大师了。” 事实上,说到错误,我是一名科学博士。

第一名:App Inventor API

真正可怕的错误会影响大量用户,成为公众知识,需要很长时间才能纠正,并且是由那些本来不可能犯下这些错误的人犯下的。 我最大的错误符合所有这些标准。

越差越好

我读 理查德·加布里埃尔的文章 作为一名研究生,我在九十年代谈到了这种方法,我非常喜欢它,所以我向我的学生询问。 如果记不太清楚,刷新一下记忆,很小的。 本文在许多方面(包括简单性)对“做对”的愿望和“越坏越好”的方法进行了对比。

应该如何:设计的实现和接口应该简单。 接口的简单性比实现的简单性更重要。

越差越好:设计在实现和接口上应该简单。 实现的简单性比接口的简单性更重要。

让我们暂时忘记这一点。 不幸的是,我已经忘记了很多年了。

应用发明家

在 Google 工作期间,我是团队的一员 应用发明家,一个为有抱负的 Android 开发人员提供的拖放式在线开发环境。 那是 2009 年,我们急于及时发布 alpha 版本,以便在夏季为秋季教学时可以使用该环境的教师举办大师班。 我自愿实现精灵,怀念我以前在 TI-99/4 上编写游戏的方式。 对于那些不知道的人来说,精灵是一种二维图形对象,可以移动并与其他软件元素交互。 精灵的例子包括宇宙飞船、小行星、弹珠和球拍。

我们用 Java 实现了面向对象的 App Inventor,所以里面只有一堆对象。 由于球和精灵的行为非常相似,因此我创建了一个具有属性(字段)X、Y、速度(速度)和标题(方向)的抽象精灵类。 他们有相同的方法来检测碰撞、从屏幕边缘反弹等。

球和精灵之间的主要区别在于所绘制的内容是实心圆还是光栅。 由于我首先实现了精灵,因此指定图像所在位置左上角的 x 和 y 坐标是合乎逻辑的。

我编程生涯中最尴尬的错误(迄今为止)
一旦精灵开始工作,我决定可以用很少的代码来实现球对象。 唯一的问题是我采用了最简单的路线(从实现者的角度来看),指示球轮廓左上角的 x 和 y 坐标。

我编程生涯中最尴尬的错误(迄今为止)
事实上,有必要指出圆心的 x 和 y 坐标,正如任何数学教科书和任何其他提到圆的资料中所教导的那样。

我编程生涯中最尴尬的错误(迄今为止)
与我过去的错误不同,这一次不仅影响了我的同事,还影响了数百万 App Inventor 用户。 他们中的许多人都是孩子或者完全是编程新手。 在处理存在球的每个应用程序时,他们必须执行许多不必要的步骤。 如果说我以前犯过的其他错误我都能笑着回忆起来,那么这个错误至今仍让我汗流浃背。

直到最近,也就是十年后,我才终于修复了这个错误。 “修补”,而不是“修复”,因为正如 Joshua Bloch 所说,API 是永恒的。 由于无法进行影响现有程序的更改,我们添加了 OriginAtCenter 属性,其值在旧程序中为 false,在所有未来程序中为 true。 用户可能会问一个逻辑问题:谁会想到将起点放在中心以外的地方。 给谁? 对于十年前一位懒得创建普通 API 的程序员来说。

得到教训

在处理 API 时(几乎每个程序员有时都必须这样做),您应该遵循 Joshua Bloch 的视频中概述的最佳建议“如何创建良好的 API 及其为何如此重要“ 要么 在这个简短的名单中:

  • 一个API既可以给你带来很大的好处,也可以给你带来很大的伤害。。 良好的 API 可以创造回头客。 坏的会成为你永恒的噩梦。
  • 公共API就像钻石一样恒久远。 全力以赴:再也没有机会把每件事都做好。
  • API 概要应该简短 — 一页包含类和方法签名和描述,最多只占一行。 如果第一次结果不完美,这将使您能够轻松地重构 API。
  • 描述用例在实施 API 甚至制定其规范之前。 这样您就可以避免实现和指定完全非功能性的 API。

如果我用人工脚本写了哪怕一个简短的概要,我很可能会发现错误并纠正它。 如果没有,那么我的一位同事肯定会这么做。 任何具有深远影响的决定都需要考虑至少一天(这不仅适用于编程)。

理查德·加布里埃尔 (Richard Gabriel) 文章的标题“更糟就是更好”指的是率先进入市场的优势——即使产品不完美——而其他人则花费永恒的时间去追逐完美的产品。 反思精灵代码,我意识到我什至不需要编写更多代码来使其正确。 不管有人怎么说,我都大错特错了。

结论

程序员每天都会犯错误,无论是编写有错误的代码还是不想尝试一些可以提高他们的技能和生产力的东西。 当然,你可以成为一名程序员,而不会犯像我这样严重的错误。 但如果不认识到自己的错误并从中吸取教训,就不可能成为一名优秀的程序员。

我经常遇到一些学生,他们觉得自己犯了太多错误,因此不适合编程。 我知道冒充者综合症在 IT 领域是多么普遍。 我希望你能吸取我列出的教训 - 但请记住主要的一个:我们每个人都会犯错误 - 令人尴尬的、有趣的、可怕的。 如果将来我没有足够的材料来继续这篇文章,我会感到惊讶和不安。

来源: habr.com

添加评论