你如何定义好的或坏的API?

时间:2009-01-22 13:42:12

标签: api api-design

背景

我正在我的大学上课,称为“软件约束”。在第一次讲座中,我们学习了如何构建优秀的API。

我们得到一个非常糟糕的API函数的一个很好的例子是C#中的套接字public static void Select(IList checkRead, IList checkWrite, IList checkError, int microseconds);。该函数接收3个套接字列表,并销毁它们,使用户必须克隆所有套接字才能将它们送入Select()。它还有一个超时(以微秒为单位),它是一个int,用于设置服务器等待套接字的最长时间。这个限制是+/- 35分钟(因为它是一个int)。


问题:

  1. 如何将API定义为 '坏'?
  2. 你如何定义一个 API为“好”?

  3. 要考虑的要点:

    • 难以记住的功能名称。
    • 难以理解的功能参数。
    • 文档错误。
    • 一切都是如此相互关联,如果您需要更改1行代码,您实际上需要在其他地方更改数百行。
    • 破坏其论点的函数。
    • 由于“隐藏”的复杂性导致可扩展性差。
    • 需要用户/ dev在API周围构建包装器才能使用它。

14 个答案:

答案 0 :(得分:105)

在API设计中,我总是发现这个主题演讲非常有帮助:
How to Design a Good API and Why it Matters - by Joshua Bloch

这是摘录,我建议阅读整篇文章/观看视频。

  

II。一般原则

     
      
  • API应该做一件事并做得很好
  •   
  • API应该尽可能小但不能小一点
  •   
  • 实施不应影响API
  •   
  • 尽量减少一切的可访问性
  •   
  • 名称Matter-API是一种小语言
  •   
  • 文件事项
  •   
  • 宗教文件
  •   
  • 考虑API设计决策的性能后果
  •   
  • API设计决策对绩效的影响是真实和永久的
  •   
  • API必须与平台和平共存
  •   
     

III。班级设计

     
      
  • 尽量减少可变性
  •   
  • 只有它有意义的子类
  •   
  • 继承的设计和文件或禁止它
  •   
     

IV。方法设计

     
      
  • 不要让客户做任何模块可以做的事
  •   
  • 不要违反最小惊讶原则
  •   
  • 快速失败 - 发生错误后尽快报告错误
  •   
  • 以字符串形式提供对所有可用数据的编程访问权
  •   
  • 小心超载
  •   
  • 使用适当的参数和返回类型
  •   
  • 使用跨方法的一致参数排序
  •   
  • 避免长参数列表
  •   
  • 避免要求异常处理的返回值
  •   

答案 1 :(得分:37)

您无需阅读文档即可正确使用它。

令人敬畏的API的标志。

答案 2 :(得分:14)

许多编码标准以及longer documents甚至books (Framework Design Guidelines)都是针对这一主题撰写的,但其中大部分仅在相当低的水平上有所帮助。

还有品味问题。 API可以遵守任何规则手册中的每一条规则,并且由于对各种时尚意识形态的盲目遵守而仍然很糟糕。最近的一个罪魁祸首是模式导向,其中Singleton模式(仅比初始化的全局变量更多)和Factory Patterns(一种参数化构造的方式,但通常在不需要时实现)被过度使用。最近,控制反转(IoC)和微小接口类型数量的相关爆炸更有可能给设计增加了多余的概念复杂性。

最好的品味导师是模仿(阅读大量代码和API,找出哪些有效,哪些无效),体验(犯错误并从中学习)和思考(不要只做它的时尚之作)自己的缘故,在行动前思考。)

答案 3 :(得分:12)

  • 有用 - 它解决了尚未满足的需求(或改进现有需求)
  • 易于解释 - 对其所做的基本理解应该很容易理解
  • 遵循某些问题域或现实世界的某些对象模型。它使用有意义的结构
  • 正确使用同步和异步调用。 (不要阻止需要时间的事情)
  • 良好的默认行为 - 尽可能允许扩展和调整,但为简单案例提供所有必需的默认值
  • 样本使用和工作样本应用程序。这可能是最重要的。
  • 优秀文档
  • 吃自己的狗粮(如适用)
  • 保持小或将其分割,使其不是一个巨大的污染空间。保持功能集独立和隔离,几乎没有任何依赖。

