1.2 API设计上有什么不同
接口是开发者所编写的最重要的代码。因为比起相关的实现代码出现问题,修复接口出现的问题代价要大得多。因此,相比标准应用程序或图形用户界面(GUI)的开发,共享API的开发过程应该给予更多关注。当然,二者均涉及最佳设计实践;不过,API开发直接关系到项目的成败。下面列举了API开发中的一些关键因素。
API是为开发者设计的接口,如同GUI是为用户设计的接口一样。事实上,有人曾经说过:API是为了编程(www.cppentry.com)人员所开发的用户接口(Arnold, 2005)。因此,你的API可能会被世界各地成百上千的开发者调用,而且无疑会以你从来没有设想过的方式调用(Tulach, 2008)。你必须在设计中考虑到这点。精心设计的API可以成为你的组织中最大的资产。而设计拙劣的API可能会导致一场技术支持的噩梦,甚至可能让你的用户转而投向竞争者的怀抱(Bloch, 2005),如同一个漏洞百出、难以使用的GUI会导致最终用户改用其他应用程序一样。
多个应用程序可以共享同一个API。如图1-1所示,一个应用程序可以由多个API组成。而且,其中任一API同样也可以被其他应用程序重用。这意味着如果一个特定的应用程序代码出现了错误,只会影响到该应用程序本身,而如果API的代码中出现了错误,就会影响到所有使用该API的应用程序。
修改API时,必须尽可能保证向后兼容。如果不能做到接口向后兼容的修改,客户端代码可能会编译错误,或者更糟,代码能够通过编译,但在运行时出现错误结果或使应用程序崩溃。想象一下,如果在标准C库中printf()函数的签名会因为使用不同的编译器和平台而产生了各种混淆和混乱的情况,那么一个简单的"Hello World"程序可就没有看上去那么简单了:

虽然这个例子看起来可能有点刻意,但实际上它并不是极端情况。查看编译器携带的标准头文件,就会发现类似的令人费解、不可思议的声明,或者更糟的问题。
出于向后兼容的需求,一定要具有变更控制流程。在正常的开发过程中,许多开发人员都可能要修复API中的错误或者向API中添加一项新功能。一些开发人员可能是初级工程师,他们不能完全理解良好API设计的各个方面。因此,在发布新版本的API之前,对其进行审查是十分重要的。审查工作包括:一名或多名高级工程师检查所有接口的改变是否合适,理由是否合理,是否使用最佳方式实现以保证向后兼容性。在很多开源API中,如果要改变源代码,必须遵循变更请求流程,只有获得批准,才能将变更加入源代码中。
API的生存周期一般都比较长。为了创造良好的API,在前期要投入巨大的成本,因为规划、设计、版本和审查开销是必不可少的。如果这方面做好了,则能够极大地降低长期成本,因为能够对软件进行根本的修改和改进,而不会干扰到客户。换言之,由于增加了API灵活性,开发速度也会大大提高。
在编写API时,良好的文档必不可少,特别是当不提供实现的源代码时。虽然用户可以通过阅读头文件搜集使用方法,但是头文件并没有定义API的行为,例如可接受的输入值或错误条件。因此,精心编写的、术语一致且内容全面的文档是任何优秀API的必备品。
自动化测试同样也很重要。当然,你总是应该测试你的代码,但是当编写API时,你可能拥有成百上千的其他开发人员以及他们的成千上万的用户,他们都依赖于你的代码的正确性。当你对API的实现进行重大修改时,如果你有一套完整的回归测试验证并未改变所需的API行为,那么就会更有信心地保证不会让客户的程序崩溃。
编写优质的API非常困难。虽然基本的技能是建立在传统的软件设计原则中的,但还需要另外一些知识和开发过程来解决刚才列出的几点问题。然而,API设计的原则与技术却很少教授给工程师。一般来说,这些技能只能通过经验积累,而经验又来源于不断犯错误或借鉴别人的经验,了解什么可行什么不可行(Henning, 2009)。本书尝试纠正这种情况,提炼出耐用且不会过时的API设计策略,并将这些策略由软件工程经验演化为全面、实用且易于理解的形式。
提示
API描述了其他工程师构建他们的应用软件所使用的软件。因此,API必须拥有良好的设计、文档、回归测试,并且保证发布之间的稳定性。