1.4 代码风格指南
标识符
在 Dart 中标识符有三种类型
- UpperCamelCase 每个单词的首字母都大写,包含第一个单词
- lowerCamelCase 每个单词的首字母都大写,除了第一个单词, 第一个单词首字母小写,即使是缩略词
- lowercase_with_underscores 只是用小写字母单词,即使是缩略词, 并且单词之间使用 _ 连接
要使用 UpperCamelCase 风格命名类型
Classes(类名)、 enums(枚举类型)、 typedefs(类型定义)、 以及 type parameters(类型参数)应该把每个单词的首字母都大写(包含第一个单词),不使用分隔符
class SliderMenu { ... }
class HttpRequest { ... }
typedef Predicate \= bool Function<T\>(T value);
这里包括使用元数据注解的类
class Foo { const Foo(\[arg\]); }
@Foo(anArg) class A { ... }
@Foo() class B { ... }
要在库,包,文件夹,源文件中使用
lowercase\_with\_underscores 方式命名
Linter rules: library_names, file_names
要用 lowercase_with_underscores 风格命名库和源文件名
一些文件系统不区分大小写,所以很多项目要求文件名必须是小写字母。 使用分隔符这种形式可以保证命名的可读性。使用下划线作为分隔符可确保名称仍然是有效的Dart标识符, 如果语言后续支持符号导入,这将会起到非常大的帮助。
library peg\_parser.source\_scanner;
import 'file\_system.dart';
import 'slider\_menu.dart';
library pegparser.SourceScanner;
import 'file\-system.dart'; import 'SliderMenu.dart';
⚠️ 注意: 如果你选择命名库,本准则给定了如何为库取名。 如果需要,可以在文件中_省略_库指令
要使用 lowercase_with_underscores 风格命名导入的前缀
Linter rule: library_prefixes
import 'dart:math' as math;
import 'package:angular\_components/angular\_components'
as angular\_components;
import 'package:js/js.dart' as js;
import 'dart:math' as Math;
import 'package:angular\_components/angular\_components'
as angularComponents;
import 'package:js/js.dart' as JS;
要使用 lowerCamelCase 风格来命名其他的标识符
Linter rule: non_constant_identifier_names
类成员、顶级定义、变量、参数以及命名参数等 除了第一个单词,每个单词首字母都应大写,并且不使用分隔符。
var item;
HttpRequest httpRequest;
void align(bool clearItems) {
// ...
}
推荐使用 lowerCamelCase 来命名常量
Linter rule: constant_identifier_names
在新的代码中,使用 lowerCamelCase 来命名常量,包括枚举的值。 已有的代码使用了 SCREAMING_CAPS 风格, 你可以继续全部使用该风格来保持代码的一致性
const pi \= 3.14;
const defaultTimeout \= 1000;
final urlScheme \= RegExp('^(\[a\-z\]+):');
class Dice { static final numberGenerator \= Random(); }
const PI = 3.14;
const DefaultTimeout = 1000;
final URL\_SCHEME = RegExp('^(\[a\-z\]+):');
class Dice { static final NUMBER\_GENERATOR = Random(); }
您可以使用 SCREAMING_CAPS 与现有代码保持一致,比如:
- 将代码添加到已使用 SCREAMING_CAPS 的文件或库时。
- 生成与 Java 代码并行的 Dart 代码时。例如,来自 protobufs 的枚举类型
注意: 我们一开始使用 Java SCREAMING_CAPS 风格来命名常量。 我们之所以不再使用,是因为:
- SCREAMING_CAPS 很多情况下看起来比较糟糕, 尤其类似于 CSS 颜色这类的枚举值
- 常量常常被修改为 final 类型的非常量变量, 这种情况你还需要修改变量的名字为小写字母形式
- 在枚举类型中自动定义的 values 属性为常量并且是小写字母 形式的
要把超过两个字母的首字母大写缩略词和缩写词当做一般单词来对待
首字母大写缩略词比较难阅读, 特别是多个缩略词连载一起的时候会引起歧义。 例如,一个以 HTTPSFTP 开头的名字, 没有办法判断它是指 HTTPS FTP 还是 HTTP SFTP 。
为了避免上面的情况,缩略词和缩写词要像普通单词一样首字母大写, 两个字母的单词除外。 (像 ID 和 Mr. 这样的双字母缩写词仍然像一般单词一样首字母大写。)
HttpConnectionInfo uiHandler IOStream HttpRequest Id DB
HTTPConnection UiHandler IoStream HTTPRequest ID Db
译者注:
- acronyms:首字母缩略词,指取若干单词首字母组成一个新单词,如:HTTP = HyperText Transfer Protocol
- abbreviations: 缩写词,指取某一单词的部分字母(或其他缩短单词的方式)代表整个单词,如:ID = identification
不要 使用前缀字母
在编译器无法帮助你了解自己代码的时, 匈牙利命名法 和其他方案出现在了 BCPL , 但是因为 Dart 可以提示你声明的类型,范围,可变性和其他属性, 所以没有理由在标识符名称中对这些属性进行编码。
defaultTimeout 👌
kDefaultTimeout ❌
顺序
为了使文件前面部分保持整洁,我们规定了关键字出现顺序的规则。 每个“部分”应该使用空行分割。
A single linter rule handles all the ordering guidelines: directives_ordering
要 把 “dart:” 导入语句放到其他导入语句之前
Linter rule: directives_ordering
import 'dart:async';
import 'dart:html';
import 'package:bar/bar.dart';
import 'package:foo/foo.dart';
要把 “package:” 导入语句放到项目相关导入语句之前
Linter rule: directives_ordering
import 'package:bar/bar.dart';
import 'package:foo/foo.dart';
import 'util.dart';
推荐把外部扩展 “package:” 导入语句放到其他语句之前
如果你使用了多个 “package:” 导入语句来导入自己的包以及其他外部扩展包, 推荐将自己的包分开放到一个额外的部分
import 'package:bar/bar.dart';
import 'package:foo/foo.dart';
import 'package:my\_package/util.dart';
要把导出(export)语句作为一个单独的部分放到所有导入语句之后
Linter rule: directives_ordering
import 'src/error.dart';
import 'src/foo\_bar.dart';
export 'src/error.dart';
import 'src/error.dart';
export 'src/error.dart';
import 'src/foo\_bar.dart';
要 按照字母顺序package:my_package/util
Linter rule: directives_ordering
import 'package:bar/bar.dart';
import 'package:foo/foo.dart';
import 'foo.dart';
import 'foo/foo.dart';
import 'package:foo/foo.dart';
import 'package:bar/bar.dart';
import 'foo/foo.dart';
import 'foo.dart';
格式化
和其他大部分语言一样, Dart 忽略空格。但是,人不会。 具有一致的空格风格有助于帮助我们能够用编译器相同的方式理解代码
要使用 dartfmt 格式化你的代码
格式化是一项繁琐的工作,尤其在重构过程中特别耗时。 庆幸的是,你不必担心。 我们提供了一个名为 dartfmt 的优秀的自动代码格式化程序,它可以为你完成格式化工作。 我们有一些关于它适用的规则的 文档 , Dart 中任何官方的空格处理规则由 dartfmt 生成
其余格式指南用于 dartfmt 无法修复的一些规则
考虑修改你的代码让格式更友好
无论你扔给格式化程序什么样代码,它都会尽力去处理, 但是格式化程序不会创造奇迹。 如果代码里有特别长的标识符,深层嵌套的表达式,混合的不同类型运算符等。 格式化输出的代码可能任然很难阅读。
当有这样的情况发生时,那么就需要重新组织或简化你的代码。 考虑缩短局部变量名或者将表达式抽取为一个新的局部变量。 换句话说,你应该做一些手动格式化并增加代码的可读性的修改。 在工作中应该把 dartfmt 看做一个合作伙伴, 在代码的编写和迭代过程中互相协作输出优质的代码
避免单行超过 80 个字符
Linter rule: lines_longer_than_80_chars
可读性研究表明,长行的文字不易阅读, 长行文字移动到下一行的开头时,眼睛需要移动更长的距离。 这也是为什么报纸和杂志会使用多列样式的文字排版。
如果你真的发现你需要的文字长度超过了 80 个字符, 根据我们的经验,你的代码很可能过于冗长, 而且有方式可以让它更紧凑。 最常见的的一种情况就是使用 VeryLongCamelCaseClassNames (非常长的类名字和变量名字)。 当遇到这种情况时,请自问一下:“那个类型名称中的每个单词都会告诉我一些关键的内容或阻止名称冲突吗?”, 如果不是,考虑删除它。
注意,dartfmt 能自动处理 99% 的情况,但是剩下的 1% 需要你自己处理。 dartfmt 不会把很长的字符串字面量分割为 80 个字符的列, 所以这种情况你需要自己手工确保每行不超过 80 个字符。
对于包含 URIs 的字符串则是一个例外—主要是导入和导出语句。 如果导入导出语句很长,则还是放到同一行上。 这样可以方便搜索某一个路径下的代码文件。
我们对 URI 和文件路径做了例外。 当情况出现在注释或字符串是(通常在导入和导出语句中), 即使文字超出行限制,也可能会保留在一行中。 这样可以更轻松地搜索给定路径的源文件
要对所有流控制结构使用花括号
Linter rule: curly_braces_in_flow_control_structures
这样可以避免 dangling else (else悬挂)的问题
if (isWeekDay) {
print('Bike to work!');
} else {
print('Go dancing or read a book!');
}
这里有一个例外:一个没有 else 的 if 语句, 并且这个 if 语句以及它的执行体适合在一行中实现。 在这种情况下,如果您愿意,可以不用括号:
if (arg \== null) return defaultValue;
但是,如果执行体包含下一行,请使用大括号:
if (overflowChars != other.overflowChars) {
return overflowChars < other.overflowChars;
}
if (overflowChars != other.overflowChars)
return overflowChars < other.overflowChars;
网友评论