[Flutter翻译]Flutter lint的比较

1,653 阅读19分钟

本文由 简悦SimpRead 转码,原文地址 rydmike.com

与rydmike.com一起翩翩起舞

(发表于2021年7月28日,更新于2022年5月21日)

更新后涵盖了Flutter 3.0和Dart 2.17的衬垫。

在这篇文章的末尾,我介绍了Flutter默认的linting和流行软件包的比较,比较了它们使用的Dart和Flutter lint规则。

image.png

什么是Dart Linter?

Dart linter是一个静态分析器,用于识别Dart源代码中可能存在的问题。有两百多条代码分析规则可用,可以检查任何潜在的类型问题、编码风格、正确的Flutter部件使用和格式化。

您可以设置Dart分析器和林特,以您喜欢的方式完成您的任务。有些规则比其他的更重要,有些只是与风格和个人偏好有关,是开发者喜欢永远争论的那种。当涉及到它们时,没有真正的对与错,如果你的项目中没有强制规定某种风格,就做你喜欢的事情。

在一个以前没有使用过的代码库上启用非常严格的提示规则,可能会很费时间。对于这种情况,逐步引入更严格的提示规则是一个好主意。要做到这一点,你可能想更好地了解lint规则,以及如何在不使用软件包的情况下自己设置它们。

许多Dart分析器和linting错误也可以通过使用dart fix自动修复。当你在一个以前没有使用的项目中启用一个规则时,这也适用于许多lint规则。关于如何使用dart fix的更多信息,请参见文档。如果一个给定的lint规则有一个 "dart fix",那么用它来迁移一个代码库来使用它,就可以节省很多时间。

要研究和阅读更多关于每条lint规则的信息,你可以到Linter for Dart GitHub页面。官方Dart文档最近增加了一个合理的内容,现在也包括同样的信息,而且是以更好的格式

我如何使用Dart Linter?

我个人喜欢在一个文件中启用所有的lint规则,然后将其纳入我的analysis_options.yaml文件。我简单地把这个文件称为all_lint_rules.yaml。你可以在这里得到所有lint规则的最新官方版本,而且总是最新的,抓取它的内容并把它放在all_lint_rules.yaml文件中。

如果你不想跟踪Dart lint网站对所有可用的lint规则的更新,还有一个由Gaëtan Schwartz @gaetschwartz制作的优秀软件包,叫做all_lint_rules_community,你可以用它将所有lint规则添加到你的项目,而不是手动添加和更新文件。当新的lint规则被添加到Dart的all lint rules page时,该包会自动更新,所以你所要做的就是提升包的版本,在包被更新后得到所有lint规则的最新列表。

analysis_options.yamlall_lint_rules.yaml都放在Flutter项目的根目录下,也就是你的pubspec.yaml文件的位置。在我的analysis_options.yaml中,我包括all_lint_rules.yaml文件。在我的analysis_options.yaml中,我还排除了一些通常生成的Dart文件的分析。

我使用新的Dart language:设置,其中我设置了strict-casts: truestrict-inference: true,和strict-raw-types: true。这些设置取代了以前的强模式设置implicit-casts: falseimplicit-dynamic: false。更多信息请参见Dart文档Enabling stricter type checks。我强烈建议使用这些设置。

我把那些我认为应该是错误的常见错误,提升到错误级别。然后分析器甚至不会让我编译存在这些错误的代码。这包括将缺失的返回值和缺失的必要参数设置为错误,而不是警告或信息。我把参数重新分配只保留为警告,有些场合可能需要这样做,但我想要一个警告,这样我就可以考虑重写它,或者在考虑后逐个忽略警告规则。

我的analysis_options.yaml文件是这样开始的。

