让犯错变得困难的驱动开发

Chris Coyier - 2019年4月2日

开发工作很复杂。我们的工作是在完成任务和以安全、持久的方式完成任务之间持续进行的斗争。

开发人员会说:“我先快速粗糙地做一下”,因为人们认为,如果快速编写代码,不仅容易出错,而且会故意不遵守既定的规范,跳过使代码更健壮的任务。

可能没有办法完全阻止编写粗制滥造的糟糕代码,但考虑工具如何发展以使编写糟糕代码变得更困难,这很有趣。

让我们在开发中充分利用防错设计

最明显的例子是自动化的代码质量工具。

假设您正在编写 JavaScript。 ESLint 是一款非常流行的工具,它会在您编写代码时检查代码并告知您存在的问题。

ESLint 是可配置的,这些配置可以根据团队的喜好进行强制执行。如果您更喜欢使用一些强大且已建立的约定,我相信最流行的是 Airbnb 的配置

当然,任何东西都有替代方案。这篇文章与其说是关于一个全面的工具列表,不如说是关于考虑哪些类型的工具可以帮助我们朝着编写更好代码的方向发展。也就是说,stylelint 适用于 CSS,PHP_CodeSniffer 适用于 PHP,而 Rubocop 适用于 Ruby。

Prettier 属于类似但独特的类别。它就像代码的“美化器”,因为它可以帮助您重新格式化代码,使其不仅看起来好看,还可以遵循团队约定(例如单引号!双空格缩进!)。使用 Prettier 最常见的方式是在保存文件时运行它。因此,也许您可以快速编写代码,而不用过多地担心格式问题,因为它会在您保存的瞬间自动完成。这里有一个有趣的质量副作用,因为Prettier 可能会失败,如果失败,则表示您的代码语法存在问题,需要修复。非常有用。

Prettier 失败。

我对像 SonarlintCode ClimateResharper 这样的工具很感兴趣,在我看来,它们本质上就像代码风格检查器,但只提供最佳实践分析,而不是自己配置。它还声称可以更深入地理解您的代码。 WebhintDeepscan 看起来也同样有趣。如果您认为我理解错误,请随时纠正我,因为我还没有机会使用过任何一个。

更进一步地使用代码风格检查器,您可以将通过代码风格检查作为在 Git 中提交文件之前的必要条件Git 钩子 是这里的关键,而管理它们的流行工具是 Husky

同样,实际的测试是阻止糟糕代码的有效方法。

编写测试始终是明智之举。部署导致功能中断的代码令人尴尬,浪费时间,并可能对您的业务产生负面影响。然而,我们经常这样做。测试的全部意义就在于防止这种情况发生。

诸如 JavaScript 的 Jest 和 Ruby 的 RSpec 之类的工具很有用,并且被认为是单元测试。这是一项工作!您手动编写期望获得特定结果的函数。我期望如果使用这些参数调用一个函数,它会返回这个值!

测试驱动开发 (TDD) 是一种实践,您在编写实际执行您尝试执行的操作的代码之前编写测试。如果您能够做到,这是一种不错的工作方式,因为您从一开始就拥有了代码覆盖率。

另一种类型的自动化测试是集成(也称为端到端)测试。我非常喜欢 Cypress。它模拟用户实际使用浏览器的方式。访问此 URL!点击这里!填写此字段并提交表单!现在这个东西存在吗?URL 是否正确?其他内容是否可见?这种测试非常强大,因为要通过这些测试,很多事情都必须正确,因此包含大量的隐式测试。

作为一名 CSS 开发人员,我也喜欢那些监视网站外观是否符合预期,以及样式更改是否没有产生意外后果的测试。 Percy 在这方面非常棒(请参阅我们的视频)。

当我们谈论所有不同类型的自动化测试时,还有各种工具可以自动化一定程度的可访问性测试。此外,还有像 CalibreSpeedCurve 这样的工具可以自动执行 Lighthouse 来监视性能。

帮助我们(有意或无意)的语言和语言特性

例如,以 JSX 为例。完全有可能在 JSX 中编写糟糕的 HTML,但您无法编写无效的 HTML。组件将完全出错,您将在工作时知道这一点。这甚至不是 JSX 存在的理由,但我发现这是一个有趣的副作用。在我的职业生涯中,我修复了许多与格式错误的 HTML 导致的问题相关的错误,从细微的副作用到重大的布局错误。

Prettier 在这里捕获了问题,但如果编译并发送到浏览器,我们会在控制台中看到错误。

类似地,像 Emmet 这样的工具可以帮助生成有效的 HTML。我一直都在使用 Emmet,直到有人 提醒我,我才知道这一点。

我还想到了 React 的特性,比如 PropTypes,当传入缺少或意外的数据时,它会抛出错误。更不用说您可以配置您的代码风格检查器,如果缺少 PropType,它就会警告您。对于相当少量的劳动(与编写测试相比),这是一种非常强大的测试。您甚至可以 强制它们帮助提高可访问性

在这里不提及 TypeScript 是不可能的。使用 TypeScript 的主要目的之一是代码安全性。它变得非常流行(听 Laurie Voss 的说法)表明我们希望强制执行这种安全性。我记得 Angular 2 发布时,有关于为什么这样做的长篇解释。人们也谈论了使用 TypeScript 获得的工具改进:高级自动完成功能、导航和重构。从某种意义上说,它们都与代码安全性有关——让编辑器帮助您编写正确的文件名和函数名。无论是否使用 TypeScript,任何类型的自动完成功能/IntelliSense 都非常好用。

这篇文章的整个想法源于我思考 GraphQL 如何具有这种“你无法搞砸”的特性。您无法请求不存在的数据,因为它会在您使用它的同时出错——然后您将修复它。而且您无法获取到您没有预期的数据,因为您已经准确地描述了您想要获取的数据,而 GraphQL 正是如此。这并不是说您不能编写使用 GraphQL 的糟糕代码或编写糟糕的 GraphQL 实现,但该技术在某种程度上鼓励编写更好的代码,我对这一点感到着迷。

CSS-in-JS,虽然这可能是一个过于宽泛的术语,但适用于本次讨论。该领域的大多数解决方案都涉及某种样式作用域,而样式作用域提供了我们关注的“你无法搞砸”的主题。当您刚刚编写的选择器编译成您从未手动编写的选择器时,例如 .SpecificComponent_root_34lkj4x,您就不会造成意外的副作用。

您的同事是一条很棒的防线

首先,给自己制定一个系统。任何内容都不能直接提交到主分支,并且所有内容都必须是合并/拉取请求。这为您提供了一个讨论代码质量的地方——更不用说在代码即将进入生产环境之前运行一系列自动化测试的地方。

GitLab 有一个合并请求审批人的概念。您可以选择一些必须在合并分支之前批准该分支的人员。

GitHub 有类似的概念,即 受保护分支。也许防止出现糟糕代码的最佳方法是扩大责任范围。当然,也存在这种做法仅仅变成“匆匆扫一眼代码,然后点赞”的风险,但这取决于你们自己,确保代码审查被认真对待。我发现,在代码发布之前,要求多个人审查代码非常有价值。“人多眼杂,Bug无处遁形”,以及 其他相关内容


我们总会写出有问题的代码,但我们也总能找到避免犯错的方法。