星语课程网
Google API设计指南-命名约定
来源:本站编辑
2023-07-08 19:23
85
> 翻译自 [API Design Guide - Naming Conventions](https://link.segmentfault.com/?enc=RPlLg%2Btl4Vgzr3RUwQqHIw%3D%3D.R7jCbtj3hL%2BlE%2B3R%2BZyKQ23W8%2FZfyF04r1J3dUFB5I7EUYLbsTWgRw%2Fh7OYFJmwmqJwK3wXWtxHhI%2Fyzd6RVtQ%3D%3D) 为了在长期和大量使用的 API 中提供统一的开发体验,API 中的所有名字 **应该(should)** : * 简单 * 直观 * 一致 此文章讨论了接口、资源、集合、方法和消息的名字。 因为很多开发者的母语并不是英语,这些命名约定通过鼓励使用简单、统一的短词汇来命名方法和资源来保证大部分开发者能够容易理解 API。 * API 中的名字 **应该(should)** 使用美式英语,例如:license(不是 licence),color(不是 colour)。 * 使用常用的简短形式或缩写,例如: API 比 Application Programming Interface 更好。 * 尽量使用直接、熟悉的术语,例如:描述对资源的删除(销毁)时,delete 比 erase 更好。 * 对相同的概念使用相同的名字或术语,包括在 API 中共享的概念。 * 避免名字重用,对不同的概念要使用不同名字。 * 避免使用在 API 上下文中会造成混乱的过于通用的名字,它们会导致对 API 概念的误解。应该选择能够精确描述概念的名字。这对于定义一阶 API 元素的名称尤其重要。因为名字与上下文相关,所以并没有明确的名字黑名单。Instance, info 和 service 是会产生问题的名字。应该选择能够明确表达出 API 概念(例:instance 表示什么的实例?)并且容易与其他相关概念有区分(例:alert 的意思是规则,信号还是通知?)的名字。 * 谨慎使用会与常用编程语言中的关键字有冲突的名字。 产品名 --- 产品名是指 API 的产品营销名称,例如 _Google Calendar API_。在 API、UI、文档、服务条款、结账单和商业合同中使用的产品名称 **应该(should)** 一致。 Google API **必须(must)** 使用 _Google_ 作为产品名的前缀,除非它们像 _Gmail_, _Nest_, _Youtube_ 这种有不同的品牌。一般来说产品名 **应该(should)** 由产品和市场部门决定。 下表列出了所有相关 API 名称及其一致性的示例,有关各自名称及其约定的更多详细信息,请继续往下看。 | API 名 | 示例 | | - | - | | 产品名 | Google Calendar API | | 服务名 | calendar.googleapis.com | | 包名 | google.calendar.v3 | | 接口名 | google.calendar.v3.CalendarService | | 资源目录 | //google/calendar/v3 | | API 名 | calendar | 服务名 --- 服务名 **应该(should)** 是一个能够被解析为一个或多个网络地址的合法 [DNS 名字](https://link.segmentfault.com/?enc=JEIsNgRXeWmcfqjKagA6jA%3D%3D.RLIRYlwiLwvGx33dwoI3zpPCByxITdImQOmkvZrUMcSD5AYhaxnVcqveTM7dogqX)。公有 Google API 的服务名遵循如下模式:`xxx.googleapis.com`。例如:谷歌日历的服务名是 `calendar.googleapis.com`。 如果一个 API 由多个服务组成,它们 **应该(should)** 以能够提高可发现性的方法命名。一种方法是为这些服务名使用相同的前缀。例如服务 `build.googleapis.com` 和 `buildresults.googleapis.com` 都是 Google Build API 的一部分。 包名 -- 在 .proto 文件中定义的包名 **应该(should)** 与产品名和服务名相同。有版本号的包名 **必须(must)** 以版本号结尾。例如: // Google Calendar API package google.calendar.v3; 不与服务直接关联的抽象 API,例如 Google Watcher API **应该(should)** 使用与产品名相同的 proto 包名: // Google Watcher API package google.watcher.v1; 在 .proto 文件中指定的 Java 包名 **必须(must)** 符合标准 Java 包名的前缀(`com.`, `edu.`, `net.` 等)。例如: package google.calendar.v3; // 指定 Java 包的名字,使用标准前缀 "com." option java\_package \= "com.google.calendar.v3"; 集合 ID ----- [集合 ID](https://link.segmentfault.com/?enc=Bqt2KutpSmeGb7oi2qGUYw%3D%3D.C1I1MFpQFV6muJ1DRpYs3BZPp3qZQmSHULFKN021OtW6pwvZh%2B6ysuRAuDUMgVcGQeU70m5QWg3ygnVGih9y1P3ss%2BQ4v9Yhe9PqvpljU3U%3D) **应该(should)** 使用美式英语的、复数形式的、首字母小写的驼峰命名法,例如:`events`, `children` 或 `deletedEvents`。 接口名 --- 为了避免和形如 `pubsub.googleapis.com` 的[资源名](https://link.segmentfault.com/?enc=XwdJfI93saN5lCjYUIke%2Fw%3D%3D.eeFHU%2FU%2FHOGasmXB3MJzTzI8lQ0yzKIAGP8vMul%2Fn0zxmU5cpHnDSA8I7%2FEB4rUVEYRFmpxdo%2FCuoTPttBHdAYTl2V00HM0nitrbL%2FWiHfEEtkKoIf1kVsZ9gu6QZpmu)混淆,术语 _接口名_ 指的是在 .proto 文件中定义 `service` 时使用的名字: // Library is the interface name. service Library { rpc ListBooks(...) returns (...); rpc ... } 你可以认为 _服务名_ 是指一组 API 的具体实现,_接口名_ 是指一个 API 的抽象定义。 接口名称 **应该(should)** 使用直观的名词,如 Calendar 或 Blob。**不应该(should not)** 与编程语言中已有的任何概念或运行时库冲突(如:File)。 当 _接口名_ 与 API 中其他名字冲突时,应该为其加上前缀(如 `Api` 或 `Service`)来进行区分。 方法名 --- 在其 IDL 规范中,服务 **可以(may)** 定义与集合和资源上的方法相对应的一个或多个RPC方法。方法名 **应该(should)** 遵循像 `VerbNoun` 这样首字母大写的驼峰命名法的命名约定,其中名词(Noun)通常是资源类型。 | 动词(Verb) | 名词(Noun) | 方法名 | 请求信息 | 响应信息 | | -| -| - | - | - | | List | Book | ListBooks | ListBooksRequest | ListBooksResponse | | Get | Book | GetBook | GetBookRequest | Book | | Create | Book | CreateBook | CreateBookRequest | Book | | Update | Book | UpdateBook | UpdateBookRequest | Book | | Rename | Book | RenameBook | RenameBookRequest | RenameBookResponse | | Delete | Book | DeleteBook | DeleteBookRequest | google.protobuf.Empty | 消息名 --- RPC 方法的请求与响应消息 **应该(should)** 以方法名分别加上 `Request` 和 `Response` 的方式命名。除非方法的请求或响应类型如下: * 空消息(使用 `google.protobuf.Empty`) * 资源类型 * 代表一种操作的资源 枚举名 --- 枚举类型的名字 **必须(must)** 使用首字母大写的驼峰命名法。 枚举值 **必须(must)** 以下划线分隔且字母全部大写的方式来命名(例如:CAPITALIZED\_NAMES\_WITH\_UNDERSCORES)。每个枚举值 **必须(must)** 以分号而不是逗号结尾。第一个值 **应该(should)** 命名为 ENUM\_TYPE\_UNSPECIFIED,用于当没有明确指定枚举值时返回。 enum FooBar { // 第一个表示默认值,并且一定等于 0 FOO\_BAR\_UNSPECIFIED \= 0; FIRST\_VALUE \= 1; SECOND\_VALUE \= 2; } 字段名 --- 在 .proto 文件中定义的字段名 **必须(must)** 以下划线分隔且字母全部小写的方式来命名(例如:lower\_case\_underscore\_separated\_names)。这些名字会遵守各编程语言的命名约定来映射到生成的代码中。 ### 重复字段名(Repeated field) API 中的重复字段 **必须(must)** 使用合适的复数形式。这符合现有 Google API 的惯例以及外部开发人员的通常期望。 ### 时间和间隔 **应该(should)** 使用 `google.protobuf.Timestamp`并且字段名 **应该(should)** 以 `time` 结尾来表示独立于任一时区的时间点。例如 `start_time`, `end_time`。 如果表示一个活动的时间,字段名 **应该(should)** 使用 `verb_time` 格式,如 `create_time`, `update_time`。避免使用动词的过去时形式,如 `created_time` 或 `last_updated_time`。 **应该(should)** 使用 `google.protobuf.Duration` 来表示一个时间段。 message FlightRecord { google.protobuf.Timestamp takeoff\_time \= 1; google.protobuf.Duration flight\_duration \= 2; } 如果因为遗留系统或兼容原因要使用整形来表示时间相关的字段(包含墙上时间、时间段、延迟),字段名 **必须(must)** 有如下形式: xxx\_{time|duration|delay|latency}\_{seconds|millis|micros|nanos} message Email { int64 send\_time\_millis \= 1; int64 receive\_time\_millis \= 2; } 如果因为遗留系统或兼容原因要使用字符串来表示时间戳,字段名 **不应该(should not)** 包含任何单位后缀。**应该(should)** 使用形如 `2014-07-30T10:43:17Z` 的 RFC 3339 格式。 ### 日期与时间 **应该(should)** 使用 `google.type.Date` 并且字段名以 `_date` 结尾来表示独立于时区与时间的日期。如果必须以字符串表示,应该使用形如 YYYY-MM-DD 的 ISO 8601 日期格式(例如 2014-07-30)。 **应该(should)** 使用 `google.type.TimeOfDay` 并且字段名以 `_time` 结尾来表示独立于时区与日期的时间。如果必须以字符串表示,应该使用形如 HH:MM:SS\[.FFF\] 的 ISO 8601 的 24 小时时间格式(例如 14:55:01.672)。 message StoreOpening { google.type.Date opening\_date \= 1; google.type.TimeOfDay opening\_time \= 2; } ### 数量 以整形表示的数量 **必须(must)** 包含单位。 xxx\_{bytes|width\_pixels|meters} 如果表示物品的数量,字段名 **应该(should)** 使用 `_count` 做为后缀,如 `node_count`。 ### List 过滤字段 如果 `List` 方法支持过滤资源,包含过滤表达式的字段 **应该(should)** 命名为 `filter`。例: message ListBooksRequest { // 父资源名 string parent = 1; // 过滤表达式 string filter = 2; } ### List 响应 `List` 方法的响应消息中包含资源列表的字段名字 **必须(must)** 是资源名的复数形式。例如,方法 `CalendarApi.ListEvents()` **必须(must)** 定义响应消息 `ListEventsResponse`,此消息中包含名为 `events` 的重复字段来用于返回资源列表。 service CalendarApi { rpc ListEvents(ListEventsRequest) returns (ListEventsResponse) { option (google.api.http) = { get: "/v3/{parent=calendars/\*}/events"; }; } } message ListEventsRequest { string parent = 1; int32 page\_size = 2; string page\_token = 3; } message ListEventsResponse { repeated Event events = 1; string next\_page\_token = 2; } 驼峰命名法 ----- 除了字段名和枚举值,在 .proto 文件中的所有定义 **必须(must)** 使用首字母大写的[驼峰命名法](https://link.segmentfault.com/?enc=GXrXxQiNdCjNXKfT6Na6zQ%3D%3D.Lq5UJtO9MMVoWy8TrIFW3zYphyf9hwONsQM5OiIJerI04%2FZ%2F8UkKO3urL5EFjHDEpJV2wYBFETeDuKyUs8NjnPllGUKbi6l40mfuB%2FyG5f0%3D)。 名字缩写 ---- 对于像 `config` 和 `spec` 这种被软件工程师熟知的缩写,在 API 定义中 **应该(should)** 使用缩写而不是其完整形式,这会使代码便于读写。在正式的文档中 **应该(should)** 使用其完整形式。例如: * config (configuration) * id (identifier) * spec (specification) * stats (statistics) [查看其他章节](https://link.segmentfault.com/?enc=5ZO7Yu7A6bWAW8V1wx3SqA%3D%3D.Nr7pJ%2FT9PxVeqTwDtCBAOZmV1WZfx0NYy%2BKyFubN9pCSIS1UrzCOfokbhY%2BH%2Fh3wNy7%2FEAelS8iZ0jgmPN%2BsFw%3D%3D)
点赞
热门评论
最新评论
匿名用户
+1
-1
·
回复TA
暂无热门评论
相关推荐
阅读更多资讯
热门评论 最新评论
暂无热门评论