# RydMike LINTER Preferences v2.0.0
#
# Get this file here: https://gist.github.com/rydmike/fdb53ddd933c37d20e6f3188a936cd4c
#
# We include and activate all lint rules, later below we disable the not used or desired ones.
# You can find a list of all lint rules to put in your all_lint_rules.yaml file here:
# https://dart-lang.github.io/linter/lints/options/options.html
#
# For a full comparison of all lint rules settings in rule styles listed below, please see this
# sheet: https://docs.google.com/spreadsheets/d/1Nc1gFjmCOMubWZD7f2E4fLhWN7LYaOE__tsA7bf2NjA
include: all_lint_rules.yaml
analyzer:
  exclude:
    - "**/*.g.dart"
    - "**/*.freezed.dart"
    - "test/.test_coverage.dart"
    - "bin/cache/**"
    - "lib/generated_plugin_registrant.dart"

  # For more information see:
  # https://dart.dev/guides/language/analysis-options#enabling-additional-type-checks
  language:
    strict-casts: true
    strict-inference: true
    strict-raw-types: true

  errors:
    # Without ignore here, we cause import of all_lint_rules to warn, because some rules conflict.
    # We explicitly enabled even conflicting rules and are fixing the conflicts in this file.
    # Put it to warning temporarily, if you need troubleshoot lint rule settings.
    included_file_warning: ignore

    # Treat missing required parameters as an error, not as a hint or a warning.
    missing_required_param: error

    # Treat missing returns as an error, not as a hint or a warning.
    missing_return: error

    # Allow self-reference to deprecated members. This is done because otherwise we have
    # to annotate every member in every test, assert, etc., when we deprecate something.
    deprecated_member_use_from_same_package: ignore

    # DON'T assign new values to parameters of methods or functions.
    # https://dart-lang.github.io/linter/lints/parameter_assignments.html
    parameter_assignments: warning

    # Allow having TODOs in the code.
    todo: ignore

# LINTER Preferences
#
# Explicitly disable only the rules we do not want.
linter:
  rules:

其余的设置只是把我不想使用的linting规则关闭。因为现在所有的规则默认都是开的,这是一个不应该使用的规则列表。我试图让它相对简短。

至于什么是真正被关闭的,首先,有一些提示规则是相互冲突的。当涉及到它们时,你可以采取两种方式。如果你不想做选择,并希望能够使用两种选择,那么就禁用这两种规则。或者选择其中一个,禁用你不想使用的那个。我更喜欢做出选择,相互冲突的规则往往是非常有意见的。在某些情况下,允许两个选项可能更宽松。如果是个人项目,那就去使用你喜欢的东西吧。

个人偏好的提示规则的一个典型例子是 "prefer_double_quotes "与 "prefer_single_quotes "的选择。即使一个提示规则是非常有主见的,在大型项目中,你可能仍然想做出选择,以执行一个一致的风格。

下面是我的选择和我对引号风格的理由。

    # DO use double quotes where they wouldn't require additional escapes.
    #
    # https://dart-lang.github.io/linter/lints/prefer_double_quotes.html
    #
    # This rule is mostly about what style you want to use and enforce, if any.
    # It of course conflicts with rule:
    # `prefer_single_quotes` : "DO use single quotes where they wouldn't require additional escapes."
    # https://dart-lang.github.io/linter/lints/prefer_single_quotes.html
    #
    # For us single quotes are easier to type. On our ISO keyboards it is next to Enter key, and
    # we don't need the Shift plus the far to reach nr 2 key on R1 to type it. Also, we don't think
    # they compromise on readability.
    # Then again if you don't care and don't mind mixing and matching, then ALSO
    # turning OFF `prefer_single_quotes` works fine too, and then you can use both options.
    #
    # We thought it was cleaner to stick to one style. Single quotes are easier to type for us,
    # thus we turn OFF this `prefer_double_quotes` rule. There is another lint rules that recommends you
    # to use double quotes when you otherwise would need to escape the single quote char, it works
    # well when you use the prefer_single_quotes rule as well.
    #
    # Other known linters use:
    #
    # Core           disabled : https://pub.dev/packages/lints
    # Recommended    disabled : https://pub.dev/packages/lints
    # Flutter Lints  disabled : https://pub.dev/packages/flutter_lints
    # Pedantic       disabled : https://pub.dev/packages/pedantic
    # Effective Dart disabled : https://pub.dev/packages/effective_dart
    # Flutter repo   disabled : https://github.com/flutter/flutter/blob/master/analysis_options.yaml
    # Lint           disabled : https://pub.dev/packages/lint
    # VG Analysis    disabled : https://pub.dev/packages/very_good_analysis
    # RydMike        disabled : https://gist.github.com/rydmike/fdb53ddd933c37d20e6f3188a936cd4c
    prefer_double_quotes: false

