Dart 规范

news/2024/11/24 11:50:06/

好的代码有一个非常重要的特点就是拥有好的风格。一致的命名、一致的顺序、以及一致的格式让代码看起来是一样的。这非常有利于发挥我们视力系统强大的模式匹配能力。如果我们整个 Dart 生态系统中都使用统一的风格,那么这将让我们彼此之间更容易的互相学习和互相贡献。它使我们所有人都可以更容易地学习并为彼此的代码做出贡献。

标识符

在 Dart 中标识符有三种类型。

  • UpperCamelCase 每个单词的首字母都大写,包含第一个单词。

  • lowerCamelCase 除了第一个字母始终是小写(即使是缩略词),每个单词的首字母都大写。

  • lowercase_with_underscores 只是用小写字母单词,即使是缩略词,并且单词之间使用 _ 连接。

 使用 UpperCamelCase 风格命名类型。

Linter rule: camel_case_types

Classes(类名)、 enums(枚举类型)、 typedefs(类型定义)、以及 type parameters(类型参数)应该把每个单词的首字母都大写(包含第一个单词),不使用分隔符。

class SliderMenu { ... }class HttpRequest { ... }typedef Predicate<T> = bool Function(T value);

这里包括使用元数据注解的类。

class Foo {const Foo([Object? arg]);
}@Foo(anArg)
class A { ... }@Foo()
class B { ... }

如果注解类的构造函数是无参函数,则可以使用一个 lowerCamelCase 风格的常量来初始化这个注解。

const foo = Foo();@foo
class C { ... }

 使用 UpperCamelCase 风格类型作为扩展名

Linter rule: camel_case_extensions

与类型命名一样,扩展 的名称也应大写每个单词的首字母(包括第一个单词),并且不使用分隔符。

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

 在package文件夹源文件 中使用 lowercase_with_underscores 方式命名。

Linter rules: file_names, package_names

一些文件系统不区分大小写,所以很多项目要求文件名必须是小写字母。使用分隔符这种形式可以保证命名的可读性。使用下划线作为分隔符可确保名称仍然是有效的Dart标识符,如果语言后续支持符号导入,这将会起到非常大的帮助。

my_package
└─ lib└─ file_system.dart└─ slider_menu.dart
mypackage
└─ lib└─ file-system.dart└─ SliderMenu.dart

如果你 选择命名库,本准则给定了 如何 为库取名。如果需要,可以在文件中 省略 库指令。

</aside>

 用 lowercase_with_underscores 风格命名库和源文件名。

Linter rule: library_prefixes

import 'dart:math' as math;
import 'package:angular_components/angular_components.dart' as angular_components;
import 'package:js/js.dart' as js;
import 'dart:math' as Math;
import 'package:angular_components/angular_components.dart' as angularComponents;
import 'package:js/js.dart' as JS;

 使用 lowerCamelCase 风格来命名其他的标识符。

Linter rule: non_constant_identifier_names

类成员、顶级定义、变量、参数以及命名参数等 除了第一个单词,每个单词首字母都应大写,并且不使用分隔符。

var count = 3;HttpRequest httpRequest;void align(bool clearItems) {// ...
}

推荐 使用 lowerCamelCase 来命名常量。

Linter rule: 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 的枚举类型。

 备注: We initially used Java’s SCREAMING_CAPS style for constants. We changed for a few reasons:

我们一开始使用 Java SCREAMING_CAPS 风格来命名常量。我们之所以不再使用,是因为:

  • SCREAMING_CAPS 很多情况下看起来比较糟糕,尤其类似于 CSS 颜色这类的枚举值。

  • 常量常常被修改为 final 类型的非常量变量,这种情况你还需要修改变量的名字为小写字母形式。

  • 在枚举类型中自动定义的 values 属性为常量并且是小写字母形式的。

把超过两个字母的首字母大写缩略词和缩写词当做一般单词来对待。

首字母大写缩略词比较难阅读,特别是多个缩略词连载一起的时候会引起歧义。例如,一个以 HTTPSFTP 开头的名字,没有办法判断它是指 HTTPS FTP 还是 HTTP SFTP。

为了避免上面的情况,缩略词和缩写词要像普通单词一样首字母大写。

例外情况 两个字母情况下,类似 IO (input/output) 这样的 缩略词 要全大写。另外,两个字母的 缩写词 比如 ID (identification) 与其他常规单词一样,首字母大写即可: Id

