Contents

Effective Dart: Style

好的代码令人惊讶的重要部分是好的样式. 一致的命名,排序和格式有助于代码相同的外观相同. 它利用了我们大多数人眼系统中强大的图案匹配硬件. 如果我们在整个Dart生态系统中使用一致的样式,则这将使我们所有人都更容易学习彼此的代码并做出贡献.

Identifiers

标识符在Dart中具有三种风格.

  • UpperCamelCase名称将每个单词的首字母大写,包括第一个字母.

  • lowerCamelCase名称为每个字的第一个字母, 除了第一个它总是小写,即使它是一个缩写.

  • lowercase_with_underscores仅使用小写字母(即使是首字母缩写词),并使用_分隔单词.

DO name types using UpperCamelCase.

短绒规则: camel_case_types

类,枚举类型,typedef和类型参数应将每个单词的首字母大写(包括第一个单词),并且不使用分隔符.

class SliderMenu { ... }

class HttpRequest { ... }

typedef Predicate<T> = bool Function(T value);

This even includes classes intended to be used in metadata annotations.

class Foo {
  const Foo([arg]);
}

@Foo(anArg)
class A { ... }

@Foo()
class B { ... }

如果注释类的构造函数不带任何参数,则可能要为其创建一个单独的lowerCamelCase常量.

const foo = Foo();

@foo
class C { ... }

DO name extensions using UpperCamelCase.

短绒规则: camel_case_extensions

Like types, extensions should capitalize the first letter of each word (including the first word), and use no separators.

extension MyFancyList<T> on List<T> { ... }

extension SmartIterable<T> on Iterable<T> { ... }

DO name libraries, packages, directories, and source files using lowercase_with_underscores.

林特规则: library_names, file_names

一些文件系统不区分大小写,因此许多项目要求文件名全部为小写. 使用分隔字符允许名称仍以该形式可读. 使用下划线作为分隔符可确保名称仍然是有效的Dart标识符,如果该语言以后支持符号导入,则可能会有所帮助.

library peg_parser.source_scanner;

import 'file_system.dart';
import 'slider_menu.dart';
library pegparser.SourceScanner;

import 'file-system.dart';
import 'SliderMenu.dart';

DO name import prefixes using lowercase_with_underscores.

林特规则: 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;

DO name other identifiers using lowerCamelCase.

短绒规则: non_constant_identifier_names

类成员,顶级定义,变量,参数和命名参数应将第一个单词以外的每个单词的首字母大写,并且不使用分隔符.

var item;

HttpRequest httpRequest;

void align(bool clearItems) {
  // ...
}

PREFER using lowerCamelCase for constant names.

Linter规则: constant_identifier_names

在新代码中,将lowerCamelCase用于常量变量,包括枚举值.

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生成的枚举类型.

DO capitalize acronyms and abbreviations longer than two letters like words.

大写的首字母缩写词可能难以阅读,并且多个相邻的首字母缩写词可能导致名称不明确. 例如,给定以HTTPSFTP开头的名称,则无法分辨它是指HTTPS FTP还是HTTP SFTP.

为避免这种情况,首字母缩写词和缩写词与普通单词一样大写,除了两个字母的首字母缩写词. (ID和Mr.等两个字母的缩写仍像单词一样大写.)

HttpConnectionInfo
uiHandler
IOStream
HttpRequest
Id
DBIOPort
TVVcr
HTTPConnection
UiHandler
IoStream
HTTPRequest
ID
DbIoPort
TvVcr

DON’T use a leading underscore for identifiers that aren’t private.

Dart在标识符中使用前导下划线将成员和顶级声明标记为私有. 这样可以培训用户将领先的下划线与其中一种声明相关联. 他们看到" _"并认为"私有".

对于局部变量,参数或库前缀,没有"专用"的概念. 当其中之一的名称以下划线开头时,它会向阅读器发送一个混乱的信号. 为避免这种情况,请勿在这些名称中使用前划线.

例外:可以将未使用的参数命名为______等.这种情况发生在回调中,在该回调中您可以向其传递一个值,但不需要使用它. 给它一个包含下划线的名称是一种惯用的方式,用于指示未使用该值.

