标识符
大小写
标识符的命名一般有大驼峰命名法、小驼峰命名法、蛇形命名法、大写蛇形命名法三种类型。
- 大驼峰(UpperCamelCase):每个单词的首字母大写并连接在一起,例如
HelloWorld,一般用于表示类型的定义。 - 小驼峰(lowerCamelCase):除首个单词的首字母大写并连接在一起,例如
helloWorld,一般用于表示变量。 - 蛇形(lowercase_with_underscores):每个单词之间使用下划线
_进行连接,表示单词的分割,例如hello_world,一般用于表示文件名。 - 大写蛇形命名法(all_uppercase_with_underscores):所有字母大写,单词之间使用下划线
_进行连接,表示单词的分割,例如HELLO_WORLD,一般用于表示常量等。不过在EffectiveDart中,不再使用该类命名规范。
// 大驼峰命名法
class SliderMenu { ... }
// 小驼峰命名法
var sliderMenu = SliderMenu(...);
// 蛇形命名法
// navigator_bar.dart
// 大写蛇形命名法
const TEXT_ROUTE_MAP = 1;
强制:类名、枚举类名、别名和参数类型使用大驼峰命名法
// 类名
class HttpRequest { ... }
// 枚举类名
enum HttpStatusCode { ... }
// 别名及参数类型
typedef Predicate<T> = bool Function(T value)
强制:类扩展使用大驼峰命名法
// 类扩展
extension FancyList<T> on List<T> { ... }
强制:注解和注解类使用大驼峰命名法。推荐:为无参的注解提供小写速记符
class Foo {
const Foo([Object? arg]);
}
// 注解使用大驼峰命名法
@Foo(anArg)
class A { ... }
// 为无参的注解提供小写速记符
const foo = Foo();
// 小写的无参注释速记符
@foo
class C { ... }
强制:变量名、参数名和函数名使用小驼峰命名法。使用_开头表示私有变量
// 私有变量名
var _count = 3;
// 变量名
HttpRequest httpRequest;
// 函数名和变量名
void align(bool clearItems) {
// ...
}
强制:包名、文件夹名和源文件名使用蛇形命名法
my_package
└─ lib
└─ file_system.dart
└─ slider_menu.dart
强制:导入类库别名使用蛇形命名法
import 'dart:math' as math;
import 'package:angular_components/angular_components.dart' as angular_components;
import 'package:js/js.dart' as js;
强制:常量使用小驼峰命名法
const pi = 3.14
在Java和C#中,我们常常使用大写蛇形命名法来表示常量,但是在实际项目中,由于常量通常用于参数作为传递,而且,我们会使用枚举类来替代具有选项的常量。另外一个原因,是因为大写蛇形命名法的输入更加麻烦,因此在以后的项目中,均使用小驼峰命名法来表示常量。
例外:虽然在编码中,我们使用小驼峰命名法,但是仍然有几种场景需要或者合适使用大写蛇形命名法。
- 由编译器生成的代码,特别是序列化相关的内容。
- 对接底层库时,不适用枚举而使用常量表示选项的。例如Window平台的COM接口。
- 其他需要使用大写蛇形命名法的情形。
更加具体的内容可以参考Effective Dart: Style > Constant
缩写
在实际的编码中,我们往往会使用专有名词,专有名词往往会很长,因此,我们需要进行一定程度的缩写来提高代码的可读性。缩写可以分成以下两种情况:
- 由多个单词的首字母缩写的单词(
acronyms),例如Input/Output缩写成IO。 - 单词的缩写(
abbreviations),例如Identification缩写成Id。
强制:缩写单词时,缩写后的词首字母大写,后续均小写
// 首字母缩写成四个字母
class HttpConnection {}
// 首字母缩写成两个字母
class DBIOPort {}
// 首字母缩写成三个字母
class UserDao {}
var httpRequest = ...
var uiHandler = ...
var userId = ...
Id id;
例外:由两个单词的首字母缩写的词,字母均大写,例如Input/Output缩写成IO。而单词的缩写是两个字母时,仍然保持首字母大写,后续小写的情形。
推荐:只对10个字母及以上的单词进行缩写
// context单词较短,应当避免缩写
Context baseContext = ...
// reposiotory单词较长,推荐缩写
Repo userRepo = ...
// implemtation单词较长,推荐缩写
class ClockImpl extends Clock {}
例外:当10个字母以内的单词通常以缩写的形式出现时,也可以使用缩写的形式,当然,同一个单词在一个项目内应当同时使用或不使用缩写。
其他
强制:部分单词连接可以形成新的单词时,以长单词为准
// username是一个单词
var username = ...
推荐:使用_,__等表示为未使用的变量
futureOfVoid.then((_) {
print('Operation complete.');
});
禁止:使用new关键词创建对象
用new关键词创建对象是多余的,我们只需要调用构建函数便能生成一个新的对象。
命名
禁止:使用无意义命名表示一个变量
// a没有意义,所以不能使用
× var a = 5;
禁止:在变量名之前添加前缀
// 使用了m,k表示变量的前缀
× var mContext = ...;
× var kDefaultTime = ...;
× var mList = ...;
推荐:区分性的词在前,表属性的词在最后
一般将能够表示变量属性的中心词放在最后面,能够和其他同类词区分的单词放在前面,这样能够提高
// navigator放最后,表示其是一个导航器
var rootNavigator = ...;
// list放最后,表示其是一个列表
var bookList = ...;
× var navigatorRoot = ...;
× var listBook = ...;
强制:bool型变量命名时应当带有表示布尔含义的单词
在javascript中,我们通常为遇见例如empty()的函数,用于表示一个集合是否为空,这个函数的命名是有歧义的,因此,在该规范中,我们必须使用相应的前缀单词用于表达其是一个bool型变量,例如is,has,can,contains等。
// 初始化,没有表达其布尔的含义
× var initialized;
// 表示是否初始化的情形
var isInitialized;
格式
空行
强制:不同区域之间的代码使用空行分割
void readBuffer() { ... }
void writeBuffer() { ... }
强制:函数内部使用空行分隔不同功能段的代码
换行
禁止:单行累计使用80个以上的字符
研究表明,当单行文本过长时,进行文本阅读时会变得更加困难。这种情况一般出现在过长的类名、变量名时。我们常常使用恰当的换行策略来避免这种情况。然而,也存在必须保留长文本行的情况。
例外:当你在注释或者字符串中表示路径或者链接时,可以保留长文本行。
例外:在编码中存在多行文本时,可以保留长文本行,为了该规则换行时,往往会出现程序的错误。