有效 Dart
在过去的几年里,我们编写了大量的 Dart 代码,并了解了很多关于什么有效以及什么无效的知识。我们与您分享这些信息,以便您也可以编写一致、健壮、快速的代码。有两个主要的主题
保持一致。 在格式和大小写等方面,关于哪种更好是主观的,无法解决。我们所知道的是,保持一致 绝对有用。
如果两段代码看起来不同,应该是因为它们在某种有意义的方式上是不同的。当一段代码脱颖而出并引起你的注意时,它应该出于有用的原因。
简洁。 Dart 的设计是为了熟悉,因此它继承了 C、Java、JavaScript 和其他语言中许多相同的语句和表达式。但是我们创建 Dart 是因为这些语言提供的功能还有很大的改进空间。我们添加了许多功能,从字符串插值到初始化形式参数,以帮助您更简单、更轻松地表达您的意图。
如果有多种方法可以表达某件事,你通常应该选择最简洁的一种。这并不是说你应该代码高尔夫将整个程序压缩成一行。目标是经济的代码,而不是密集的代码。
指南
#我们将指南分为几个独立的页面,以便于消化
样式指南 – 这定义了代码布局和组织的规则,或者至少定义了
dart format
未为你处理的部分。样式指南还指定了标识符的格式:camelCase
、using_underscores
等。文档指南 – 这告诉了你有关注释中包含内容的所有信息。包括文档注释和普通代码注释。
用法指南 – 这教你如何最佳地利用语言特性来实现行为。如果它在语句或表达式中,那么它都会在这里涵盖。
设计指南 – 这是最柔和的指南,但也是范围最广的指南。它涵盖了我们在设计一致、易用的库 API 时所学到的经验教训。如果它在类型签名或声明中,那么这将会涵盖它。
有关所有指南的链接,请参阅摘要。
如何阅读指南
#每个指南都分为几个部分。部分包含一系列指南。每个指南都以以下词语之一开头
DO 指南描述了应该始终遵循的做法。几乎没有正当理由偏离它们。
DON'T 指南与之相反:几乎从来都不是好主意的事情。希望我们没有像其他语言那样多的这种指南,因为我们有更少的历史包袱。
PREFER 指南是你应该遵循的做法。但是,在某些情况下,可能也有其他做法更合理。当你这样做的时候,请确保你完全了解忽略该指南的全部影响。
AVOID 指南是 "prefer" 的对立:你不应该做的事情,但在极少数情况下可能会有充分的理由这样做。
CONSIDER 指南是你在某些情况下可能想要遵循也可能不想遵循的做法,具体取决于情况、先例和你的个人偏好。
有些指南描述了该规则不适用的例外情况。当列出时,例外情况可能并不详尽—你可能仍然需要在其他情况下使用你的判断。
这听起来像是如果你没有系好鞋带,警察就会破门而入。事情并没有那么糟糕。这里的大多数指南都是常识,我们都是理智的人。目标,一如既往,是编写美观、可读、易于维护的代码。
Dart 分析器提供了一个 linter 来帮助你编写符合这些指南和其他指南的良好、一致的代码。如果存在一个或多个linter 规则可以帮助你遵循某个指南,那么该指南会链接到这些规则。链接使用以下格式
Linter 规则:unnecessary_getters_setters
要了解如何使用 linter,请参阅启用 linter 规则和linter 规则列表。
术语表
#为了使指南简明扼要,我们使用了一些简写术语来指代不同的 Dart 结构。
库成员是顶级字段、getter、setter 或函数。基本上,顶级的所有内容,除了类型。
类成员是在类内声明的构造函数、字段、getter、setter、函数或运算符。类成员可以是实例或静态的、抽象的或具体的。
成员是库成员或类成员。
变量,当一般使用时,指的是顶级变量、参数和局部变量。它不包括静态或实例字段。
类型是任何命名的类型声明:类、类型定义或枚举。
属性是顶级变量、getter(在类内或顶级,实例或静态)、setter(相同)或字段(实例或静态)。大致上任何 "字段类" 命名的结构。
所有规则摘要
#样式
#标识符
- DO 使用
UpperCamelCase
来命名类型。 - DO 使用
UpperCamelCase
来命名扩展。 - DO 使用
lowercase_with_underscores
来命名包、目录和源文件。 - DO 使用
lowercase_with_underscores
来命名导入前缀。 - DO 使用
lowerCamelCase
来命名其他标识符。 - PREFER 使用
lowerCamelCase
来命名常量。 - DO 将超过两个字母的首字母缩略词和缩写大写,如同单词一样。
- PREFER 使用
_
、__
等来命名未使用的回调参数。 - DON'T 为非私有标识符使用前导下划线。
- DON'T 使用前缀字母。
- DON'T 显式命名库。
排序
格式
文档
#注释
文档注释
- 使用
///
文档注释对成员和类型进行文档化。 - 优先为公共 API 编写文档注释。
- 考虑编写库级文档注释。
- 考虑为私有 API 编写文档注释。
- 文档注释以单个句子摘要开头。
- 将文档注释的第一句话放在单独的一段中。
- 避免与周围环境重复。
- 优先使用第三人称动词开头函数或方法注释。
- 优先使用名词短语开头非布尔型变量或属性注释。
- 优先使用 "Whether" 后跟名词或动名词短语开头布尔型变量或属性注释。
- 不要为属性的 getter 和 setter 都编写文档。
- 优先使用名词短语开头库或类型注释。
- 考虑在文档注释中包含代码示例。
- 在文档注释中使用方括号引用作用域内标识符。
- 使用散文解释参数、返回值和异常。
- 将文档注释放在元数据注释之前。
Markdown
编写
用法
#库
空
- 不要显式地将变量初始化为空值
null
。 - 不要使用显式
null
作为默认值。 - 不要在相等运算中使用
true
或false
。 - 如果需要检查变量是否已初始化,请避免使用
late
变量。 - 考虑使用类型提升或空值检查模式来使用可空类型。
字符串
集合
- 尽可能使用集合字面量。
- 不要使用
.length
检查集合是否为空。 - 避免使用
Iterable.forEach()
以及函数字面量。 - 不要使用
List.from()
,除非你打算更改结果的类型。 - 使用
whereType()
按类型过滤集合。 - 如果附近的运算可以完成,请不要使用
cast()
。 - 避免使用
cast()
。
函数
变量
成员
- 不要不必要地将字段包装在 getter 和 setter 中。
- 优先使用
final
字段创建只读属性。 - 考虑对简单的成员使用
=>
。 - 不要使用
this.
,除非重定向到命名构造函数或避免遮蔽。 - 尽可能在声明时初始化字段。
构造函数
错误处理
- 避免没有
on
子句的捕获块。 - 不要在没有
on
子句的捕获块中丢弃错误。 - 对于程序性错误,仅抛出实现
Error
的对象。 - 不要显式地捕获
Error
或实现它的类型。 - 使用
rethrow
重新抛出捕获的异常。
异步
设计
#名称
- 一致地使用术语。
- 避免使用缩写。
- 优先将最具描述性的名词放在最后。
- 考虑使代码像句子一样阅读。
- 优先使用名词短语表示非布尔型属性或变量。
- 优先使用非祈使式动词短语表示布尔型属性或变量。
- 考虑省略命名布尔型参数的动词。
- 优先使用布尔型属性或变量的 "肯定" 名称。
- 如果函数或方法的主要目的是副作用,则优先使用祈使式动词短语。
- 如果返回值是函数或方法的主要目的,则优先使用名词短语或非祈使式动词短语。
- 如果你想突出它所执行的工作,则考虑使用祈使式动词短语表示函数或方法。
- 避免以
get
开头方法名。 - 如果方法将对象的 state 复制到新对象,则优先使用
to___()
命名它。 - 如果方法返回一个不同但基于原始对象的表示形式,则优先使用
as___()
命名它。 - 避免在函数或方法名中描述参数。
- 在命名类型参数时,请遵循现有的助记符约定。
库
类和 mixin
- 如果简单的函数可以完成,请避免定义只有一个成员的抽象类。
- 避免定义只包含静态成员的类。
- 避免扩展不打算被子类的类。
- 如果你的类支持扩展,请对其进行文档化。
- 避免实现不打算用作接口的类。
- 如果你的类支持用作接口,请对其进行文档化。
- 优先使用纯
mixin
或纯class
代替mixin class
。
构造函数
成员
- 优先使用
final
创建字段和顶级变量。 - 对于概念上访问属性的操作,请使用 getter。
- 对于概念上更改属性的操作,请使用 setter。
- 不要在没有相应 getter 的情况下定义 setter。
- 避免使用运行时类型测试模拟重载。
- 避免使用没有初始化程序的公共
late final
字段。 - 避免返回可空
Future
、Stream
和集合类型。 - 避免仅为了启用流畅接口从方法中返回
this
。
类型
- 为没有初始化程序的变量添加类型注释。
- 如果类型不明显,请为字段和顶级变量添加类型注释。
- 不要为已初始化的局部变量冗余地添加类型注释。
- 为函数声明添加返回值类型注释。
- 为函数声明添加参数类型注释。
- 不要为函数表达式上的推断参数类型添加注释。
- 不要为初始化形式参数添加类型注释。
- 对于没有推断的泛型调用,请编写类型参数。
- 对于已推断的泛型调用,请不要编写类型参数。
- 避免编写不完整的泛型类型。
- 使用
dynamic
添加注释,而不是让推断失败。 - 优先在函数类型注释中使用签名。
- 不要为 setter 指定返回值类型。
- 不要使用旧的 typedef 语法。
- 优先使用内联函数类型代替 typedef。
- 优先使用函数类型语法表示参数。
- 避免使用
dynamic
,除非你想要禁用静态检查。 - 对于不生成值的异步成员,请使用
Future<void>
作为返回值类型。 - 避免使用
FutureOr<T>
作为返回值类型。
参数
相等
除非另有说明,否则本网站上的文档反映了 Dart 3.5.3。页面最后更新于 2024-05-06。 查看源代码 或 报告问题.