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. 游戏行业 ...
随机推荐
- MaskLLM:英伟达出品,用于大模型的可学习`N:M`稀疏化 | NeurIPS'24
来源:晓飞的算法工程笔记 公众号,转载请注明出处 论文: MaskLLM: Learnable Semi-Structured Sparsity for Large Language Models 论 ...
- 零基础入门gRPC:从 0 实现一个Hello World
在之前讲解 Nacos 注册中心的过程中,我曾简要提到过 gRPC,主要是因为 Nacos 的最新版已经采用了 gRPC 作为其核心通信协议.这一变化带来了显著的性能优化,尤其在心跳检测.健康检查等接 ...
- TypeScript名词解释系列:tsconfg中的target,module和moduleResolution
tsconfg中的target,module和moduleResolution target 就是TypeScript文件编译后生成的javascript文件里的语法应该遵循哪个JavaScript的 ...
- 在vue中使用XLSX导出表格
安装依赖 npm install file-saver xlsx -S 然后在需要的页面中引入依赖包 import FileSaver from 'file-saver'; import XLSX f ...
- Abp Vnext Vue Element UI实现
Abp Vnext Vue Element UI实现版本开箱即用的中后台前端/设计解决方案 链接 AbpPro Vben5 Vue Element Plus 预览 点击查看效果 文档地址 点击查看文档 ...
- 人工智能大语言模型起源篇,低秩微调(LoRA)
上一篇: <规模法则(Scaling Law)与参数效率的提高> 序言:您在找工作时会不会经常听到LoRA微调,这项技术的来源就是这里了. (12)Hu.Shen.Wallis.Allen ...
- 【报错解决】使用代理后从Github中clone仓库报错
当电脑使用代理后,会造成Github的clone和push等功能无法正常使用 报错内容:Failed to connect to github.com port 443 after ***** ms: ...
- 简单软件架构的一些好处zz
简单软件架构的一些好处_大数据_Dan Luu_InfoQ精选文章 Wave 是一家价值 17 亿美元的公司,拥有 70 名工程师,该公司的产品是一款加减数字的 CRUD 应用程序.为了与此保持一致, ...
- Ubuntu sudo nopasswd方法
1 运行 visudo 2 假设用户名为yourname, 则在最后一行添加: # User privilege specificationroot ALL=(ALL:ALL) ALL# Member ...
- Java保留两位小数的几种写法总结
转载 本文列举了几个方法: 1. 使用java.math.BigDecimal 2. 使用java.text.DecimalFormat 3. 使用java.text.NumberFormat 4. ...