除了与自己的对应部分相冲突的东西外,我还关闭了什么?尽可能少,我喜欢相当严格的东西,但这只是我的个人偏好。

我记录了我所做的选择,以及在我做这些选择的时间点上的理由。我根据我是在为一个包还是一个应用使用linting而略有不同,对公共包保持更严格的要求。这些选项和选择也被记录下来了。

这里有一个Gist,包含了我在analysis_options.yaml中为个人项目使用的全部设置细节。

随着事情的发展,我可能会改变一些设置。我发现自己不喜欢并禁用的一个规则是sort_constructors_first。听起来这是个不错的规则,对吗?对于默认的未命名的构造函数,我同意,我也想让它优先。有一个单独的提示,我确实在使用,它叫做sort_unnamed_constructors_first。然而,之后,我想看到默认构造函数的所有属性,以及它们的文档注释。我发现这对更复杂的类很有用,这些类可能有很多命名的构造函数或有很多命名参数的工厂。

如果启用 "sort_constructors_first "规则,我就不得不使用这样的顺序:我必须向下滚动,才能在所有命名的构造函数和工厂之后找到更多的属性。我觉得这很不方便。这是另一个关于个人风格偏好的小例子。有许多与风格和代码一致性相关的提示性规则。了解它们,找到你自己的个人偏好。

当你禁用一个lint规则时,试着给你未来的自己写一个简短的说明,为什么你要禁用它。这就是我写下的关于为什么我关闭了sort_constructors_first规则的原因。好处是你当然可以改变你对规则的看法,或者根据你的需要增加更多的规则,至少在你的个人项目中是这样。

    # DO sort constructor declarations before other members.
    #
    # We do like this lint rule, but we want to have the default constructor first, followed
    # by its properties, after this other named constructors and factories. This rule gets
    # in the way of that and forces you to put (often final) constructor properties after all
    # the named constructors and factories, making them tedious to find and disconnected from
    # where we want to see, read and handily edit them. This is especially the case if there are
    # many constructors and factories, and they have a lot of parameters. For now, we disable
    # this rule and order things as described above, which apart from the default constructor
    # properties coming right after the constructor, is the only part where we in practice
    # deviate from this rule, so other yes, we do put constructors first as well anyway.
    #
    # Other known linters use:
    #
    # Core           disabled : https://pub.dev/packages/lints
    # Recommended    disabled : https://pub.dev/packages/lints
    # Flutter Lints  disabled : https://pub.dev/packages/flutter_lints
    # Pedantic       disabled : https://pub.dev/packages/pedantic
    # Effective Dart disabled : https://pub.dev/packages/effective_dart
    # Flutter repo   enabled  : https://github.com/flutter/flutter/blob/master/analysis_options.yaml
    # Lint           disabled : https://pub.dev/packages/lint
    #                           Discussion https://github.com/passsy/dart-lint/issues/1
    # VG Analysis    enabled  : https://pub.dev/packages/very_good_analysis
    # RydMike        disabled : https://gist.github.com/rydmike/fdb53ddd933c37d20e6f3188a936cd4c
    sort_constructors_first: false

