Dart 编码风格指南

Dart 编码风格指南

空白符

和其他语言类似,Dart 会忽略空白。但是,人们却不会这样。在代码中加入空格调整样式后可以让人们看到内容和编译器看到的类似。

不要使用 Tab 缩进。

使用空白符来格式化代码可以保证每个人在编辑器中看到的内容是一样的。这也会和传送到博客上的样式一样,或者是一些代码站点,比如 Github

现在的编辑器在缩进的时候可以模拟 tab 键来进行缩进,以让你在编写代码的时候更加轻松,并且可以保证代码的一致性。

你应该避免在编写代码时一行的长度超过八十个字符。

可读性研究表明,过长的文本不适合阅读,因为当你看到下一行的时候眼睛移动的距离过大。这就是为什么新闻以及杂志的文本都是多行的。

如果你在编码时希望一行的代码可以超过八十个字符,那么对于阅读者而言你的代码过于冗长并且有点太紧凑了。你真的希望调用一个名为 AbstractWidgetFactoryManagerBuilder 的函数吗?

应该将二元操作符放在多行表达式的前一行。

各种样式的参数都是有效的,但是大多数情况下代码看起来都是下面这个样子的,并且这样更容易保证代码的一致性。

// good
if (isDeepFried ||
    (hasPieCrust && !vegan) ||
    containsBacon) {
  print('Bob likes it.');
}

注意这也可以直接使用 =>

// good
bobLikes() =>
    isDeepFried || (hasPieCrust && !vegan) || containsBacon;
// bad
bobLikes()
    => isDeepFried || (hasPieCrust && !vegan) || containsBacon;

应该将三元运算符放在多行表达式的下一行。

同样的,如果你在操作符之前换行了,那么全部操作符之前都要换行。

// good
return someCondition
    ? whenTrue
    : whenFalse;
// bad
return someCondition ?
    whenTrue :
    whenFalse;
return someCondition
    ? whenTrue : whenFalse;

在多行表达式中应该在下一行加入 . 操作符。

这条规则优先级高于上一条。可其他操作符不同,如果你使用 . 来分隔一个表达式,那就应该把它放在第二行的开头。

// good
someVeryLongVariable.withAVeryLongProperty
    .aMethodOnThatObject();

在代码块中应该缩进两格。

// good
if (condition) {
  print('hi');
}

如果代码过长需要换行,那么下一行应该缩进四格。

// good
someLongObject.aReallyLongMethodName(longArg, anotherLongArg,
    wrappedToNextLine);

你也可以按照你的喜好来进行缩进:

// good
someLongObject.aReallyLongMethodName(longArg, anotherLongArg,
                                     wrappedToNextLine);

注意使用 => 也是可以的:

// good
bobLikes() =>
    isDeepFried || (hasPieCrust && !vegan) || containsBacon;
// bad 
bobLikes() =>
  isDeepFried || (hasPieCrust && !vegan) || containsBacon;

如果某一行的上一行是一个函数表达式,那么该行不应该缩进。

上面这个规则的一个例外就是函数表达式嵌套在另一个表达式中,比如是作为参数传递给一个方法。这些应该写成下面的格式:

// good
new Future.delayed(const Duration(seconds: 1), () {
  print('I am a callback');
});
// bad
new Future.delayed(const Duration(seconds: 1), () {
      print('I am a callback');
    });

