API 设计之禅
API 设计之禅
译者按:本文翻译自 How to design a good API and why it matters。根据笔者经历,很多大厂程序员所写的代码和大厂内部封装的各种中间件、类库,毫不客气地说,90%都是没有经过仔细考虑的,经常有各种各样的性能、拓展、可读性、一致性等问题。本文总结深刻,建议反复阅读学习。文章首发公众号,欢迎关注。
在传统的 API 设计方法中,我尝试将讲座的精华提炼成一系列格言,以帮助开发者更好地理解和设计高质量的 API:
- 所有程序员都是 API 设计师。好的程序是模块化的,模块之间的边界定义了 API。好的模块可以被重用。
- API 可以是你最宝贵的资产,也可能是负担。好的 API 可以创造长期的客户,而差的 API 会造成长期的维护噩梦。
- 公共 API,像钻石一样,永恒存在。你只有一次机会来设计它,所以要尽全力做到最好。
- API 应该易于使用且难以滥用。做简单的事情应该容易,做复杂的事情应该可能,做错误的事情应该尽可能困难或不可能。
- API 应该是自文档化的:对于一个好的 API,代码应该很少需要额外的文档说明。事实上,编写好的 API 代码时,通常也不需要太多文档说明。
- 在设计 API 时,首先要收集需求,且保持一定的怀疑态度。人们通常会提供解决方案,但你的任务是发现潜在的问题并寻找最佳的解决方案。
- 以用例的形式构建需求:用例是你衡量 API 的标准。
- API 的早期草稿应该简短,通常是一页纸,列出类和方法的签名以及一行描述。这能方便你在首次设计不完全正确时进行重构。
- 在实现 API 之前,甚至在它完全规范之前,先编写用例代码。这样可以避免实现或设计出根本不合适的 API。
- 随着 API 的演化,维护用例代码。这不仅能避免突然的意外,而且生成的代码将成为 API 的示例、教程和测试的基础。
- 示例代码应该是典范。如果一个 API 被广泛使用,它的示例将成为成千上万程序的原型。任何错误都会以千倍的速度反弹回来。
- 你无法取悦所有人,所以应该尽量让每个人都不满。大多数 API 都会受到过多的约束。
- 预期由于想象力的局限导致的 API 设计错误。你不可能合理地想象出每个人会如何使用一个 API,或者它将如何与系统的其他部分交互。
- API 设计不是孤立的活动。把你的设计展示给尽可能多的人,并认真听取他们的反馈。那些你没能想到的可能对别人来说是显而易见的。
- 避免固定输入大小的限制。它们会限制 API 的实用性,并加速它的过时。
- 如果难以找到合适的名称,就重新开始设计。不要害怕拆分或合并 API,或将其嵌入更通用的设置中。如果名称开始变得合适,你就走在了正确的轨道上。
- 命名非常重要。追求可读性、一致性和对称性。每个 API 都是一个小语言,人们必须学习如何阅读和书写它。如果你设计得当,代码会像散文一样流畅。
- 当不确定时,去除不必要的部分。如果有 API 设计的基本定理,那就是这一条。这适用于功能、类、方法和参数。API 的每个方面都应该尽可能简洁,但不能少于必要的部分。你可以随时添加,但不能删除。
- 最小化概念上的重量比类或方法的数量更重要。
- 保持 API 远离实现细节。它们会让用户困惑,并且限制了演化的灵活性。什么是实现细节并不总是显而易见的:小心过度规范。
- 最小化可变性。不可变对象简单、线程安全并且可以自由共享。
- 文档很重要。无论 API 多么优秀,没有良好的文档,它都不会被广泛使用。文档应该覆盖每个导出的 API 元素:每个类、方法、字段和参数。
- 考虑 API 设计决策的性能后果,但不要为了性能而扭曲 API。幸运的是,好的 API 通常也能够带来高效的实现。
- API 必须与平台和谐共处,所以要遵循常规。几乎总是错误的做法是将一个平台的 API 直接“翻译”到另一个平台。
- 最小化访问权限;不确定时将其设为私有。这简化了 API,并减少了耦合。
- 只有当你能断言子类的每个实例都是真正的父类实例时,才应该使用子类化。暴露的类不应仅仅为了重用实现代码而子类化。
- 设计并文档化继承,或者禁止继承。这个文档形式是自用模式:类中的方法如何互相使用。如果没有这种文档,安全的子类化是不可能的。
- 不要让客户端做任何库本可以做的事。违反这一规则会导致客户端中大量重复的代码,增加了出错的机会和难度。
- 遵循最小惊讶原则。每个方法应该做出它最不让人惊讶的事情,给定它的名称。如果一个方法没有做用户期望的事情,就会引发 bug。
- 快速失败。报告错误的时机越早,造成的损害越小。编译时失败是最佳的。如果必须在运行时失败,尽量早做失败处理。
- 为所有字符串形式的数据提供编程访问。否则,程序员就不得不手动解析字符串,这很痛苦。而且,字符串形式最终会变成事实上的 API。
- 谨慎使用方法重载。如果两个方法的行为有差异,最好给它们不同的名称。
- 为任务选择合适的数据类型。例如,不要使用字符串,如果有更合适的类型。
- 在方法中保持一致的参数顺序。否则,程序员可能会搞错顺序。
- 避免长参数列表,尤其是那些有多个连续相同类型参数的列表。
- 避免返回值要求特殊处理。客户端会忘记编写特殊处理代码,导致 bug。例如,返回零长度的数组或集合,而不是 null。
- 只有在出现异常情况时才抛出异常。否则,客户端会强迫用异常来处理正常的流程,导致程序难以阅读、易出错或性能较差。
- 抛出未检查的异常,除非客户端能合理地从失败中恢复。
- API 设计是一门艺术,而不是科学。追求美感,并相信你的直觉。不要死板地遵循上述启示,但偶尔合理地违反它们。
通过这些设计原则,你将能够更好地理解和设计高质量、易用、可维护的 API,为长远的开发打下坚实的基础。
本文由博客一文多发平台 OpenWrite 发布!
API 设计之禅的更多相关文章
- javascript的api设计原则
前言 本篇博文来自一次公司内部的前端分享,从多个方面讨论了在设计接口时遵循的原则,总共包含了七个大块.系卤煮自己总结的一些经验和教训.本篇博文同时也参考了其他一些文章,相关地址会在后面贴出来.很难做到 ...
- (转载) RESTful API 设计指南
作者: 阮一峰 日期: 2014年5月22日 网络应用程序,分为前端和后端两个部分.当前的发展趋势,就是前端设备层出不穷(手机.平板.桌面电脑.其他专用设备......). 因此,必须有一种统一的机制 ...
- RESTful API 设计指南
转自:http://www.ruanyifeng.com/blog/2014/05/restful_api.html 网络应用程序,分为前端和后端两个部分.当前的发展趋势,就是前端设备层出不穷(手机. ...
- GOTO Berlin: Web API设计原则
在邮件列表和讨论区中有很多与REST和Web API相关的讨论,下面仅是我个人对这些问题的一些见解,并没有绝对的真理,InnoQ的首席顾问Oliver Wolf在GOTO Berlin大会上开始自己的 ...
- RESTful API 设计最佳实践
背景 目前互联网上充斥着大量的关于RESTful API(为了方便,以后API和RESTful API 一个意思)如何设计的文章,然而却没有一个"万能"的设计标准:如何鉴权?API ...
- 我所理解的RESTful Web API [设计篇]
<我所理解的RESTful Web API [Web标准篇]>Web服务已经成为了异质系统之间的互联与集成的主要手段,在过去一段不短的时间里,Web服务几乎清一水地采用SOAP来构建.构建 ...
- 从英文变形规则计算到Restful Api设计
➠更多技术干货请戳:听云博客 一天在研究Restful API设计,命名的时候我总是很纠结,我相信大多数人也有这种感觉,不是说想不出来某个单词怎么写的问题,像我这种没事背单词背到13000词量的人也要 ...
- RESTful API 设计指南 (转)
RESTful API 设计指南 2016-02-23 ImportNew (点击上方公号,可快速关注) 作者:阮一峰 链接:http://www.ruanyifeng.com/blog/2014/0 ...
- 基于资源的权限系统-API设计
概述 权限系统需要和别的系统集成,因此,良好的API是易用性的保证. 这里只设计一些权限相关的核心 API,关于用户,组织,导入导出之类的后续再逐步补充 API 设计 围绕权限有以下 4 类 API: ...
- Atitit. Api 设计 原则 ---归一化
Atitit. Api 设计 原则 ---归一化 1.1. 叫做归一化1 1.2. 归一化的实例:一切对象都可以序列化/toString 通过接口实现1 1.3. 泛文件概念.2 1.4. 游戏行业 ...
随机推荐
- Nuxt.js 应用中的 webpack:configResolved事件钩子
title: Nuxt.js 应用中的 webpack:configResolved事件钩子 date: 2024/11/21 updated: 2024/11/21 author: cmdragon ...
- ADMM——交替方向乘子法
ADMM(Alternating Direction Method of Multipliers,交替方向乘子法)是一种优化算法,主要用于解决分布式.大规模和非光滑的凸优化问题.ADMM通过将原始问题 ...
- golang之循环导包
作为一个 Golang 开发,你可能在项目中遇到过包的循环依赖问题.Golang 不允许循环依赖,如果检测到代码中存在这种情况,在编译时就会抛出异常. 循环依赖 假设我们有两个包:p1和p2.当包p1 ...
- Konva.js
1.前言 简介:Konva.js - 适用于桌面/移动端应用的 HTML5 2d canvas 库 个人体验:原生的canvas只支持绘制基本的直线,矩形,文字,图片,扇形等,如果要支持更复杂的功能, ...
- uniapp 画布
1.前言 uniapp中的canvas与HTML中的canvas用法并不同,他的使用文档请参考微信小程序画布 2.基本使用 1.准备canvas容器,并为其设置canvas-id和宽高(为了兼容H5, ...
- 前端每日一知之让Chrome支持小于12px的文字
脑图在线链接 本文内容依据[js每日一题]公众号精彩文章总结而来
- Flutter 错误The argument type 'Color' can't be assigned to the parameter type 'MaterialStateProperty<Color?>?'.dart(argument_type_not_assignable)
MaterialStateProperty<Color?>?和Color 当为TextButton等button添加颜色时,使用ButtonStyle为其添加颜色 TextButton( ...
- Redis应用—7.大Value处理方案
大纲 1.⽅案设计 2.安装与配置环境 1.⽅案设计 步骤一:首先需要配置一个crontab定时调度shell脚本,然后该脚本每天凌晨会通过rdbtools⼯具解析Redis的RDB⽂件,接着对解析出 ...
- Envoy 官网,中文指南,Envoy 实现 .NET 架构网关
收集一些 Envoy 的资料 Envoy 实现 .NET 架构的网关系列 Envoy实现.NET架构的网关(一)静态配置与文件动态配置 Envoy实现.NET架构的网关(二)基于控制平面的动态配置 E ...
- 中电金信:GienTech动态| 获奖、合作、与伙伴共谋数字化转型…
-- -- GienTech动态 -- -- 中电金信携"源启"亮相第十二届中国电子信息博览会 4月11日,为期三天的"第十二届中国电子信息博览会" ...