以上也是我为所有我关闭的lint规则使用的文档风格的一个例子。是的,它很冗长,但现在我可以找到我过去做出选择的理由。我还可以直接看到别人对我不使用的每条规则选择了什么作为他们的lint偏好的参考。

我应该使用哪一个linting包?

如果我想根据一个包来使用linting,我应该使用哪个linting包?当Flutter 2.5发布后,回答这个问题变得容易多了。

从Flutter 2.5版本开始,Flutter和Dart使用了两个新的linting包,当你创建一个新的Flutter项目时,这两个包是默认启用的。随着Flutter 3的推出,所使用的linting包被更新为版本2,并包括比版本1中的规则集更多的Dart相关规则。当您用Flutter 3.0.0或更高版本创建一个新的Flutter项目时,您会得到默认启用的第2版linting规则。

如果您用2.5版或更高版本创建了您的Flutter项目,那么您已经在使用默认的linting包。这是一个非常好的起点。下面您可以将Dart和Flutter默认启用的提示规则与流行的第三方软件包进行比较。

使用第三方提示包呢?

如果你想使用第三方提示包,你可以这样做。有许多第三方软件包可以为你定义提示规则。如果第三方提示包符合你的需求,使用第三方提示包没有什么问题。使用现成的提示包可能是你的正确选择,特别是如果你对自己了解规则和跟进Dart团队偶尔增加的新规则不感兴趣,那么请你使用一个包。

对于我的个人项目,我更喜欢在一个文件中启用所有的规则,然后禁用那些不适合我的使用情况和偏好的规则,这种做法很清晰。早些时候我也是用一个包开始的,但我注意到当我需要或想修改一些规则时。然后我就开始启用或禁用规则,与使用的包设置有关。这变得有点混乱,难以追踪。最后,我觉得把所有的东西都打开,然后在我的analysis_options.yaml里有OFF的定义,这样就更干净了。超级简单,清晰,在需要的时候容易修改,不会把事情搞乱。另外,对于这种相对简单的设置,不需要一个包。

在一个大的项目中,可能已经为你商定和定义了lint规则,那么就坚持下去吧。如果你发现lint规则没有被定义,也没有记录他们为什么在项目中采用某种方式,那么他们真的应该被定义,也许是需要解决的问题。

在过去,Effective DartPedantic曾经非常流行。然而,这两个包都已经被弃用了。对于一个新的项目来说,不要使用它们,并考虑将使用它们的应用程序和软件包迁移到推荐的替代品上。

来自Google的Pedantic包最初主要是供他们内部使用。尽管它的名字是这样的,但它根本不是很严格,也不是很迂腐。它被用作他们内部对Dart项目达成共识的最低限度的集合。

Effective Dart包,在它被废弃之前,是一种提供与Effective Dart文档中的准则相对应的分析选项的方式。

我仍然把这两个被废弃的包包括在我的比较表中,这样你就可以看到它们与目前常用的品管规则集的比较。

Lints

第一个Flutter和Dart默认使用的linting包叫做lints。它在2021年5月12日推出了1.0.0版本。这个包包含了新的官方推荐的Dart项目的提示规则选择。随着Dart 2.17.0和Flutter 3的发布,它被提升到2.0.0版本,启用了更多的新规则。

"lints"包有两种形式,一种是绝对最小的lint规则集,称为Core lints,另一种是更广泛的规则集,称为Recommended Lints。推荐集也包括核心lint。在Dart指南中,你可以看到更多关于它的信息这里

在其最新版本中,Lints Core可以实现28条提示性规则,这只是可用规则的13.8%,只是最关键的Dart规则。Lints Recommended集启用了84条规则,即41.4%的可用规则和强烈推荐的Dart规则。

Flutter lints

第二个开箱即用的软件包被称为Flutter lints。它也是在2021年5月12日推出的1.0.0版本。flutter_lints包包括来自Dart lints的推荐集,另外还有一些在Flutter项目中很重要的规则。