花括号({)应该放在它之前那一行的后面。

// good
class Foo {
  method() {
    if (true) {
      // ...
    } else {
      // ...
    }
  }
}

对于全部的控制语句,都应该使用括号括起来。

这样做有助于避免 else 悬挂 的问题。

// good
if (true) {
  print('sanity');
} else {
  print('opposite day!');
}
// bad
if (true) print('sanity');
else
  print('opposite day!');

这种情况有个特例:单个 if 语句,如果没有相应的 else 语句就可以不实用括号。

// good
if (arg == null) return defaultValue;

switch 语句中的 case 语句应该缩进两个空格,case 语句的函数体应该缩进四个空格。

// good
switch (fruit) {
  case 'apple':
    print('delish');
    break;

  case 'durian':
    print('stinky');
    break;
}

在函数、操作符或者 setter 的名称与其参数列表间不要加入空格。

// good
bool convertToBool(arg) { ... }
bool operator ==(other) { ... }
set contents(value) { ... }
// bad
bool convertToBool (arg) { ... }
bool operator == (other) { ... }
set contents (value) { ... }

operator 关键字之后应该空一格。

// good
bool operator ==(other) => ...;
// bad
bool operator==(other) => ...;

二元、三元运算符的周围应该空一格,逗号之后也应该空一格,但是在一元运算符周围不应该留空格。

注意 < 以及 > 用在表达式中时是作为二元操作符的,但是作为泛型的时候则不是。is 以及 !is 只能作为二元运算符。另外,. 用于访问成员的时候绝对不能插入空格。

// good
a = 1 + 2 / (3 * -b);
c = !condition == a > b;
d = condition ? b : object.method(a, b, c);
if (obj is! SomeType) print('not SomeType');
// bad
a=1+2/(3* - b);
c= ! condition==a>b;
d= condition?b:object.method(a,b,c);
if (obj is !SomeType) print('not SomeType');

在循环语句中,in 的周围以及每个 ; 之后都应该空一格。

// good
for (var i = 0; i < 100; i++) {
  // ...
}

for (final item in collection) {
  // ...
}

流控制的关键字之后应该空一格。

这和函数调用不同,函数调用中函数名和括号之间不应该有空格。

// good 
while (foo) {
  // ...
}

try {
  // ...
} catch (e) {
  // ...
}

([{ 之前,以及 )]} 之后不应该有空格。

同样的,如果 <> 用作泛型的话也不应该在其中间留空格。

// good
var numbers = <int>[1, 2, (3 + 4)];

在函数体内的 {应该空一格。

上述规则有一个特殊情况。如果 { 是用在某个函数的参数列表之后,那么在 ) 和它之间应该空一格。

// good
getEmptyFn(a) {
  return () {};
}
// bad
getEmptyFn(a){
  return (){};
}

构造函数中的初始化应该保证每个字段都单独占一行。

// good
MyClass()
    : firstField = "some value",
      secondField = "another",
      thirdField = "last" {
  // ...
}

注意 : 应该放在函数名称的下一行开头,并且应该缩进四格。而字段则应该对齐(也就是说第一个字段总共缩进六格)。

对于已命名的的实参和形参,在 : 之后应该空一格。

// good
class ListBox {
  bool showScrollbars;

  ListBox({this.showScrollbars: false});
}

main() {
  new ListBox(showScrollbars: true);
}
// bad
new ListBox(showScrollbars:true);
new ListBox(showScrollbars : true);

可选位置参数的 = 周围应该空一格。

// good
class HttpServer {
  static Future<HttpServer> listen([int port = 80]) {
    // ...
  }
}
// bad
import 'dart:async';

class HttpServer {
  static Future<HttpServer> listen([int port=80]) {
    // ...
  }
}

方法的级联应该缩进两格。

// good
list = new List()
  ..addAll([1, 2, 3])
  ..addAll([4, 5, 6]);
// bad
list = new List()
    ..addAll([1, 2, 3])
    ..addAll([4, 5, 6]);

多行列表以及映射的字面值的代码如果采取多行形式,那么应该缩进两行,并且把闭合的 ] 或者 } 放在下一行。

多行列表以及映射的字面值最好是在逗号之后换行。

] 或者 } 应该根据上下文代码来进行缩进,以匹配上下文代码的格式。

// good
var simpleList = [1, 2, 3];
var simpleMap = {'a': 1, 'b': 2, 'c': 3};

var fooList = [
  'a',
  'b',
  'c'
];

var barMap = {
  'a': 'b',
  'c': 'd'
};

var listInsideMap = {
  'a': ['b', 'c', 'd'],
  'e': [
    'f',
    'g',
    'h'
  ]
};

var mapInsideMap = {
  'a': {'b': 'c', 'd': 'e'},
  'f': {
    'f': 'g',
    'h': 'i'
  }
};

var mapInsideList = [
  {
    'a': 'b',
    'c': 'd'
  },
  {
    'a': 'b',
    'c': 'd'
  },
];
// bad
var fooList = [
    1,
    2,
    3
];

var fooList = [
  1,
  2,
  3];

var fooList = [1, 2,
  3, 4];
07-10 11:31