高效 Dart
过去几年,我们编写了大量的 Dart 代码,并学习了很多关于哪些方法有效,哪些方法无效的知识。我们与您分享这些知识,以便您也可以编写一致、健壮、快速的代码。有两个主要的主题:
保持一致性。 在格式和大小写等方面,关于哪种更好是主观的,无法解决。我们知道的是, 一致性 客观上有帮助。
如果两段代码看起来不同,那应该是因为它们在某种有意义的方式上是 不同 的。当一段代码脱颖而出并引起您的注意时,它应该有其有用的原因。
简洁明了。 Dart 的设计易于理解,因此它继承了 C、Java、JavaScript 和其他语言的许多相同语句和表达式。但是我们创建 Dart 是因为这些语言提供的功能还有很大的改进空间。我们添加了许多功能,从字符串插值到初始化形式参数,以帮助您更简单、更容易地表达您的意图。
如果有多种表达方式,您通常应该选择最简洁的一种。这并不是说您应该 代码高尔夫 将整个程序压缩到一行中。目标是 经济型 的代码,而不是 密集型 的代码。
指南
#我们将指南分成几个单独的页面,便于理解:
风格指南 – 这定义了代码布局和组织的规则,或者至少是
dart format
没有为您处理的部分。风格指南还指定了标识符的格式:camelCase
、using_underscores
等。文档指南 – 这告诉您关于注释内容的所有信息。包括文档注释和普通的代码注释。
使用指南 – 这将教你如何最好地利用语言特性来实现行为。如果它在语句或表达式中,这里就会介绍。
设计指南 – 这是最宽松的指南,但范围最广。它涵盖了我们在设计一致、易用的库 API 方面学到的知识。如果它在类型签名或声明中,这里会介绍。
有关所有指南的链接,请参阅 摘要 。
如何阅读指南
#每个指南都分成几个部分。各部分包含一系列指南。每个指南都以以下词语开头:
DO 指南描述应始终遵循的实践。几乎永远没有理由偏离它们。
DON'T 指南是相反的:几乎永远不是好主意的东西。希望我们不像其他语言那样有那么多这样的指南,因为我们没有那么多的历史包袱。
PREFER 指南是您 应该 遵循的做法。但是,在某些情况下,这样做可能是有意义的。如果您这样做,请务必了解忽略该指南的全部含义。
AVOID 指南与“prefer”相反:您不应该做的事情,但在极少数情况下可能有充分的理由。
CONSIDER 指南是您可能想要或可能不想要遵循的做法,具体取决于环境、先例和您的个人喜好。
一些指南描述了规则 不 适用的 例外情况 。列出时,例外情况可能并不详尽——您可能仍然需要在其他情况下使用您的判断力。
这听起来好像如果您鞋带系得不正确,警察就会冲破你的门。事情并没有那么糟糕。这里的大多数指南都是常识,我们都是通情达理的人。目标,一如既往,是编写漂亮、可读且易于维护的代码。
Dart 分析器提供了一个棉绒检查器,以帮助您编写符合这些和其他指南的良好、一致的代码。如果存在一个或多个 棉绒检查器规则 可以帮助您遵循指南,则该指南会链接到这些规则。这些链接使用以下格式:
Linter 规则:
要了解如何使用棉绒检查器,请参阅 启用棉绒检查器规则 和 棉绒检查器规则 列表。
词汇表
#为了使指南简洁明了,我们使用一些简写术语来指代不同的 Dart 结构。
库成员 是顶级字段、getter、setter 或函数。基本上,任何不在顶级且不是类型的成员。
类成员 是在类内声明的构造函数、字段、getter、setter、函数或运算符。类成员可以是实例或静态的、抽象的或具体的。
成员 是库成员或类成员。
变量 ,当一般使用时,指的是顶级变量、参数和局部变量。它不包括静态或实例字段。
类型 是任何命名的类型声明:类、typedef 或枚举。
属性 是顶级变量、getter(在类内或顶级,实例或静态)、setter(相同)或字段(实例或静态)。大致上任何“类似字段”的命名结构。
所有规则摘要
#样式
#标识符
- 使用
UpperCamelCase
命名类型。 - 使用
UpperCamelCase
命名扩展。 - 使用
lowercase_with_underscores
命名包、目录和源文件。 - 使用
lowercase_with_underscores
命名导入前缀。 - 使用
lowerCamelCase
命名其他标识符。 - 建议对常量名称使用
lowerCamelCase
。 - 将超过两个字母的首字母缩写词和缩写词像单词一样大写。
- 建议对未使用的回调参数使用
_
、__
等。 - 不要对非私有标识符使用前导下划线。
- 不要使用前缀字母。
- 不要显式命名库。
顺序
格式化
文档
#注释
文档注释
- 使用
///
文档注释来记录成员和类型。 - 建议为公共API编写文档注释。
- 考虑编写库级别的文档注释。
- 考虑为私有API编写文档注释。
- 文档注释以单句摘要开头。
- 将文档注释的第一句分成单独的一段。
- 避免与周围环境冗余。
- 建议用第三人称动词开头函数或方法注释。
- 建议用名词短语开头非布尔变量或属性注释。
- 建议用“Whether”后跟名词或动名词短语开头布尔变量或属性注释。
- 不要同时为属性的getter和setter编写文档。
- 建议用名词短语开头库或类型注释。
- 考虑在文档注释中包含代码示例。
- 在文档注释中使用方括号引用作用域内的标识符。
- 使用散文解释参数、返回值和异常。
- 将文档注释放在元数据注释之前。
Markdown
写作
true
或false
。 * 如果需要检查late
变量是否已初始化,请避免使用它们。 * 考虑使用类型提升或空值检查模式来使用可空类型。字符串
集合
- 尽可能使用集合字面量。
- 不要使用
.length
来查看集合是否为空。 - 避免将
Iterable.forEach()
与函数字面量一起使用。 - 除非打算更改结果的类型,否则不要使用
List.from()
。 - 使用
whereType()
按类型过滤集合。 - 如果附近的操作可以完成,则不要使用
cast()
。 - 避免使用
cast()
。
函数
变量
成员
- 不要不必要地将字段包装在getter和setter中。
- 建议使用
final
字段创建只读属性。 - 考虑对简单的成员使用
=>
。 - 除非重定向到命名构造函数或避免隐藏,否则不要使用
this.
。 - 尽可能在声明时初始化字段。
构造函数
错误处理
异步
设计
#名称
库
类和混入
- 如果简单的函数可以完成,则避免定义只有一个成员的抽象类。
- 避免定义仅包含静态成员的类。
- 避免扩展不打算被子类化的类。
- 如果您的类支持扩展,请进行说明。
- 避免实现不打算用作接口的类。
- 如果您的类支持用作接口,请进行说明。
- 建议定义纯
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.6.0。页面最后更新于 2025-02-05。 查看源代码 或 报告问题.