默认的Dart和Flutter lint规则集是作为超集构建的,启用的规则数量越来越多。Flutter lints包括所有Dart 推荐的lints规则,然后包括所有Dart 核心lints规则。

从Flutter稳定版2.5.0及以后的版本开始,包flutter_lints定义了最新的官方推荐的提示规则,鼓励Flutter应用程序、包和插件的良好编码实践。在其最新的版本中,Flutter lints启用了97条规则,或47.8%的可用品评规则。

使用 Flutter 2.5.0 及更高版本的 flutter create 创建的项目,会自动设置为使用 Flutter lints 包。当使用Flutter 3.0.0或更高版本创建Flutter项目时,使用的flutter_lints提示包级别被提升到2.0.0版本,也使用lints2.0.0。你可以找到官方的使用和设置说明在Flutter文档中

由于这些都被包含并自动设置为新Flutter项目的默认linting包,所以除了flutter_lints之外,没有什么重要的理由推荐任何其他linter包作为一般的良好起点。然而,如果你想使用更多更严格的规则,除了滚动自己的设置外,还有两个非常好的选择。

Lint和Very Good Analysis

LintVery Good Analysis (VGA)都是可靠的选择,提供了比flutter_lints更严格的提示规则集。

它们都比默认的flutter_lints启用了更多更严格的提示规则。lint "和 "very_good_analysis "都使用强模式,并且禁用了隐式转换。Very Good Analysis也明智地选择了禁用隐式动态。

写这篇文章时,这两个包都没有更新,以使用新的Dartlanguage:设置,其中有strict-casts: truestrict-inference: true,和strict-raw-types: true。这些设置取代了以前的强模式设置implicit-cast: falseimplicit-dynamic: false。更多信息请参见Dart文档Enabling stricter type checks。例如,Flutter SDK仓库使用较新的language设置。建议使用它们而不是旧的strong-mode设置,根据Dart文档,这些设置已被废弃。最有可能的是,Lint和VGA在不久的将来也会被更新为这样。

从2.3.0版本开始,Very Good Analysis开始将缺失的必要参数和缺失的返回作为代码错误处理。我认为这是一个明智的、受欢迎的补充。从1.8.1版本开始,lint包也是这样做的,它甚至增加了将函数参数的新值分配视为警告,在这方面,它的严格程度甚至高于VGA。

lint包在源代码中为其lint规则的选择提供了很好的推理文档,使你可以阅读并理解作者对所使用的选择的理由。它还为包提供了一个变体,为公共包增加了一些更有用的规则。如果你编写软件包,这是一个很好的功能。有些规则并不那么有用,甚至在你写应用程序的时候会碍事,但在你写包的时候却很重要,可以帮助你的包在pub.dev上获得更高的分数。

在已打包的linters中,very_good_analysis,使比较过的打包linters中的lint规则数量最多。在3.0.0版本中启用了177条规则,占可用的lint规则的87.2%,它是所比较的打包linters中最严格和迂腐的。lint包也不甘落后。在其1.8.2版本中,它有152条规则,或74.9%的可用提示规则被启用。

这两个包都很好地跟踪了新的Dart和Flutter的提示规则的发展,并定期更新。它们都启用了所有关键和重要的规则。如果你想要比Flutter开箱即用的更严格的品头论足,并且不想自己跟踪和维护使用的规则集,而宁愿只更新一个包的依赖关系来更新你的品头论足游戏,那么这两个都是很好的选择。

如果我不使用并且喜欢自定义设置,我可能会选择very_good_analysis而不是lint,主要是因为它更严格,也因为它的维护可能更积极一些。例如,它更快地采用了新的Flutter 3.0和Dart 2.17的linting规则。lint包也很严格,只是不是最严格的,它试图在有用和烦人之间找到合适的平衡,这可能更符合你的偏好。