class HttpConnection {}
class DBIOPort {}
class TVVcr {}
class MrRogers {}var httpRequest = ...
var uiHandler = ...
var userId = ...
Id id;
class HTTPConnection {}
class DbIoPort {}
class TvVcr {}
class MRRogers {}var hTTPRequest = ...
var uIHandler = ...
var userID = ...
ID iD;

PREFER using ___, etc. for unused callback parameters.

Sometimes the type signature of a callback function requires a parameter, but the callback implementation doesn’t use the parameter. In this case, it’s idiomatic to name the unused parameter _. If the function has multiple unused parameters, use additional underscores to avoid name collisions: _____, etc.

futureOfVoid.then((_) {print('Operation complete.');
});

This guideline is only for functions that are both anonymous and local. These functions are usually used immediately in a context where it’s clear what the unused parameter represents. In contrast, top-level functions and method declarations don’t have that context, so their parameters must be named so that it’s clear what each parameter is for, even if it isn’t used.

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

Dart uses a leading underscore in an identifier to mark members and top-level declarations as private. This trains users to associate a leading underscore with one of those kinds of declarations. They see “_” and think “private”.

There is no concept of “private” for local variables, parameters, local functions, or library prefixes. When one of those has a name that starts with an underscore, it sends a confusing signal to the reader. To avoid that, don’t use leading underscores in those names.

不要使用前缀字母

在编译器无法帮助你了解自己代码的时, 匈牙利命名法 和其他方案出现在了 BCPL ,但是因为 Dart 可以提示你声明的类型,范围,可变性和其他属性,所以没有理由在标识符名称中对这些属性进行编码。

defaultTimeout
kDefaultTimeout

DON’T explicitly name libraries

Appending a name to the library directive is technically possible, but is a legacy feature and discouraged.

Dart generates a unique tag for each library based on its path and filename. Naming libraries overrides this generated URI. Without the URI, it can be harder for tools to find the main library file in question.

library my_library;
/// A really great test library.
@TestOn('browser')
library;

顺序

为了使文件前面部分保持整洁,我们规定了关键字出现顺序的规则。每个“部分”应该使用空行分割。

A single linter rule handles all the ordering guidelines: directives_ordering.

 把 “dart:” 导入语句放到其他导入语句之前。

Linter rule: directives_ordering

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

 把 “package:” 导入语句放到项目相关导入语句之前。

Linter rule: directives_ordering

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

 把导出 (export) 语句作为一个单独的部分放到所有导入语句之后。

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

 按照字母顺序来排序每个部分中的语句。

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

格式化

和其他大部分语言一样, Dart 忽略空格。但是,不会。具有一致的空格风格有助于帮助我们能够用编译器相同的方式理解代码。

 使用 dart format 格式化你的代码。

格式化是一项繁琐的工作,尤其在重构过程中特别耗时。庆幸的是,你不必担心。我们提供了一个名为 dart format 的优秀的自动代码格式化程序,它可以为你完成格式化工作。我们有一些关于它适用的规则的 文档 , Dart 中任何官方的空格处理规则由 dart format 生成

其余格式指南用于 dart format 无法修复的一些规则。

考虑 修改你的代码让格式更友好。

无论你扔给格式化程序什么样代码,它都会尽力去处理,但是格式化程序不会创造奇迹。如果代码里有特别长的标识符,深层嵌套的表达式,混合的不同类型运算符等。格式化输出的代码可能任然很难阅读。

当有这样的情况发生时,那么就需要重新组织或简化你的代码。考虑缩短局部变量名或者将表达式抽取为一个新的局部变量。换句话说,你应该做一些手动格式化并增加代码的可读性的修改。在工作中应该把 dart format 看做一个合作伙伴,在代码的编写和迭代过程中互相协作输出优质的代码。

避免 单行超过 80 个字符。

Linter rule: lines_longer_than_80_chars

可读性研究表明,长行的文字不易阅读,长行文字移动到下一行的开头时,眼睛需要移动更长的距离。这也是为什么报纸和杂志会使用多列样式的文字排版。

如果你真的发现你需要的文字长度超过了 80 个字符,根据我们的经验,你的代码很可能过于冗长,而且有方式可以让它更紧凑。最常见的的一种情况就是使用 VeryLongCamelCaseClassNames (非常长的类名字和变量名字)。当遇到这种情况时,请自问一下:“那个类型名称中的每个单词都会告诉我一些关键的内容或阻止名称冲突吗?”,如果不是,考虑删除它。