DON’T use prefix letters.

BCPL时代出现了匈牙利表示法和其他方案,当时编译器并没有帮助您理解代码. 由于Dart可以告诉您声明的类型,范围,可变性和其他属性,因此没有理由在标识符名称中对这些属性进行编码.

defaultTimeout
kDefaultTimeout

Ordering

为了使文件的序言保持整洁,我们有一条应在指令中出现的规定顺序.每个"节"都应以空白行分隔.

一条短绒规则将处理所有排序准则: directives_ordering.

DO place “dart:” imports before other imports.

Linter规则: directives_ordering

import 'dart:async';
import 'dart:html';

import 'package:bar/bar.dart';
import 'package:foo/foo.dart';

DO place “package:” imports before relative imports.

Linter规则: directives_ordering

import 'package:bar/bar.dart';
import 'package:foo/foo.dart';

import 'util.dart';

DO specify exports in a separate section after all imports.

Linter规则: 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';

DO sort sections alphabetically.

Linter规则: 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';

Formatting

与许多语言一样,Dart会忽略空格. 但是, 人类没有. 具有一致的空格样式有助于确保人类读者以与编译器相同的方式查看代码.

DO format your code using dartfmt.

格式化是繁琐的工作,并且在重构期间特别耗时. 幸运的是,您不必担心. 我们提供了一个称为dartfmt的复杂的自动代码格式化程序 ,可以为您完成此任务. 我们有一些有关适用规则的文档 ,但是Dart的官方空白处理规则是dartfmt生成的 .

其余的格式指南仅针对dartfmt无法为您解决的一些问题.

CONSIDER changing your code to make it more formatter-friendly.

格式化程序无论使用什么代码,都可以尽其所能,但是它不能解决奇迹. 如果您的代码具有特别长的标识符,深层嵌套的表达式,不同类型的运算符的混合等等,那么格式化的输出可能仍然难以阅读.

发生这种情况时,请重新组织或简化代码. 考虑缩短局部变量名称或将表达式提升为新的局部变量. 换句话说,进行与您手动格式化代码并尝试使其更具可读性的修改方式相同的修改. 可以将dartfmt视为一种伙伴关系,在这种伙伴关系中,有时需要反复合作才能产生漂亮的代码.

AVOID lines longer than 80 characters.

短绒规则: lines_longer_than_80_chars

可读性研究表明,较长的文本行较难阅读,因为移至下一行的开始时,您的眼睛必须走得更远. 这就是报纸和杂志使用多列文字的原因.

如果您真的希望行长超过80个字符,则我们的经验是您的代码可能太冗长,并且可能更紧凑. 主要罪犯通常是VeryLongCamelCaseClassNames . 问问自己:"该类型名称中的每个单词是否都告诉我一些关键信息或防止名称冲突?" 如果不是,请考虑省略它.

请注意,dartfmt为您完成了其中的99%,但最后1%是您. 它不会将长字符串文字拆分为80列,因此您必须手动进行操作.

例外:当URI或文件路径出现在注释或字符串中(通常在导入或导出中)时,即使它导致行超过80个字符,也可能保持完整. 这样可以更轻松地在源文件中搜索路径.

例外:多行字符串可以包含多于80个字符的行,因为换行符在字符串内很重要,将行拆分为较短的行可以更改程序.

DO use curly braces for all flow control statements.

Linter规则: curl_braces_in_flow_control_structures

这样做可以避免其他问题.

if (isWeekDay) {
  print('Bike to work!');
} else {
  print('Go dancing or read a book!');
}

例外:当你有一个if声明没有else条款和整个if在一行语句配合,你可以,如果你喜欢省略大括号:

if (arg == null) return defaultValue;

但是,如果正文换行到下一行,请使用花括号:

if (overflowChars != other.overflowChars) {
  return overflowChars < other.overflowChars;
}
if (overflowChars != other.overflowChars)
  return overflowChars < other.overflowChars;

by  ICOPY.SITE