还有更多,但这是一个好的开始

答案 4 :(得分:7)

一个好的API允许客户端完成他们需要做的所有事情,但不要求他们做很多盲目忙碌的工作。 “盲目繁忙的工作”的例子是初始化数据结构字段,按顺序调用几个例程,这些例程永远不会因中间没有真正的自定义代码而变化,等等。

错误API的最可靠迹象是,如果您的客户都希望用自己的帮助程序代码包装它。至少,您的API应该提供了帮助程序代码。最有可能的是,它应该被设计为提供客户每次都自己滚动的更高层次的抽象。

答案 5 :(得分:6)

一个好的API的语义模型接近它所描述的内容。

例如,用于创建和操作Excel电子表格的API将包含WorkbookSheetCell等类,其中包含Cell.SetValue(text)和{{1}等方法}。

答案 6 :(得分:6)

我一直很喜欢名为 API Design Matters

的队列中的这篇文章

http://queue.acm.org/detail.cfm?id=1255422

此列还涉及API设计问题:

http://queue.acm.org/detail.cfm?id=1229903

答案 7 :(得分:3)

错误的API是其目标受众未使用的API。

一个好的API是其目标受众用于其设计目的的API。

一个出色的API是其目标受众用于其预期目的的API,以及由于其设计者未曾预料到的原因而无意识的受众。

如果亚马逊将其API作为SOAP和REST发布,并且REST版本胜出,那么这并不意味着底层的SOAP API是坏的。

我想你也会如此。您可以阅读所有您想要的设计并尽力而为,但酸性测试将被使用。花一些时间建立一些方法来获得有效和无效的反馈,并准备根据需要进行重构以使其更好。

答案 8 :(得分:2)

一个好的API是简单的事情(最简单的样板和学习曲线来做最常见的事情)和复杂的事情(最大的灵活性,尽可能少的假设)。一个平庸的API可以很好地完成其中一个(要么非常简单,但只有当你试图做真正基本的东西,或者非常强大,但学习曲线非常陡峭等)。一个可怕的API是一个既不能做到这一点的API。

答案 9 :(得分:2)

答案 10 :(得分:1)

我认为一个好的API应该允许自定义IO和内存管理挂钩(如果它适用)。

一个典型的例子是您拥有磁盘上数据的自定义压缩归档格式,而且api较差的第三方库希望访问磁盘上的数据,并且需要一个文件路径来加载其数据。

此链接有一些好处: http://gamearchitect.net/2008/09/19/good-middleware/

答案 11 :(得分:1)

如果API产生错误消息,请确保消息和诊断有助于开发人员解决问题所在。

我的期望是API的调用者传入正确的输入。开发人员是API(而不是最终用户)生成的任何错误消息的使用者,针对开发人员的消息可帮助开发人员调试其调用程序。

答案 12 :(得分:0)

如果API记录严重,则

如果API记录良好且遵循编码标准,则

现在这些是非常简单的,也是非常难以遵循的,这将带来一个软件架构领域。你需要一个好的架构师来构建系统,并帮助框架遵循自己的指导。

评论代码,为API编写解释良好的手册是强制性的。

如果API具有解释如何使用它的良好文档,那么它可能会很好。但是如果代码是干净的,良好的并且遵循内部标准,那么如果它确实有一个不错的文档就无所谓。

我写了一些关于编码结构here

的文章

答案 13 :(得分:0)

我认为最重要的是可读性,我的意思是质量使得最多的程序员能够在最短的时间内理解代码的作用。但是判断哪个软件是可读的,哪个不具有难以描述的人类品质:模糊性。你提到的要点部分地成功地结晶了它。但是,整体而言,它必须是个案,并且很难提出普遍规则。