我的会议如何设计一个好的API及其重要性一直吸引着很多人。 去年,InfoQ上的观看次数排名第三。 当我在OOPSLA 2006上以受邀演讲的形式介绍本次会议时,有机会为会议记录撰写摘要。 我决定代替普通的摘要,尝试一些不寻常的事情:我以乔恩·本特利(Jon Bentley)的经典《 保险杠-贴纸》计算机科学 ( Bumper-Sticker Computer Science)优秀著作中的第6项的精神,将谈话的精髓缩编为少量的虚构的格言。 ,《 更多的编程珍珠:编码人员的自白》 (Addison-Wesley,1988年)。
我希望这些格言能够以易于消化的形式简要概述API设计的要点:
所有程序员都是API设计人员。 好的程序是模块化的,而模块化之间的边界定义了API。 好的模块将被重用。
API可能是您最大的资产或负债之一。 好的API可以创造长期客户; 不好的人会造成长期的支持梦night。
像钻石一样的公共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。
小心超载。 如果两种方法的行为不同,则最好给它们指定不同的名称。
为作业使用正确的数据类型。 例如,如果有更合适的类型,请不要使用字符串。
跨方法使用一致的参数顺序。 否则,程序员会倒退。
避免使用长参数列表,尤其是那些具有多个相同类型连续参数的列表 。
避免需要特殊处理的返回值。 客户会忘记编写特殊情况的代码,从而导致错误。 例如,返回零长度数组或集合,而不是null。
抛出异常仅表示异常情况。 否则,客户端将被迫使用异常进行正常的流控制,从而导致程序难以阅读,出错或运行缓慢。
除非客户端可以从故障中实际恢复,否则将引发未经检查的异常。
API设计是一门艺术,而不是一门科学。 追求美丽,相信自己的直觉。 不要从容地遵循上述启发式方法,而应仅偶尔且有充分理由违反它们。
观看演示: 如何设计好的API及其重要性
Joshua Bloch是Google的首席Java架构师,《 有效Java,第二版》 (Addison-Wesley,2008年)的作者,还是《 Java Puzzlers:Traps,Pitfalls和Corner Cases》 (Addison-Wesley,2005年)和《 Java Concurrency in Practice》的合著者。 他曾是Sun Microsystems的杰出工程师,在那里他领导了许多Java平台功能(包括JDK 5.0语言增强功能和Java Collections Framework)的设计和实现。 他拥有博士学位。 来自卡内基-梅隆大学,哥伦比亚大学学士学位。