Flutter 仓库

我还发现,关注Flutter SDK仓库使用什么提示规则很有意思。在过去的一年里,Flutter SDK中也启用了许多新的规则。将我的对比表中的旧版本1.4.0(2021年9月10日)与当前版本2.0.0(2022年5月21日)相比较,我们看到Flutter仓库(主通道)已经从129条启用的规则(67.2%),变成152条(74.9%)启用的linting规则。

它一直使用的一个有趣的选择,也是我个人喜欢的,就是always_specify_types规则。这使得代码非常冗长,因此很少有开发者喜欢它。它的优点是使阅读不熟悉的代码更容易,特别是在GitHub上,你不能用IDE来偷看类型信息。

比较和选择

你可以用我的比较表来比较Dart和Flutter的默认提示,与过去和目前流行的提示包,以及Flutter仓库本身进行比较。您可以看到他们启用的每一条规则,并根据比较结果做出您自己的选择。

如果你想自己保持在你的提示规则设置的顶端,那么就像我一样,滚动你自己的提示规则配置。大多数情况下,我这样做是为了使用比目前的软件包提示器提供的更严格的提示规则,也是为了做出我喜欢的有主见的选择。当涉及到非常有主见的个人偏好规则时,大多数lint包都故意避免为你做出任何选择。

我也喜欢在一个文件中启用所有规则的简洁设置,包括所有当前可用的规则,然后只关闭我不使用的规则。这使设置易于维护。你也可以做同样的事情,或者走简单的路线,只使用默认的Flutter lints,或者使用Very Good AnalysisLint走狭窄而严格的道路。

如果你不关心自己的提示和调整,好的部分是,一个好的基本提示设置是Flutter的一部分。从Flutter的2.5版本开始,你会得到一个坚实的规则集,默认为新项目启用。这是Flutter团队提供的一个很好的举措。这意味着,最终所有的Flutter项目都将默认使用坚实的提示规则。这些规则将有助于提高Flutter应用程序和包的质量。由于我们现在处于Flutter 3.0,这个目标已经在很大程度上实现了。

所有这些包之间的规则差异是什么?

所有这些包之间有哪些规则上的差异?这是个非常好的问题。我想我把这个博客中最有趣的部分留到了最后。我对这个问题也非常好奇,所以我查看了所有的lint设置,包括以下lint包和设置。

Lint stylePrevious% of rulesUsed now+/-% of rules
Dart Core  (v2.0.0)2613.5%28+213.8%
Dart Recommended  (v2.0.0)7438.5%84+1041.4%
Flutter lints  (v2.0.1)8544.3%97+1247.8 %
Pedantic  (v1.11.1) (Deprecated)5227.1%52025.6%
Effective Dart  (v1.3.2) (Deprecated)5729.7%57028.1%
Flutter SDK repository  (master)12967.2%152+2374.9%
Lint  (v1.8.2)14776.6%152+574.9%
Very Good Analysis  (v3.0.0)15379.7%177+2487.2%
RydMike - All ON, then turn OFF some  (v2.0.0)17189.1%183+1290.1%
All LINT rules192100.0%203+11100.0%

以前的值指的是2021年9月10日的1.4.0版本的比较表中启用的提示性规则的数量,以及最新的提示性规则比较表中现在使用的规则,即2022年5月21日更新的2.0.0版本。

以下是Google Sheet中的完整比较,请欣赏!

image.png

我在审查设置时可能犯了一些错误,如果你注意到任何错误,请告诉我,我将更新它。你可以在Twitter上找到我

更多代码分析?

如果你想更深入地了解Dart代码分析,我推荐你看看Dart代码度量。这是一个静态分析工具,可以帮助你分析和提高Dart的代码质量。它通过计算具有可配置阈值的代码指标来收集代码的分析数据,并为Dart分析器提供附加规则。

(2022年5月21日页面更新)


www.deepl.com 翻译