API 设计之禅

译者按:本文翻译自 How to design a good API and why it matters。根据笔者经历,很多大厂程序员所写的代码和大厂内部封装的各种中间件、类库,毫不客气地说,90%都是没有经过仔细考虑的,经常有各种各样的性能、拓展、可读性、一致性等问题。本文总结深刻,建议反复阅读学习。文章首发公众号,欢迎关注。

在传统的 API 设计方法中,我尝试将讲座的精华提炼成一系列格言,以帮助开发者更好地理解和设计高质量的 API:

  1. 所有程序员都是 API 设计师。好的程序是模块化的,模块之间的边界定义了 API。好的模块可以被重用。
  2. API 可以是你最宝贵的资产,也可能是负担。好的 API 可以创造长期的客户,而差的 API 会造成长期的维护噩梦。
  3. 公共 API,像钻石一样,永恒存在。你只有一次机会来设计它,所以要尽全力做到最好。
  4. API 应该易于使用且难以滥用。做简单的事情应该容易,做复杂的事情应该可能,做错误的事情应该尽可能困难或不可能。
  5. API 应该是自文档化的:对于一个好的 API,代码应该很少需要额外的文档说明。事实上,编写好的 API 代码时,通常也不需要太多文档说明。
  6. 在设计 API 时,首先要收集需求,且保持一定的怀疑态度。人们通常会提供解决方案,但你的任务是发现潜在的问题并寻找最佳的解决方案。
  7. 以用例的形式构建需求:用例是你衡量 API 的标准。
  8. API 的早期草稿应该简短,通常是一页纸,列出类和方法的签名以及一行描述。这能方便你在首次设计不完全正确时进行重构。
  9. 在实现 API 之前,甚至在它完全规范之前,先编写用例代码。这样可以避免实现或设计出根本不合适的 API。
  10. 随着 API 的演化,维护用例代码。这不仅能避免突然的意外,而且生成的代码将成为 API 的示例、教程和测试的基础。
  11. 示例代码应该是典范。如果一个 API 被广泛使用,它的示例将成为成千上万程序的原型。任何错误都会以千倍的速度反弹回来。
  12. 你无法取悦所有人,所以应该尽量让每个人都不满。大多数 API 都会受到过多的约束。
  13. 预期由于想象力的局限导致的 API 设计错误。你不可能合理地想象出每个人会如何使用一个 API,或者它将如何与系统的其他部分交互。
  14. API 设计不是孤立的活动。把你的设计展示给尽可能多的人,并认真听取他们的反馈。那些你没能想到的可能对别人来说是显而易见的。
  15. 避免固定输入大小的限制。它们会限制 API 的实用性,并加速它的过时。
  16. 如果难以找到合适的名称,就重新开始设计。不要害怕拆分或合并 API,或将其嵌入更通用的设置中。如果名称开始变得合适,你就走在了正确的轨道上。
  17. 命名非常重要。追求可读性、一致性和对称性。每个 API 都是一个小语言,人们必须学习如何阅读和书写它。如果你设计得当,代码会像散文一样流畅。
  18. 当不确定时,去除不必要的部分。如果有 API 设计的基本定理,那就是这一条。这适用于功能、类、方法和参数。API 的每个方面都应该尽可能简洁,但不能少于必要的部分。你可以随时添加,但不能删除。
  19. 最小化概念上的重量比类或方法的数量更重要
  20. 保持 API 远离实现细节。它们会让用户困惑,并且限制了演化的灵活性。什么是实现细节并不总是显而易见的:小心过度规范。
  21. 最小化可变性。不可变对象简单、线程安全并且可以自由共享。
  22. 文档很重要。无论 API 多么优秀,没有良好的文档,它都不会被广泛使用。文档应该覆盖每个导出的 API 元素:每个类、方法、字段和参数。
  23. 考虑 API 设计决策的性能后果,但不要为了性能而扭曲 API。幸运的是,好的 API 通常也能够带来高效的实现。
  24. API 必须与平台和谐共处,所以要遵循常规。几乎总是错误的做法是将一个平台的 API 直接“翻译”到另一个平台。
  25. 最小化访问权限;不确定时将其设为私有。这简化了 API,并减少了耦合。
  26. 只有当你能断言子类的每个实例都是真正的父类实例时,才应该使用子类化。暴露的类不应仅仅为了重用实现代码而子类化。
  27. 设计并文档化继承,或者禁止继承。这个文档形式是自用模式:类中的方法如何互相使用。如果没有这种文档,安全的子类化是不可能的。
  28. 不要让客户端做任何库本可以做的事。违反这一规则会导致客户端中大量重复的代码,增加了出错的机会和难度。
  29. 遵循最小惊讶原则。每个方法应该做出它最不让人惊讶的事情,给定它的名称。如果一个方法没有做用户期望的事情,就会引发 bug。
  30. 快速失败。报告错误的时机越早,造成的损害越小。编译时失败是最佳的。如果必须在运行时失败,尽量早做失败处理。
  31. 为所有字符串形式的数据提供编程访问。否则,程序员就不得不手动解析字符串,这很痛苦。而且,字符串形式最终会变成事实上的 API。
  32. 谨慎使用方法重载。如果两个方法的行为有差异,最好给它们不同的名称。
  33. 为任务选择合适的数据类型。例如,不要使用字符串,如果有更合适的类型。
  34. 在方法中保持一致的参数顺序。否则,程序员可能会搞错顺序。
  35. 避免长参数列表,尤其是那些有多个连续相同类型参数的列表
  36. 避免返回值要求特殊处理。客户端会忘记编写特殊处理代码,导致 bug。例如,返回零长度的数组或集合,而不是 null。
  37. 只有在出现异常情况时才抛出异常。否则,客户端会强迫用异常来处理正常的流程,导致程序难以阅读、易出错或性能较差。
  38. 抛出未检查的异常,除非客户端能合理地从失败中恢复
  39. API 设计是一门艺术,而不是科学。追求美感,并相信你的直觉。不要死板地遵循上述启示,但偶尔合理地违反它们。

