Flutter开发规范(2): 2.1 代码风格

478 阅读6分钟

标识符

大小写

标识符的命名一般有大驼峰命名法、小驼峰命名法、蛇形命名法、大写蛇形命名法三种类型。

  • 大驼峰(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#中,我们常常使用大写蛇形命名法来表示常量,但是在实际项目中,由于常量通常用于参数作为传递,而且,我们会使用枚举类来替代具有选项的常量。另外一个原因,是因为大写蛇形命名法的输入更加麻烦,因此在以后的项目中,均使用小驼峰命名法来表示常量。

例外:虽然在编码中,我们使用小驼峰命名法,但是仍然有几种场景需要或者合适使用大写蛇形命名法。

  1. 由编译器生成的代码,特别是序列化相关的内容。
  2. 对接底层库时,不适用枚举而使用常量表示选项的。例如Window平台的COM接口。
  3. 其他需要使用大写蛇形命名法的情形。

更加具体的内容可以参考Effective Dart: Style > Constant

缩写

在实际的编码中,我们往往会使用专有名词,专有名词往往会很长,因此,我们需要进行一定程度的缩写来提高代码的可读性。缩写可以分成以下两种情况:

  1. 由多个单词的首字母缩写的单词(acronyms),例如Input/Output缩写成IO。
  2. 单词的缩写(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个以上的字符

研究表明,当单行文本过长时,进行文本阅读时会变得更加困难。这种情况一般出现在过长的类名、变量名时。我们常常使用恰当的换行策略来避免这种情况。然而,也存在必须保留长文本行的情况。

例外:当你在注释或者字符串中表示路径或者链接时,可以保留长文本行。

例外:在编码中存在多行文本时,可以保留长文本行,为了该规则换行时,往往会出现程序的错误。

强制:当调用具有4个及以上参数的函数时,每个参数均换行