mcpField
D
dart-api-design

dart-api-design

github.com/dart-lang开发53266 次安装2 周前更新
代码仓库

关于 dart-api-design

面向 Dart 开发者的 API 设计指南,涵盖命名、类型签名、类修饰符、封装和参数选择。它还提供设计清单及使用 `dart analyze` 检查的工作流程。

主要功能

  1. 01命名与 API 规范
  2. 02Dart 3 类修饰符指南
  3. 03封装与相等性规则
  4. 04类型和参数设计
  5. 05API 清单与分析流程

适用场景

  1. 01设计新的 Dart 库 API
  2. 02审查类层次结构和公共成员
  3. 03运行 `dart analyze` 前检查签名

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/dart-lang/skills --skill dart-api-design

安装后在 Claude Code 中输入/dart-api-design确认已加载。

详细介绍

设计有效的 Dart API

目录

命名约定

采用一致且描述性强的命名,以便充分利用已有的领域知识和核心库知识。

  • 属性与变量:
    • 非布尔属性使用名词短语(例如,pageCount、context.lineWidth)。
    • 布尔属性使用非祈使动词短语(例如,isEmpty、canClose)。优先使用“肯定”名称(例如,使用 isConnected 而不是 isNotDisconnected)。
  • 方法与函数:
    • 对副作用较大的操作使用祈使动词短语(例如,list.add()、window.refresh())。
    • 如果返回值是主要目的,则使用名词短语或非祈使动词短语(例如,list.elementAt(3))。
    • 避免以 get 开头命名方法。使用 getter 或描述性动词(例如,downloadData())。
    • 如果方法将状态复制到新对象中,则命名为 to___()(例如,list.toSet())。
    • 如果方法返回由原始对象支持的不同表示形式,则命名为 as___()(例如,table.asMap())。
  • 类型参数:遵循标准助记符:E(元素)、K/V(键/值)、R(返回类型)或 T/S/U(单一类型)。

类修饰符与架构

使用 Dart 3 类修饰符进行可扩展设计并封装实现。应用修饰符来控制外部库的访问。

  • abstract:用于定义需要对其接口进行具体实现的类。无法实例化。
  • base:用于强制继承类的实现。在类自身库之外禁止使用 implements。保证调用基类构造函数。
  • interface:用于定义纯接口。允许使用 implements,但在该库之外禁止使用 extends。可减少脆弱基类问题。
  • final:用于封闭类型层级。在该库之外同时禁止使用 extends 和 implements。保证 API 可安全地渐进式修改。
  • sealed:用于创建已知且可枚举的子类型集合。支持针对子类型编写穷尽式 switch 语句。隐式为抽象类。

注意:可根据需要组合使用修饰符(例如,使用 abstract interface class 表示纯接口)。

成员与封装

  • 封装:避免使用公共字段;使用 getter 和 setter 来封装并控制状态的访问与修改。
  • Getter:对于概念上访问属性的操作,使用 getter。该操作不得接受参数、必须返回结果、不得产生用户可见的副作用,并且必须是幂等的。
  • Setter:对于概念上更改属性的操作,使用 setter。该操作必须接受一个参数、改变状态,并且必须是幂等的。
    • 不要定义没有对应 getter 的 setter。
    • 不要为 setter 指定返回类型(它们本身返回 void)。
  • 方法级联:避免仅为实现流畅接口而让方法返回 this。改用 Dart 的级联运算符(..)。
  • 相等性:
    • 如果重写了 ==,就要重写 hashCode。
    • 避免为可变类定义自定义相等性。
    • 不要让 == 的参数可为 null(语言会自动处理 null 检查)。

类型与签名

  • 类型别名:DO 使用类型别名(typedef)简化复杂的函数签名。使用现代语法:typedef Comparison<T> = int Function(T a, T b);。
  • 内联函数:对于简单的一次性回调,PREFER 使用内联函数类型,而不是 typedef(例如,void Function(Event) callback)。
  • 类型注解:
    • DO 为未初始化的变量添加类型注解。
    • DO 为非局部函数声明的返回值和参数添加类型注解。
    • DON'T 为已初始化的局部变量或可推断的闭包参数冗余添加类型注解。
  • 泛型:使用完整的泛型类型。AVOID 使用不完整的泛型类型(例如,使用 Completer<Map<String, int>>(),而不是 Completer<Map>())。
  • Dynamic 与 Object:AVOID 使用 dynamic,除非你明确希望禁用静态检查。使用 Object? 安全地接受任意值。
  • 异步返回值:对于不产生值的异步成员,DO 使用 Future<void> 作为返回类型。AVOID 将 FutureOr<T> 用作返回类型(它会迫使调用方检查类型)。

参数

  • 命名参数:对于参数超过两个的函数,PREFER 使用命名参数,以提高调用处的可读性。
  • 布尔参数:AVOID 使用位置布尔参数。改用命名参数。
    • CONSIDER 在命名布尔参数中省略 is/can/has 前缀(例如,使用 Isolate.spawn(..., paused: true),而不是 isPaused: true)。
  • 可选位置参数:如果用户可能想省略前面的参数,AVOID 使用可选位置参数。改用命名参数。
  • 范围:DO 使用包含在内的 start 参数和不包含在内的 end 参数来接受范围(例如,substring(1, 3))。

工作流

任务进度:API 设计与实现

复制此清单,以便在设计新的 Dart 类或库 API 时跟踪进度。

  • 定义类修饰符:
    • 如果要定义不带实现的契约 -> abstract interface class。
    • 如果要提供必须由子类继承的实现 -> base class。
    • 如果要封闭类层次结构,禁止外部扩展或实现 -> final class。
    • 如果要定义可枚举的状态集合,以便进行穷尽式切换 -> sealed class。
  • 封装状态:
    • 将内部字段设为私有(_fieldName)。
    • 通过 getter 暴露状态。
    • 通过 setter 暴露修改操作(确保存在对应的 getter)。
  • 完善签名:
    • 如果位置参数超过 2 个,将其转换为命名参数。
    • 将位置布尔参数转换为命名布尔参数(去掉 is/can/has 前缀)。
    • 将复杂的函数参数提取为 typedef 别名。
  • 验证类型:
    • 确保公共签名中不存在隐式的 dynamic 类型。
    • 将 FutureOr<T> 返回类型替换为 Future<T>。
    • 确保异步 void 方法返回 Future<void>。
  • 运行验证器 -> 检查错误 -> 修复:
    • 运行 dart analyze,检查缺失的注解、未处理的 sealed class switch 分支以及 linter 违规项。在最终确定 API 之前修复所有警告。

评论

支持 Markdown