内容简介:Dart支持四种集合:list、map、queue和setDart的类成员包含成员属性和方法(静态方法和实例方法)
-
类名采用
UpperCamelCase风格写法(即:单词首字母大写,多单词直接拼接,同 Java 中类命名规则) -
库和源文件使用
lowercase_with_underscores风格(即:小写字母,多单词以_分割—) -
import的库文件设置别名时,别名也使用
lowercase_with_underscores风格 -
其他标识符均使用驼峰法
-
字母缩写时,<=两个字符均大写(如:IO),>两个字符首字符大写(如:Http)
-
不要使用字母前缀(如:Java中常见的
mName写法)
排序
-
dart:系列import放在最前面 -
package:系列import放在相对import前面 -
三方包的
package:放在自己写的package:前面 -
export写在所有import后面,且留白一行以分开 - 同一优先级的import块按照字母进行排序
格式化
- 使用 dartfmt 进行代码格式化
- 避免一行超过80个字符的长度
-
对所有的流式控制均使用
{}
用法
库
-
引用自己的
lib包中的文件时,考虑使用相对路径/// my_package /// └─ lib /// ├─ src /// │ └─ utils.dart /// └─ api.dart // api.dart引用utils.dart时 // good import 'src/utils.dart'; // bad import 'package:my_package/src/utils.dart';
字符串
-
使用相邻字符串方式进行字符串拼接
// good raiseAlarm( 'ERROR: Parts of the spaceship are on fire. Other ' 'parts are overrun by martians. Unclear which are which.'); // bad raiseAlarm('ERROR: Parts of the spaceship are on fire. Other ' + 'parts are overrun by martians. Unclear which are which.'); -
使用插值方式组合字符串和值
// good 'Hello, $name! You are ${year - birth} years old.'; // bad 'Hello, ' + name + '! You are ' + (year - birth).toString() + ' y...'; -
插值时避免使用
{},除非必要// good 'Hi, $name!' "Wear your wildest $decade's outfit." 'Wear your wildest ${decade}s outfit.' // bad 'Hi, ${name}!' "Wear your wildest ${decade}'s outfit."
集合
Dart支持四种集合:list、map、queue和set
-
使用集合简化式进行实例化
// good var points = []; var addresses = {}; // bad var points = List(); var addresses = Map(); -
不要使用
.length来判断集合是否为空// good if (lunchBox.isEmpty) return 'so hungry...'; if (words.isNotEmpty) return words.join(' '); // bad if (lunchBox.length == 0) return 'so hungry...'; if (!words.isEmpty) return words.join(' '); -
推荐使用集合的高阶函数进行相关处理(如:
where、map)// good var aquaticNames = animals .where((animal) => animal.isAquatic) .map((animal) => animal.name); -
避免在
Iterable.forEach()中处理方法体编码// good for (var person in people) { ... } // bad people.forEach((person) { ... }); // 只有forEach中是函数指针, 才鼓励使用, 如下 people.forEach(print); -
除了要改变结果类型,否则不要使用
List.from()方法// good // Creates a List<int>: var iterable = [1, 2, 3]; // Prints "List<int>": print(iterable.toList().runtimeType); // bad // Creates a List<int>: var iterable = [1, 2, 3]; // Prints "List<dynamic>": print(List.from(iterable).runtimeType);
需要改变类型时,可使用该方法
// good var numbers = [1, 2.3, 4]; // List<num>. numbers.removeAt(1); // Now it only contains integers. var ints = List<int>.from(numbers);
-
使用
whereType()来进行集合的类型过滤// good var objects = [1, "a", 2, "b", 3]; var ints = objects.whereType<int>(); // bad var objects = [1, "a", 2, "b", 3]; var ints = objects.where((e) => e is int); // bad var objects = [1, "a", 2, "b", 3]; var ints = objects.where((e) => e is int).cast<int>();
-
当有更方便的操作符可使用时,不要使用
cast// good var stuff = <dynamic>[1, 2]; var ints = List<int>.from(stuff); // bad var stuff = <dynamic>[1, 2]; var ints = stuff.toList().cast<int>(); // good var stuff = <dynamic>[1, 2]; var reciprocals = stuff.map<double>((n) => 1 / n); // bad var stuff = <dynamic>[1, 2]; var reciprocals = stuff.map((n) => 1 / n).cast<double>();
-
尽量避免使用
cast关键字-
当有更方便的操作符可使用时,不要使用
cast// good var stuff = <dynamic>[1, 2]; var ints = List<int>.from(stuff); // bad var stuff = <dynamic>[1, 2]; var ints = stuff.toList().cast<int>(); // good var stuff = <dynamic>[1, 2]; var reciprocals = stuff.map<double>((n) => 1 / n); // bad var stuff = <dynamic>[1, 2]; var reciprocals = stuff.map((n) => 1 / n).cast<double>();
-
创建集合时,通过指定泛型类型代替
cast// good List<int> singletonList(int value) { var list = <int>[]; list.add(value); return list; } // bad List<int> singletonList(int value) { var list = []; // List<dynamic>. list.add(value); return list.cast<int>(); } -
遍历集合每项元素时,使用
as代替cast// good void printEvens(List<Object> objects) { // We happen to know the list only contains ints. for (var n in objects) { if ((n as int).isEven) print(n); } } // bad void printEvens(List<Object> objects) { // We happen to know the list only contains ints. for (var n in objects.cast<int>()) { if (n.isEven) print(n); } } -
需要对集合中的大多数元素做操作时,使用
List.from()代替cast// good int median(List<Object> objects) { // We happen to know the list only contains ints. var ints = List<int>.from(objects); ints.sort(); return ints[ints.length ~/ 2]; } // bad int median(List<Object> objects) { // We happen to know the list only contains ints. var ints = objects.cast<int>(); ints.sort(); return ints[ints.length ~/ 2]; }
注:
cast() cast()
-
函数
-
使用函数声明式来绑定函数和名称
// good void main() { localFunction() { ... } } // bad void main() { var localFunction = () { ... }; } -
能够传递函数指针时不要取传递冗余的lambda式
// good names.forEach(print); // bad names.forEach((name) { print(name); });
参数
-
在
命名可选参数中指定默认参数时使用=代替:// good void insert(Object item, {int at = 0}) { ... } // bad void insert(Object item, {int at: 0}) { ... }注:
:作为指定默认参数值的用法,正在被废弃 -
不要显式地置顶参数默认值为
null// good void error([String message]) { stderr.write(message ?? '\n'); } // bad void error([String message = null]) { stderr.write(message ?? '\n'); }注: 不指定默认参数值,Dart语言机制默认指定为
null,不需要冗余指定
变量
-
初始化变量时不要显式地置顶变量为
null// good int _nextId; class LazyId { int _id; int get id { if (_nextId == null) _nextId = 0; if (_id == null) _id = _nextId++; return _id; } } // bad int _nextId = null; class LazyId { int _id = null; int get id { if (_nextId == null) _nextId = 0; if (_id == null) _id = _nextId++; return _id; } } -
不要存储你能计算的值
// bad class Circle { num radius; num area; num circumference; Circle(num radius) : radius = radius, area = pi * radius * radius, circumference = pi * 2.0 * radius; } // bad class Circle { num _radius; num get radius => _radius; set radius(num value) { _radius = value; _recalculate(); } num _area; num get area => _area; num _circumference; num get circumference => _circumference; Circle(this._radius) { _recalculate(); } void _recalculate() { _area = pi * _radius * _radius; _circumference = pi * 2.0 * _radius; } } // good class Circle { num radius; Circle(this.radius); num get area => pi * radius * radius; num get circumference => pi * 2.0 * radius; }主要出于以下方面考虑:
radius
注:这里针对的是普通计算,而对于开销较大的计算,仍然要考虑存储结果作为cache。
类成员
Dart的类成员包含成员属性和方法(静态方法和实例方法)
-
不要给成员属性设置
setter和getter方法,除非必须// good class Box { var contents; } // bad class Box { var _contents; get contents => _contents; set contents(value) { _contents = value; } } -
对于只读的成员属性,尽量用
final修饰// good class Box { final contents = []; } // bad class Box { var _contents; get contents => _contents; }注:对于需要在构造方法之外复制的成员属性,可使用private的成员属性 + public的getter方法来满足
-
对于简单的成员变量/方法可考虑使用
=>// good double get area => (right - left) * (bottom - top); bool isReady(num time) => minTime == null || minTime <= time; String capitalize(String name) => '${name[0].toUpperCase()}${name.substring(1)}';但不要为了使用
=>而强行将多行表达式进行聚合,如:// good Treasure openChest(Chest chest, Point where) { if (_opened.containsKey(chest)) return null; var treasure = Treasure(where); treasure.addAll(chest.contents); _opened[chest] = treasure; return treasure; } // bad Treasure openChest(Chest chest, Point where) => _opened.containsKey(chest) ? null : _opened[chest] = Treasure(where) ..addAll(chest.contents);还可以对无返回值的成员使用
=>// good num get x => center.x; set x(num value) => center = Point(value, center.y);
-
除非你必须要使用
this避免歧义,否则不要使用它// good class Box { var value; void clear() { update(null); } void update(value) { this.value = value; } } // bad class Box { var value; void clear() { this.update(null); } void update(value) { this.value = value; } }另,Dart语言中,构造方法里不会出现成员变量与构造方法参数同名的歧义问题,如下写法是合法的
// good class Box extends BaseBox { var value; Box(value) : value = value, super(value); } -
尽可能在成员变量声明时进行初始化
// good class Folder { final String name; final List<Document> contents = []; Folder(this.name); Folder.temp() : name = 'temporary'; } // bad class Folder { final String name; final List<Document> contents; Folder(this.name) : contents = []; Folder.temp() : name = 'temporary'; // Oops! Forgot contents. }
构造方法
-
尽可能使用标准构造式
注:标准构造式,官方原文是
initializing formals,参代码// good class Point { num x, y; Point(this.x, this.y); } // bad class Point { num x, y; Point(num x, num y) { this.x = x; this.y = y; } } -
不要在标准构造式中指定类型
// good class Point { int x, y; Point(this.x, this.y); } // bad class Point { int x, y; Point(int this.x, int this.y); } -
对于空方法体的构造方法,使用
;来替换{}// good class Point { int x, y; Point(this.x, this.y); } // bad class Point { int x, y; Point(this.x, this.y) {} } -
不要使用关键字
newDart1中的关键字
new是需要的,单Dart2已经将其变为可选的了。官方为了减轻升级迁移的负担,仍然支持了new关键字,但不建议使用。// good Widget build(BuildContext context) { return Row( children: [ RaisedButton( child: Text('Increment'), ), Text('Click!'), ], ); } // bad Widget build(BuildContext context) { return new Row( children: [ new RaisedButton( child: new Text('Increment'), ), new Text('Click!'), ], ); } -
不要使用冗余的关键字
const// good const primaryColors = [ Color("red", [255, 0, 0]), Color("green", [0, 255, 0]), Color("blue", [0, 0, 255]), ]; // bad const primaryColors = const [ const Color("red", const [255, 0, 0]), const Color("green", const [0, 255, 0]), const Color("blue", const [0, 0, 255]), ];
异步操作
-
尽可能使用
async和await来替换Future的链式风格// good Future<int> countActivePlayers(String teamName) async { try { var team = await downloadTeam(teamName); if (team == null) return 0; var players = await team.roster; return players.where((player) => player.isActive).length; } catch (e) { log.error(e); return 0; } } // bad Future<int> countActivePlayers(String teamName) { return downloadTeam(teamName).then((team) { if (team == null) return Future.value(0); return team.roster.then((players) { return players.where((player) => player.isActive).length; }); }).catchError((e) { log.error(e); return 0; }); } -
在关键字
async并无实际效果时不要使用它// good Future afterTwoThings(Future first, Future second) { return Future.wait([first, second]); } // bad Future afterTwoThings(Future first, Future second) async { return Future.wait([first, second]); }以下几种场景,
async是有实际效果的-
使用了
await关键字 -
返回一个异步错误时,
async+throw是return Future.error(...)的简写形式 -
你想在你方法的返回值中隐式包一个
Future
以上三种情况对应代码如下
// good Future usesAwait(Future later) async { print(await later); } Future asyncError() async { throw 'Error!'; } Future asyncValue() async => 'value'; -
使用了
-
考虑使用高阶函数来处理流
Streams提供了一系列高阶函数对流数据进行操作处理,建议优先考虑使用高阶函数
-
避免直接使用
Completer对象// bad Future<bool> fileContainsBear(String path) { var completer = Completer<bool>(); File(path).readAsString().then((contents) { completer.complete(contents.contains('bear')); }); return completer.future; } // good Future<bool> fileContainsBear(String path) { return File(path).readAsString().then((contents) { return contents.contains('bear'); }); } // good Future<bool> fileContainsBear(String path) async { var contents = await File(path).readAsString(); return contents.contains('bear'); } -
对
FutureOr<T>对象进行消除歧义时,优先判断Future<T>// good Future<T> logValue<T>(FutureOr<T> value) async { if (value is Future<T>) { var result = await value; print(result); return result; } else { print(value); return value as T; } } // bad Future<T> logValue<T>(FutureOr<T> value) async { if (value is T) { // 传递Future<Object>时会永远走该分支 print(value); return value; } else { var result = await value; print(result); return result; } }
以上所述就是小编给大家介绍的《Dart语言最佳实践》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 【语言模型系列】实践篇:ALBERT在房产领域的实践
- go语言中interface的实践
- GO语言泛型编程实践
- 探探长链接项目的 Go 语言实践
- Go 语言在百度 App 中的实践
- 我们必须遵循的 12 个 Go 语言最佳实践
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
High Performance Python
Micha Gorelick、Ian Ozsvald / O'Reilly Media / 2014-9-10 / USD 39.99
If you're an experienced Python programmer, High Performance Python will guide you through the various routes of code optimization. You'll learn how to use smarter algorithms and leverage peripheral t......一起来看看 《High Performance Python》 这本书的介绍吧!