垃圾堆的教训

垃圾堆的教训

原文:https://medium.com/hackernoon/lessons-from-the-garbage-pile-82ff136ad48b

在过去的十年里,我一直从事专业的软件编写工作,在此之前的十年里,我可能还从事过个人项目,也做过一些兼职工作。感觉好像我一直在以绝对极快的速度学习——这是我仍然热爱我所做的事情的很大一部分原因。有些事情已经发生了,我发现自己不得不一遍又一遍地向我指导和共事的人解释。我想,最好还是把它们写下来!

一切都是垃圾,但总比以前好

当你写代码时,很容易想到你的工具有多糟糕(“一个可怜的工匠责怪他们的工具”)。网络又慢又不可靠,一切都在不断被黑客攻击,你使用的平台像筛子一样漏内存而你对此无能为力,你依赖的服务被卖掉或关闭……你的用户也是垃圾,他们使用你的产品做任何事情,除了你设计它要做的事情,在你的表格中输入天书,在你明确告诉他们不要运行的地方运行它,并期望它几代人都没有错误地运行。我花了很长时间才意识到我写的所有东西也是垃圾。在某种程度上,它必须是——如果上面是垃圾,下面是垃圾,它怎么可能是其他东西?

垃圾有两个好处。第一件事是它很容易改进。这就是过去 50 年来人们一直在忙着做的事情。今天的垃圾比十年前(或二十年,或三十年前……)的垃圾好得多,这让我感激涕零。工具、库和模式已经改进到如此程度,以至于今天一个人所能完成的事情是惊人的。

第二件事是,扔垃圾真的很容易。“重构”只是扔掉旧的垃圾,用新的、更好的垃圾取而代之。最好的代码是由知道这些代码都是垃圾的人编写的——因为他们构建代码的方式很容易浏览、理解和改进。最糟糕的代码是由那些认为他们正在修复一切,并在垃圾堆中创建一个华丽的寺庙的人创建的代码。你不是。你永远不会,也永远不会。

像写英语一样写代码

也许我从我的导师那里学到的最重要的一课(嗨,布莱恩·福克斯!)是用类似于自然语言的方式编写和思考代码。基本上,在英语和软件中有两种“种类”:事物和动作。英语:名词和动词。在软件中:状态和功能。当你写英语时,你在利用读者一生的经验。语言都是隐喻——单词对应于你映射到现实中的概念。在软件中做同样的事情:代码对应于你映射到问题域的概念。

当你明智地选择单词时,编写和阅读代码会容易得多。等你以后看代码的时候,除了名字你什么都忘了(这才是重点!),您将根据名称重新发明概念结构。如果您选择了一个与较大系统中该元素的功能不太对应的模型,那么当您针对它编写代码时,您将会引入错误,因为您正在处理一个新创建的模型,而不是真正的代码。当您发现这样的错误时,请修复实际损坏的那一面。你使用已经编码的系统的方式是不正确的,还是你正确地使用一个损坏的系统?不要为了解决底层系统中的 bug 而破坏描述问题的好方法!不要拘泥于一种描述问题的方式,这种方式有你必须在系统中修复的固有缺陷!在构建东西的时候,我经常在概念/执行边界上来来回回。在描述这个问题时,我定义了数据结构和操作。然后我实现它们,才意识到我对问题的描述略有错误——然后我不得不重新定义和描述问题,然后重新实现它们。

这听起来效率很低,为什么不在它一“起作用”就走开呢?因为你大部分时间不会花在写代码上,会花在理解和修复旧代码上(因为所有代码都是垃圾!).如果有一个明确的意图和实现,那么找出 bug 是什么就非常容易了,因为 95%的时间都是简单的“哦,模型是错误的”或者“哦,实现忽略了这个现在很明显的边缘情况”。你要尽量减少没有明确意图和执行的情况,因为它们绝对会把你压垮。

好奇心是王道

尽可能了解您的环境和问题领域是非常重要的。这包括你选择的语言,你的库,你的用户。如果你发现自己对某事感到疑惑——去弄清楚它。这有两个好处:它通常很有趣,并且可以帮助你写出更好的代码。如果某段代码的行为“看起来不正常”,那么解决它是至关重要的。要么是你对代码的理解不正确,要么是代码不正确:这两个问题的解决都至关重要。如果你想知道一个函数是如何被调用的,那就想清楚。检验你的假设。为您正在处理的代码建立一个好的映射。

你在为谁编码?

天真的答案是:当然是电脑!然而,你的代码最重要的消费者是你自己。如果你幸运的话,将来会有一些勇敢的人使用你的代码。永远记住这一点。当你阅读这些代码时,你将来会试图回答什么问题?许多现代编码趋势与这个概念完全背道而驰。干(不要重复自己)是一个可怕的座右铭。清晰、易读、易懂比不重复输入同样的内容要重要得多。表达你想做的事情的最清晰、最简单的方式是什么?通常(为 DRY 辩护),如果你一遍又一遍地输入同样的东西,这并不清楚或简单…但有时确实如此。

使用花哨的语言功能来减少字符数有一个可怕的结局——跳过 3 个抽象层次来理解正在发生的事情是可怕的。尊重未来的你:以这样一种方式写东西,你会立即明白正在发生什么,如何发生,以及为什么发生。你花在阅读代码(和注释)上的时间要比写代码多,所以优化阅读——而不是打字速度。有些问题经常出现,“这个代码是从哪里调用的?”,“这个代码调用什么代码?”、“这一块 UI 是什么负责的?”,“那个网址是从哪里来的”。当这些问题不能通过阅读代码或全文搜索立即得到答案时,请将答案写在注释中。如今大量的动态编程实践使得这些问题更加难以回答。动态函数名、动态文本和模块化用户界面都很有用,但是它们是有代价的:你不能只靠grep自己的方式来得到一个即时的答案。如果这是一个值得做出的妥协,有时确实如此,那么就以注释、文档和可预测的项目结构的形式留下合理的痕迹。

小心边缘情况

边缘情况是“有时”发生的情况。很容易忽略它们——有人多久会让你的代码被零除一次?答案是:一直。当你编码时,记住两件事很重要。首先:这段代码将如何被误用(什么是有效的输入范围,等等。).第二:我如何报告错误?确保代码的消费者能够处理错误是一个顶级特性。不要将其归入异常或错误代码。网络成功的次数比失败的次数多,尽管很容易忘记。整数更有可能是非零而不是零,但是几年后,看起来肯定不是这样。

十年预测

最后,我想重申,我们永远不会有一个完美的系统。想象某个乌托邦,那里有 10 倍的生产力或零错误,很可能会让你做出一些适得其反的决定。对实际问题的务实解决方案,以一种容忍错误、易于阅读、浏览和理解的方式编写,是你所能期望的最好结果。如果我们都继续这样开发软件,我们将会延续过去 50 年的惊人趋势。努力让未来的生活变得更好一点,你和我们其他人也会从中受益。


本站为非盈利网站,作品由网友提供上传,如无意中有侵犯您的版权,请联系删除