关于 swift-api-design-guidelines
用于在 Swift API 中应用 Swift API Design Guidelines 的参考技能,涵盖命名、参数标签、文档和调用处可读性。面向设计或审查 Swift API 的开发者,并归纳副作用、变异方法配对和流畅调用的约定。
主要功能
- 01参数标签约定
- 02副作用与变异命名
- 03文档注释规则
- 04按角色命名与清晰度
- 05协议及大小写约定
适用场景
- 01审查公开 Swift API
- 02为方法参数选择标签
- 03记录声明与复杂度
- 04规范变异与非变异命名
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ dpearson2699/ swift-ios-skills --skill swift-api-design-guidelines安装后在 Claude Code 中输入/swift-api-design-guidelines确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
evals/evals.jsonreferences/argument-labels-and-parameters.mdconventions-and-special-rules.mdnaming-and-clarity.mdside-effects-and-mutating-pairs.md详细介绍
Swift API 设计指南
将 Swift API 设计指南应用于命名、标签、文档和调用点清晰度。对于混合请求,在此处理 API 设计部分,并将语言/类型系统相关工作转交给 swift-language,将并发相关工作转交给 swift-concurrency,将 lint 配置转交给 swiftlint。
目录
参数标签规则
参数标签决定调用点的可读性。应用第一个符合的行:
| 情况 | 规则 | 示例 |
|---|---|---|
| 第一个参数补全语法短语 | 省略标签,将词语合并到基本名称中 | addSubview(y) |
| 保留值的初始化转换 | 省略第一个标签 | Int64(someUInt32) |
| 参数是无法区分的同类项 | 省略所有标签 | min(x, y) |
| 第一个参数补全介词短语 | 使用介词作为标签 | fade(from: red) |
| 前两个参数构成单一抽象 | 将介词并入基本名称 | moveTo(x: b, y: c) |
| 其他情况 | 添加标签 | split(maxSplits: 2) |
在需要确定抽象边界、多个介词、转换初始化器、无法区分的同类项、参数命名或默认参数时,加载参数标签与参数。
副作用命名
对具有副作用的操作使用祈使动词,对没有副作用的操作使用描述结果的名词或形容词短语,对布尔 API 使用断言式名称。
array.sort()
array.append(newElement)
let d = point.distance(to: origin)
line.isEmpty
set.contains(element)
在审查扩展的纯操作/可变操作示例或布尔命名时,加载副作用与可变配对。
可变与不可变配对
根据操作的自然描述,为可变/不可变配对命名:
- 对动词操作,可变操作使用祈使形式,副本使用描述结果的分词形式:
sort()/sorted()或append(_:)/appending(_:)。优先使用-ed;仅当-ed不符合语法,或描述的是直接宾语而非返回结果时,才使用-ing。 - 对名词操作,副本使用名词,可变操作使用
form+ 名词:union(_:)/formUnion(_:)。 - 为创建新值的工厂添加
make前缀。
当返回结果的语法不明确时,加载-ed/-ing 决策树。同一参考资料还包含扩展的 form 前缀、布尔值和工厂模式。
文档注释
每个公开声明都必须有文档注释。
按声明种类划分的摘要规则
| 声明 | 摘要描述 |
|---|---|
| 函数/方法 | 它的作用及其返回内容 |
| 下标 | 它访问的内容 |
| 初始化器 | 它创建的内容 |
| 类型/属性/变量 | 它是什么 |
将摘要写成一个句子片段:动作以动词开头,实体以名词短语开头,并以句点结尾。
/// Returns the element at the specified index.
func element(at index: Int) -> Element { ... }
/// The number of elements in the collection.
var count: Int { ... }
/// Creates a new array with the given elements.
init(_ elements: some Sequence<Element>) { ... }
/// Accesses the element at the specified position.
subscript(index: Int) -> Element { ... }
符号标记
在相关情况下,于摘要后使用标准符号标记:
- Parameter name:用于单个参数- Parameters:块用于多个参数- Returns:用于返回值- Throws:用于抛出的错误- Complexity:用于算法复杂度
/// Removes and returns the element at the specified position.
///
/// - Parameter index: The position of the element to remove.
/// - Returns: The removed element.
/// - Complexity: O(*n*), where *n* is the length of the collection.
mutating func remove(at index: Int) -> Element { ... }
O(1) 复杂度规则
对于任何复杂度不是 O(1) 的计算属性,都要注明其复杂度。调用方默认属性的复杂度为 O(1)。如果属性执行的工作不止常量时间,就要明确说明其复杂度。
/// The total weight of all items.
///
/// - Complexity: O(*n*), where *n* is the number of items.
var totalWeight: Double {
items.reduce(0) { $0 + $1.weight }
}
有关文档编写模式和示例,请参阅 references/conventions-and-special-rules.md。
清晰度与命名
使用时的清晰度是最重要的目标。每项设计决策都应服务于阅读调用点的人。
清晰优先于简洁。 如果较长的名称能消除歧义,就可以使用较长的名称。不要缩写。
// GOOD
employees.remove(at: position)
// BAD — ambiguous: remove the element? remove at position?
employees.remove(position)
保留避免歧义所需的词语。 如果省略某个词会让调用点变得不清晰,就保留它。
// GOOD — "at" clarifies the argument's role
friends.remove(at: index)
// BAD — is "index" the element to remove or the position?
friends.remove(index)
省略不必要的词语。 不要重复上下文中已有的类型信息。
// GOOD
allViews.remove(cancelButton)
// BAD — "Element" repeats the type
allViews.removeElement(cancelButton)
按角色而非类型命名变量和参数。 使用实体在当前上下文中的角色,而不是其类型名称。
// GOOD — describes the role
var greeting: String
func add(_ observer: NSObject, for keyPath: String)
// BAD — names the type
var string: String
func add(_ object: NSObject, for string: String)
弥补类型信息不足。 当参数类型为 Any、AnyObject 或 Int、String 之类的基本类型时,在名称中添加能明确其角色的词语。
// GOOD — role is clear despite weak types
func addObserver(_ observer: NSObject, forKeyPath path: String)
// BAD — what does "string" mean here?
func add(_ object: NSObject, for string: String)
有关更多命名示例和模式,请参阅 references/naming-and-clarity.md。
流畅用法与协议
调用点读起来应符合语法。 优先选择能让调用点构成合乎语法的短语的名称。
// GOOD — reads fluently
x.insert(y, at: z) // "x, insert y at z"
x.subviews.remove(at: i) // "x's subviews, remove at i"
x.makeIterator() // "x, make iterator"
// BAD — ungrammatical
x.insert(y, position: z)
x.subviews.remove(i)
初始化器的第一个参数。 初始化器的第一个参数不应与类型名称连起来构成短语。
// GOOD
let foreground = Color(red: 32, green: 64, blue: 128)
// BAD — "Color with red" reads awkwardly
let foreground = Color(havingRGBValuesRed: 32, green: 64, blue: 128)
协议命名约定:
| 协议描述的内容 | 命名模式 | 示例 |
|---|---|---|
| 某物是什么 | 名词 | Collection、IteratorProtocol |
| 一种能力 | 使用 -able、-ible 或 -ing 后缀 | Equatable、Hashable、Sendable |
一般约定
大小写。 类型和协议使用 UpperCamelCase。其他所有内容使用 lowerCamelCase。在美式英语中通常全大写的首字母缩略词,应根据其位置统一使用全大写或全小写。
var utf8Bytes: [UTF8.CodeUnit]
var isRepresentableAsASCII = true
var userSMTPServer: SMTPServer
优先使用方法和属性,而非自由函数。 优先使用方法和属性。仅在以下情况下使用自由函数:
- 没有明显的
self—min(x, y) - 函数是无约束的泛型 —
print(value) - 函数语法是已确立的领域记法 —
sin(x)
优先使用默认参数,而非方法族。 优先使用一个带默认参数的方法,而不是一组仅在接受哪些参数上有所不同的方法。将带默认值的参数放在末尾。带默认值的参数应始终带有参数标签 — 带默认值的参数通常会在调用点省略,因此在出现时,其标签必须清晰明确。
// GOOD — labeled with defaults
func decode(_ data: Data, encoding: String.Encoding = .utf8) -> String?
// BAD — method family
func decode(_ data: Data) -> String?
func decode(_ data: Data, encoding: String.Encoding) -> String?
重载安全性。 方法可以共用基名称,前提是它们适用于不同的类型领域,或者其含义能从上下文中明确看出。避免仅按返回类型区分、导致调用点出现歧义的重载。
有关大小写的特殊情况、重载模式以及元组/闭包命名,请参阅 references/conventions-and-special-rules.md。
常见错误
| 错误 | 修正 |
|---|---|
| 标签含糊不清或缺失 | 让调用符合语法,例如 remove(at:)。 |
| 可变/不可变形式使用不当 | 对修改操作使用祈使动词;对副本使用符合语法的 -ed/-ing 形式或名词形式。 |
| 名称描述类型或实现方式 | 按角色和语义效果命名。 |
| 公共 API 缺少用途或复杂度文档 | 添加简明摘要,并记录复杂度不是 O(1) 的属性。 |
错误使用 form 或工厂前缀 | 将 form 保留给名词操作;工厂使用 make。 |
| 重复类型信息 | 删除声明和上下文中已明确的词语。 |
| 重载仅在返回类型上有所不同 | 添加语义名称或参数差异。 |
| 元组或闭包组件仅按位置区分 | 为公共组件和闭包参数添加标签。 |
审查清单
参数标签
- 第一个参数遵循正确的标签规则(语法短语、介词短语、转换或带标签)
- 介词标签不会错误地将独立参数归为一组
- 保留值的转换初始化器省略第一个标签
- 所有非特殊情况的参数都有标签
命名语义
- 可变更方法使用祈使动词形式
- 不可变更方法使用 -ed/-ing 形式或名词形式
- 可变更/不可变更方法对遵循正确模式(动词对或名词/形式名词对)
- 布尔属性读起来像断言(
isEmpty、isValid、contains) - 变量和参数按角色命名,而非按类型命名
文档
- 每个公开声明都有文档注释
- 摘要是以句号结尾的单句片段
- 摘要根据声明类型描述正确的内容(操作、访问、创建、实体)
- 非 O(1) 的计算属性注明其复杂度
- 参数、返回值和抛出的错误均使用符号标记进行说明
约定
- 类型和协议使用大驼峰命名法;其他内容均使用小驼峰命名法
- 根据位置统一缩略词的大小写
- 优先使用默认参数,而非方法族
- 重载不能仅在返回类型上有所不同
- 协议名称遵循名词(is-a)或后缀(能力)约定
参考资料
- 命名清晰度、基于角色的命名、弱类型补偿和术语:references/naming-and-clarity.md
- 参数标签的边缘情况、参数命名和默认参数策略:references/argument-labels-and-parameters.md
- 副作用命名示例、-ed/-ing 决策树、form- 前缀模式和工厂方法:references/side-effects-and-mutating-pairs.md
- 大小写边缘情况、复杂度文档、重载安全性、元组/闭包命名和自由函数例外:references/conventions-and-special-rules.md