API Design for C++ by Martin Reddy
February 18, 2011
Publisher: Morgan Kaufmann
In the first chapter, the author answers a question "what is a good API?". He concentrates on language-neutral qualities of APIs, such as information hiding, consistency, and loose coupling. For example, he says that each class should have a central purpose reflected in its name and the methods. It's a good practice to have another person review your API to make sure it is consistent and logical. There is also a short refresher on UML class diagrams. In the next chapter, the author describes several patterns helpful in API design: pimpl idiom, Singleton, Factory Method, Proxy, Adapter, Facade, and Observer. There is also a chapter about functional requirement gathering and use case modeling as well as object-oriented analysis and design. Various styles of C++ APIs are described: flat C APIs, object-oriented APIs, template-based APIs, and data-driven APIs. The next chapter discusses several C++ language features such as constructors/destructors, namespaces, pointer and reference parameters, friend functions, etc. There is also a chapter about performance in C++ using const references, forward declarations, data member clustering, inlining, etc. Versioning has its own chapter with an emphasis on API compatibility: backward, forward, functional, source, and binary. The importance of good documentation techniques with an example of using the Doxygen tool is a topic of another chapter. Various types of automated testing (unit, integration, performance tests) and testing methodologies (test-driven development, stub and mock objects, testing private code, and contract programming) are also presented. The last two chapters deal with optional topics such as scripting access to an API and extensibility through custom C++ plugins. An appendix provides information on how to create static and dynamic libraries in C++.
The book website http://apibook.com provides supporting material as well as a detailed table of contents. It also describes topics discussed in each chapter and includes Chapter 3 - Patterns as a PDF file. The example code should work on Windows, Mac OS X, and UNIX as the author uses the cross-platform CMake build system for compilation and linking.
An API is defined as "reusable building blocks that allow modular pieces of functionality to be incorporated into end-user applications". It provides a logical interface for a client while hiding its implementation details. We can think of the API as an abstraction and a functional specification of a component it implements. The importance of well-defined interfaces is underlined by a fact that problems in interfaces are far more costly to fix than problems in the associated implementation. That's because APIs (and their interfaces) should remain backward compatible which implies a need for a change control process and automated regression testing. Also, a stable interface acts like a contract between two pieces of software. This allows multiple developers to work in parallel and call API's functions before they are even completed. Good documentation should also be delivered with an API.
Whenever you create a file format or client/server protocol, you should also provide an API to interoperate with them.
APIs promotes, among other things, code reuse. While there are many benefits of that (e.g., reduction of code duplication) you may encounter also some difficulties. For example, if you intend to reuse a given piece of code you may need to come up with a more general interface than you intended in order to encompass clients changing requirements.
There are also circumstances when it is better to avoid creating an API. For example, if the API is going to be used only in a single application it may not be worth an effort of planning, testing, documenting and supporting. On the other hand, you may consider creating your own API if existing APIs have some limitations such as license restrictions, not exact functionality you need, no source code, or poor documentation.