通过这些设计原则,你将能够更好地理解和设计高质量、易用、可维护的 API,为长远的开发打下坚实的基础。

本文由博客一文多发平台 OpenWrite 发布!

API 设计之禅的更多相关文章

  1. javascript的api设计原则

    前言 本篇博文来自一次公司内部的前端分享,从多个方面讨论了在设计接口时遵循的原则,总共包含了七个大块.系卤煮自己总结的一些经验和教训.本篇博文同时也参考了其他一些文章,相关地址会在后面贴出来.很难做到 ...

  2. (转载) RESTful API 设计指南

    作者: 阮一峰 日期: 2014年5月22日 网络应用程序,分为前端和后端两个部分.当前的发展趋势,就是前端设备层出不穷(手机.平板.桌面电脑.其他专用设备......). 因此,必须有一种统一的机制 ...

  3. RESTful API 设计指南

    转自:http://www.ruanyifeng.com/blog/2014/05/restful_api.html 网络应用程序,分为前端和后端两个部分.当前的发展趋势,就是前端设备层出不穷(手机. ...

  4. GOTO Berlin: Web API设计原则

    在邮件列表和讨论区中有很多与REST和Web API相关的讨论,下面仅是我个人对这些问题的一些见解,并没有绝对的真理,InnoQ的首席顾问Oliver Wolf在GOTO Berlin大会上开始自己的 ...

  5. RESTful API 设计最佳实践

    背景 目前互联网上充斥着大量的关于RESTful API(为了方便,以后API和RESTful API 一个意思)如何设计的文章,然而却没有一个"万能"的设计标准:如何鉴权?API ...

  6. 我所理解的RESTful Web API [设计篇]

    <我所理解的RESTful Web API [Web标准篇]>Web服务已经成为了异质系统之间的互联与集成的主要手段,在过去一段不短的时间里,Web服务几乎清一水地采用SOAP来构建.构建 ...

  7. 从英文变形规则计算到Restful Api设计

    ➠更多技术干货请戳:听云博客 一天在研究Restful API设计,命名的时候我总是很纠结,我相信大多数人也有这种感觉,不是说想不出来某个单词怎么写的问题,像我这种没事背单词背到13000词量的人也要 ...

  8. RESTful API 设计指南 (转)

    RESTful API 设计指南 2016-02-23 ImportNew (点击上方公号,可快速关注) 作者:阮一峰 链接:http://www.ruanyifeng.com/blog/2014/0 ...

  9. 基于资源的权限系统-API设计

    概述 权限系统需要和别的系统集成,因此,良好的API是易用性的保证. 这里只设计一些权限相关的核心 API,关于用户,组织,导入导出之类的后续再逐步补充 API 设计 围绕权限有以下 4 类 API: ...

  10. Atitit. Api 设计 原则 ---归一化

    Atitit. Api 设计 原则 ---归一化 1.1. 叫做归一化1 1.2. 归一化的实例:一切对象都可以序列化/toString  通过接口实现1 1.3. 泛文件概念.2 1.4. 游戏行业 ...