注意,dart format 能自动处理 99% 的情况,但是剩下的 1% 需要你自己处理。 dart format 不会把很长的字符串字面量分割为 80 个字符的列,所以这种情况你需要自己手工确保每行不超过 80 个字符。

例外: 当 URI 及文件路径出现在注释或字符串中时(通常在导入和导出语句中),即使文字超出行限制,也可能会保留在一行中。这样可以更轻松地搜索给定路径的源文件。

Exception: Multi-line strings can contain lines longer than 80 characters because newlines are significant inside the string and splitting the lines into shorter ones can alter the program.

 对所有流控制结构使用花括号。

Linter rule: curly_braces_in_flow_control_structures

这样可以避免 dangling else(else悬挂)的问题。

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

这里有一个例外:一个没有 else 的 if 语句,并且这个 if 语句以及它的执行体适合在一行中实现。在这种情况下,如果您愿意,可以不用括号:

if (arg == null) return defaultValue;

但是,如果执行体包含下一行,请使用大括号:

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

http://www.ppmy.cn/news/284434.html

相关文章

如何通过桥接模式重构代码?

文章目录 什么是桥接模式&#xff1f;UML结构图通用代码实现适用场景案例场景分析⽤⼀坨坨代码实现桥接模式重构代码代码实现⽀付类型桥接抽象类⽀付类型的实现定义⽀付模式接⼝测试 总结 同类的业务、同样的功能&#xff0c;怎么就你能写出来那么多if else。 很多时候你写出来…

无线可编程、兼具多功能的鼠标如何选?这里有你需要的答案

说到鼠标和键盘&#xff0c;不管是宅家也好、工作或游戏也好&#xff0c;各种人群都离不开电脑&#xff0c;而鼠标做为其中使用最频繁的数码外设&#xff0c;如果选择不精准&#xff0c;就会给使用带来很闹心的烦恼。 就拿上图这几种先锋使用过的鼠标来说&#xff0c;有超薄的、…

无线鼠标分类

为了节约X201上的USB接口&#xff0c;我在一家小电脑公司购买了雷柏6000蓝牙鼠标&#xff0c;入门级的蓝光蓝牙鼠标&#xff0c;105元成交&#xff0c;比网上贵了20元。送货员送来时&#xff0c;我当时手头边只有X32本本支持蓝牙&#xff0c;结果死活用不上&#xff0c;估计是本…

CSP-S 第一轮笔试重点题

CSP-S提高组笔试题重点题汇总&#xff1a; 今天我给大家分享一些 CSP-S 第一轮笔试中的一些重点题&#xff0c;包含讲解。 第一题&#xff1a; 1.十进制小数13.375对应的二进制数是&#xff08;&#xff09;。 A.1101.011 B.1011.011 C.1101.101 D.1010.01 解析&#x…

cassandra如何进行反规范化设计?

Cassandra 是一个分布式、高可扩展性的 NoSQL 数据库&#xff0c;它采用了反规范化设计以支持快速查询和高吞吐量。反规范化是指在数据模型设计中将重复数据复制到不同的表中&#xff0c;以减少查询时的数据访问和联接操作。 以下是一个示例&#xff0c;说明如何在 Cassandra …

前后端交互四、跨域与JSONP

零、文章目录 前后端交互四、跨域与JSONP 1、同源策略和跨域 &#xff08;1&#xff09;同源 如果两个页面URL的协议&#xff0c;域名和端口都相同&#xff0c;则两个页面具有相同的源。 例如&#xff0c;下表给出了相对于 http://www.test.com/index.html 页面的同源检测&…

安装OpenResty

安装OpenResty 1.安装 首先你的Linux虚拟机必须联网 1&#xff09;安装开发库 首先要安装OpenResty的依赖开发库&#xff0c;执行命令&#xff1a; yum install -y pcre-devel openssl-devel gcc --skip-broken2&#xff09;安装OpenResty仓库 你可以在你的 CentOS 系统中…

Jsonp调用网易云音乐API搜索播放歌曲

Jsonp调用网易云音乐API搜索播放歌曲 效果如下图&#xff1a; 基本就是正常的文件播放&#xff0c;暂停&#xff0c;停止&#xff0c;设置循环&#xff0c;随机播放&#xff0c;加速&#xff0c;减速&#xff0c;上一曲&#xff0c;下一曲&#xff0c;再多个选择本地文件加入到…