Testim 2021-06-18
什么是 Linter? 简而言之,Linter(代码检查工具)是一种帮助你改进代码的工具。Linter 的概念并非 JavaScript 所独有。不过,我敢说大多数想了解 Linter 的人,主要关注的是针对 JavaScript(或更广义地说,动态类型语言)的 Linter。
在今天的文章中,我们将回答标题提出的问题,并提供更多内容。首先,我们会对 “Linter” 这一术语进行定义,让你理解它是什么以及它的由来。接着,我们将讨论使用 Linter 的好处,并进一步介绍它们提供的不同类型检查。
最后,我们会展示几种可用的 Linter 示例,提供一些实用的入门建议,并以一些最终思考作为总结。
让我们开始吧!
什么是 Linter?简要概述
我们先从定义 Linter 开始。正如你在引言中读到的那样,Linter 是一种帮助你改进代码的工具。但它是如何做到这一点的呢?答案是:通过分析你的源代码来查找问题。
“Linter” 这个术语源自一个最初名为 “lint” 的工具,该工具用于分析 C 语言的源代码。1978 年,计算机科学家 Stephen C. Johnson 在贝尔实验室工作时开发了这个实用程序。
最初的 lint 工具以及更早的类似工具,其目标是分析源代码以实现编译器优化。随着时间推移,这类 lint 工具逐渐增加了许多其他类型的检查和验证功能。
然而,正如我们在引言中提到的,Linter 并不仅限于编译型语言。恰恰相反:我们甚至可以说,对于解释型语言而言,Linter 的价值更高,因为在开发阶段没有编译器来检测错误。
使用 Linter 的优势
你刚刚学习了 Linter 的定义,也知道了这种工具是什么时候、由谁发明的。你现在可能已经对 Linter 能为你的代码做些什么有了大致的了解。但在更实际的层面上,这类工具能带来哪些具体好处呢?以下是一些关键优势:
- 减少生产环境中的错误:使用 Linter 可以诊断并修复技术问题(例如“代码异味”),从而减少缺陷进入生产环境的可能性。
- 提高代码的可读性、可维护性和一致性:Linter 可以通过强制执行规则,帮助团队实现更一致、更易读的代码风格。
- 减少代码审查中关于代码风格和审美偏好的争论:代码审查不应充斥着无休止的关于风格偏好的争论。Linter 可以将这些话题排除在外。
- 提供客观的代码质量度量标准:关于代码质量的讨论常常陷入主观性。Linter 则提供了客观且可衡量的代码质量评估。
- 提升代码的安全性和性能:并非所有 Linter 都会分析代码的性能和安全性,但有些确实会。
- 让更多开发者接受代码质量教育:Linter 可以帮助开发者——尤其是经验较少的开发者——学习代码质量的相关知识。
下一节将介绍 Linter 提供的一些检查类型。阅读之后,你将理解 Linter 是如何实现上述好处的。
Linter 提供的检查类型
正如你刚才所读到的,最初的 lint 工具是为了帮助编译器进行优化而分析代码的,但随着时间推移,出现了更多先进且功能全面的工具。如今,我们拥有大量不同类型的 Linter,它们提供多种检查功能。下面我们快速浏览其中一些类型。
语法错误(Syntax Errors)
对于 JavaScript 和其他解释型语言而言,Linter 能提供的最基本也是最重要的检查就是语法错误验证。开发者在将代码推送到主干之前,应确保代码已通过语法验证。
实现这一点的一种方法是使用 预提交钩子(pre-commit hooks),当 Linter 检测到代码存在问题时,阻止用户推送代码。
代码规范遵循(Code Standards Adherence)
Linter 提供的另一种重要检查是对编码规范的遵循情况。有些人可能会认为这纯粹是审美问题,但这是错误的。采用统一一致的编码风格有助于降低阅读、理解和维护代码的认知负担。具有统一代码风格的代码库更容易理解,使用它的开发者也更不容易引入 bug。
因此,有些 Linter 专门用于验证代码库是否符合特定的代码风格。有些工具是“有主见的”(opinionated),即它们自带一套不可更改的规则和约定;而另一些工具则高度可配置,允许用户根据自己的偏好调整规则。
潜在问题(又称“代码异味”,Potential Problems / Code Smells)
“代码异味”是指代码中可能存在某些问题的迹象。如果能有一个工具自动检测这些迹象,以便你在必要时进一步调查,那将非常有用。
例如,包括我在内的许多人认为过长的函数是一种代码异味。因此,你可以配置 Linter 来检测超过指定行数的函数。
另一个常被提及的代码异味是代码过于复杂。但我们这里说的不是主观意义上的复杂,而是非常客观的指标。圈复杂度(Cyclomatic Complexity) 是一种有用的代码度量标准,表示函数中可能的执行路径数量。Linter 可以计算你函数的圈复杂度,并标记出超过特定阈值的函数。
安全检查(Security Checks)
最后但同样重要的是安全性,这无疑是现代应用程序(尤其是 Web 应用)最关键的方面。一旦出错,后果可能是灾难性的,不仅涉及金钱和声誉损失,还可能引发法律问题(例如 GDPR 等法规)。
幸运的是,这也是 Linter 能提供帮助的领域,因为已有工具可以执行重要的安全验证。
理解静态分析(Static Analysis)
我们已经解释了 Linter 是什么、为什么有用,并介绍了主要的 Linter 类型。现在,你已准备好了解一些针对不同用途和编程语言的 Linter 示例。
不过,在此之前,我们先简要介绍一下静态分析(Static Analysis),因为这个术语将在下一节出现,而我们尚未定义它。
那么,什么是静态分析?你可以把它看作是运行前的调试。静态分析是指使用工具分析你的源代码,以查找错误、违反规则或约定的情况,或其他潜在问题。
下一节将展示按检查类型分类的 Linter 示例。归类为“静态分析”的条目主要对应上文列出的第一类(语法错误)和第三类(潜在问题/代码异味)Linter。
Linter 示例
现在,我们简要列举一些 Linter 示例。我们将展示针对不同编程语言的工具,并按其提供的检查类型进行分类。请注意,有些工具可能提供多种类型的验证,因此某些工具会出现在多个类别中。
静态分析类 Linter
- StandardJS(JavaScript)
- PHPMD(PHP)
- StyleCop(C#)
安全类 Linter
- Gosec(Go)
- Bandit(Python)
- LGTM(支持多种语言,包括 JavaScript、Python 和 C#)
编码规范 / 代码格式化类 Linter
- Prettier(JavaScript)
- Rubocop(Ruby)
- StyleCop(C#)
JavaScript 中的 Linter:快速入门指南
在文章结尾之前,我们想为你提供一个简短但实用的指南,教你如何在 JavaScript 中开始使用 Linter。既然是 JavaScript,毫不意外地,你有很多工具可选。由于我们必须选择一个,这里我们选用 ESLint。
安装 ESLint
首先,安装 Linter。ESLint 通过 npm 安装,这意味着你必须先安装 Node.js。如果你还没有安装,请先下载并安装 Node.js,然后继续。
安装好 Node.js 后,就可以通过 npm 安装 ESLint 了。
要全局安装,运行以下命令:
npm install eslint --global
不过,官方文档并不推荐这种做法。更推荐的方式是按项目单独安装。因此,首先为你的项目创建一个目录:
mkdir eslint-sample-app
然后进入该目录,并运行以下命令创建 package.json 文件(后续会用到):
cd eslint-sample-app
npm init
npm 会问你几个问题,全部按回车使用默认值即可。完成后,就可以将 ESLint 添加到你的项目中:
npm install eslint --save-dev
初始化并配置 ESLint
安装完成后,就可以初始化 ESLint 了,运行:
npx eslint --init
运行上述命令后,ESLint 会询问你希望用它来做什么。选项包括:
- 仅检查语法
- 检查语法并发现问题
- 检查语法、发现问题并强制执行代码风格
我们选择最后一个选项。使用方向键选择,按 ENTER 确认。
接着,ESLint 会询问你的项目使用哪种模块系统:
- JavaScript 模块
- CommonJS 模块
- 都不使用
我们选择 JavaScript 模块。
然后,它会问你的项目使用哪个框架:
- React
- Vue
- 都不使用
这里我们选择 “都不使用”。
下一个问题是是非题:你的项目是否使用 TypeScript?按 N 表示“否”。
之后,它会问你的代码是在浏览器中运行还是在 Node.js 中运行。
接下来,ESLint 会问你如何为项目定义代码风格。它提供三种方式:
- 使用流行的风格指南
- 回答关于你风格偏好的问题
- 分析你现有的
.js文件
我们选择第一种。然后你会在以下几种风格之间选择:Airbnb、Standard、Google 和 XO。本教程中,我们选择 Google。
接着,ESLint 会问你希望用哪种格式保存配置文件。选择 YAML。
最后,当被问及是否希望通过 npm 下载所选代码风格时,回答 “yes”。
使用 ESLint 检查文件
下载完成后,你就可以使用 ESLint 检查文件了。但为此,你需要一个待检查的文件。如果你手头有 .js 文件,可以将其复制到项目目录中;或者,你可以克隆这个仓库(包含一个单独的文件),用于测试。
要检查一个文件,使用以下命令:
npx eslint path-to-your-file.js
这是我针对 GitHub 仓库中可下载的 greeting.js 文件运行命令后得到的结果:
F:\demos\eslint-demo\greeter.js
2:3 error Missing JSDoc comment require-jsdoc
3:1 error This line has a length of 86. Maximum allowed is 80 max-len
10:4 error Unexpected 'this' no-invalid-this
✖ 3 problems (3 errors, 0 warnings)
如你所见,我得到了 3 个错误,0 个警告。
什么是 Linter?你工具箱中的利器
在本文中,我们深入探讨了 Linter 工具的概念。现在,你已经清楚地了解了 Linter 是什么,以及为什么应该采用它。此外,你还学习了不同类型的 Linter 工具,并看到了针对多种编程语言的各类示例。
除此之外,你现在也知道如何开始使用 JavaScript 中流行的 Linter 工具:ESLint。
接下来该做什么?
你可以学习以下内容:
- 禁用规则
- 将某条规则设为警告或错误
- 将 Linting 集成到构建流程中
- 高级配置选项
- 创建自定义规则
当然,你也可以尝试其他 Linter。虽然本指南选择了 ESLint,但这并不意味着你就只能用它。例如,JSHint 是另一个流行的 JavaScript Linter。你可以查看我们之前发布的 ESLint 与 JSHint 对比文章。
最后,请记住:Linting 虽然极其有价值,但它只是你武器库中的一种工具。你不应忽视自动化测试、代码审查、重构以及其他众多实践、技术和工具——它们共同构成了对抗代码混乱的持久战。
而在所有这些实践、技术和工具中,我们特别想强调一种常被忽视的测试类型:端到端测试(End-to-End Testing)。这实在令人遗憾。借助合适的工具,高质量的端到端测试可以成为你对抗代码熵增(code entropy)的强大盟友。