随机推荐

  1. python 3.7环境安装并使用csv

    因为调换需要,进了另外一个维护组,需要用python解析excel csv,所以就下载了一下他们需要的python3.7 如何做呢,看步骤 1.去官网 2.找版本 3.下源码 4.解压出来进入文件夹 ...

  2. 用于自然语言处理的循环神经网络RNN

    前一篇:<人工智能模型学习到的知识是怎样的一种存在?> 序言:在人工智能领域,卷积神经网络(CNN)备受瞩目,但神经网络的种类远不止于此.实际上,不同类型的神经网络各有其独特的应用场景.在 ...

  3. 基于antlr的表达式解析器——函数生成(通过freemarker)

    第一步.新建一个模板文件以.ftl结尾. Max.ftl /* * Copyright 2002-2007 Robert Breidecker. * * Licensed under the Apac ...

  4. Git中使用tag

    什么是tag git仓库的tag是git版本库的一个标记,指向某个commit id标记的快照记录指针,所以,标签也是版本库的一个快照. tag主要用于发布版本的管理,一个当版本发布后,可以为git当 ...

  5. RabbitMQ之安装与使用

    官网:https://www.rabbitmq.com/ 一. RabbitMQ 简介 MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法.应用程序通过读写出入 ...

  6. PHP7.4之编译安装

    虽然之前写过很多编译安装PHP的文章, 但是隔段时间还是会重新安装一些PHP的版本,再次记录一下 1. 下载安装编译工具 yum groupinstall 'Development Tools' 2. ...

  7. linux 软连接使用

    转载请注明出处: 在Linux系统中,软连接(Symbolic Link)是一种特殊类型的文件链接,类似于Windows系统中的快捷方式.它允许用户通过一个文件路径访问另一个文件或目录,而不需要拥有原 ...

  8. Vue组件样式穿透

    前情 Vue是目前主流的前端框架之一,我是Vue框架的忠实老用户,平时开发中如果再依赖个第三方组件库那样开发效率就会事半功倍. 第三方组件库可以很大提高开发效率,但是叫会有一些UI效果需要自定义,如想 ...

  9. 【并查集+dfs】codeforces 1833 E. Round Dance

    题意 输入一个正整数 \(T(1 \leq T \leq 10^4)\),表示接下来输入 \(T\) 组测试用例,对于每一个测试用例: 第一行,输入一个正整数 \(n(2 \leq n \leq 2 ...

  10. ng-alain: Title Service

    文档地址:https://ng-alain.com/theme/title/zh 源码地址: https://github.com/ng-alain/delon/blob/master/package ...