API Design for C++ book cover

API Design for C++

API Design for C++ provides a comprehensive discussion of Application Programming Interface (API) development, from initial design through implementation, testing, documentation, release, versioning, maintenance, and deprecation. The book focuses on the issues of designing APIs for a single language (C++), which remains one of the most widely used programming languages for large software projects. The book also covers specialized API topics, such as creating scripting and plug-in APIs, with emphasis on API design. A discussion on testing strategies concentrates on automated API testing techniques rather than attempting to include end-user application testing techniques such as GUI testing, system testing, or manual testing. The book will be helpful to new programmers who understand the fundamentals of C++ and who want to advance their design skills, as well as senior engineers and software architects seeking to gain new expertise to complement their existing talents. Three specific groups of readers are targeted: practicing software engineers and architects, technical managers, and students and educators.

Audience

All software engineers developing C++ code to be used by other developers, whether via APIs, libraries, device drivers, or other reusable components.

Paperback, 472 Pages

Published: February 2011

Imprint: Morgan Kaufmann

ISBN: 978-0-12-385003-4

Reviews

  • Martin Reddy draws from his experience on large scale, collaborative software projects to present patterns and practices that provide real value to individual developers as well as organizations. API Design for C++ explores often overlooked issues, both technical and non- technical, contributing to successful design decisions that produce high quality, robust, and long-lived APIs. - Eric Gregory, Software Architect, Pixar Animation Studios

    "Intended for programmers with intermediate to advanced skills in the C++ programming language, this guide to the building of useful and robust application programming interfaces (APIs) provides practical instruction for software engineers developing systems on which downstream software engineers depend. The work provides a methodical approach to API design covering solution based API design, performance, versioning, documentation, testing, scripting, extensibility and libraries. The work includes numerous illustrations and code examples and access to additional online resources is provided. Reddy is a software development consultant."--Book News, Reference & Research


Contents


  • Foreword

    Preface

    Acknowledgments

    Author Biography

    Chapter 1 Introduction

    1.1 What Are Application Programming Interfaces?

    1.1.1 Contracts and Contractors

    1.1.2 APIs in C++

    1.2 What’s Different About API Design?

    1.3 Why Should You Use APIs?

    1.3.1 More Robust Code

    1.3.2 Code Reuse

    1.3.3 Parallel Development

    1.4 When Should You Avoid APIs?

    1.5 API Examples

    1.5.1 Layers of APIs

    1.5.2 A Real-Life Example

    1.6 File Formats and Network Protocols

    1.7 About This Book

    Chapter 2 Qualities

    2.1 Model the Problem Domain

    2.1.1 Provide a Good Abstraction

    2.1.2 Model the Key Objects

    2.2 Hide Implementation Details

    2.2.1 Physical Hiding: Declaration versus Definition

    2.2.2 Logical Hiding: Encapsulation

    2.2.3 Hide Member Variables

    2.2.4 Hide Implementation Methods

    2.2.5 Hide Implementation Classes

    2.3 Minimally Complete

    2.3.1 Don’t Overpromise

    2.3.2 Add Virtual Functions Judiciously

    2.3.3 Convenience APIs

    2.4 Easy to Use

    2.4.1 Discoverable

    2.4.2 Difficult to Misuse

    2.4.3 Consistent

    2.4.4 Orthogonal

    2.4.5 Robust Resource Allocation

    2.4.6 Platform Independent

    2.5 Loosely Coupled

    2.5.1 Coupling by Name Only

    2.5.2 Reducing Class Coupling

    2.5.3 Intentional Redundancy

    2.5.4 Manager Classes

    2.5.5 Callbacks, Observers, and Notifications

    2.6 Stable, Documented, and Tested

    Chapter 3 Patterns

    3.1 Pimpl Idiom

    3.1.1 Using Pimpl

    3.1.2 Copy Semantics

    3.1.3 Pimpl and Smart Pointers

    3.1.4 Advantages of Pimpl

    3.1.5 Disadvantages of Pimpl

    3.1.6 Opaque Pointers in C

    3.2 Singleton

    3.2.1 Implementing Singletons in C++

    3.2.2 Making Singletons Thread Safe

    3.2.3 Singleton versus Dependency Injection

    3.2.4 Singleton versus Monostate

    3.2.5 Singleton versus Session State

    3.3 Factory Methods

    3.3.1 Abstract Base Classes

    3.3.2 Simple Factory Example

    3.3.3 Extensible Factory Example

    3.4 API Wrapping Patterns

    3.4.1 The Proxy Pattern

    3.4.2 The Adapter Pattern

    3.4.3 The Facade Pattern

    3.5 Observer Pattern

    3.5.1 Model-View-Controller

    3.5.2 Implementing the Observer Pattern

    3.5.3 Push versus Pull Observers

    Chapter 4 Design

    4.1 A Case for Good Design

    4.1.1 Accruing Technical Debt

    4.1.2 Paying Back the Debt

    4.1.3 Design for the Long Term

    4.2 Gathering Functional Requirements

    4.2.1 What Are Functional Requirements?

    4.2.2 Example Functional Requirements

    4.2.3 Maintaining the Requirements

    4.3 Creating Use Cases

    4.3.1 Developing Use Cases

    4.3.2 Use Case Templates

    4.3.3 Writing Good Use Cases

    4.3.4 Requirements and Agile Development

    4.4 Elements of API Design

    4.5 Architecture Design

    4.5.1 Developing an Architecture

    4.5.2 Architecture Constraints

    4.5.3 Identifying Major Abstractions

    4.5.4 Inventing Key Objects

    4.5.5 Architectural Patterns

    4.5.6 Communicating the Architecture

    4.6 Class Design

    4.6.1 Object-Oriented Concepts

    4.6.2 Class Design Options

    4.6.3 Using Inheritance

    4.6.4 Liskov Substitution Principle

    4.6.5 The Open/Closed Principle

    4.6.6 The Law of Demeter

    4.6.7 Class Naming

    4.7 Function Design

    4.7.1 Function Design Options

    4.7.2 Function Naming

    4.7.3 Function Parameters

    4.7.4 Error Handling

    Chapter 5 Styles

    5.1 Flat C APIs

    5.1.1 ANSI C Features

    5.1.2 Benefits of an ANSI C API

    5.1.3 Writing an API in ANSI C

    5.1.4 Calling C Functions from C++

    5.1.5 Case Study: FMOD C API

    5.2 Object-Oriented C++ APIs

    5.2.1 Advantages of Object-Oriented APIs

    5.2.2 Disadvantages of Object-Oriented APIs

    5.2.3 Case Study: FMOD C++ API

    5.3 Template-Based APIs

    5.3.1 An Example Template-Based API

    5.3.2 Templates versus Macros

    5.3.3 Advantages of Template-Based APIs

    5.3.4 Disadvantages of Template-Based APIs

    5.4 Data-Driven APIs

    5.4.1 Data-Driven Web Services

    5.4.2 Advantages of Data-Driven APIs

    5.4.3 Disadvantages of Data-Driven APIs

    5.4.4 Supporting Variant Argument Lists

    5.4.5 Case Study: FMOD Data-Driven API

    Chapter 6 C++ Usage

    6.1 Namespaces

    6.2 Constructors and Assignment

    6.2.1 Controlling Compiler-Generated Functions

    6.2.2 Defining Constructors and Assignment

    6.2.3 The Explicit Keyword

    6.3 Const Correctness

    6.3.1 Method Const Correctness

    6.3.2 Parameter Const Correctness

    6.3.3 Return Value Const Correctness

    6.4 Templates

    6.4.1 Template Terminology

    6.4.2 Implicit Instantiation API Design

    6.4.3 Explicit Instantiation API Design

    6.5 Operator Overloading

    6.5.1 Overloadable Operators

    6.5.2 Free Operators versus Member Operators

    6.5.3 Adding Operators to a Class

    6.5.4 Operator Syntax

    6.5.5 Conversion Operators

    6.6 Function Parameters

    6.6.1 Pointer versus Reference Parameters

    6.6.2 Default Arguments

    6.7 Avoid #define for Constants

    6.8 Avoid Using Friends

    6.9 Exporting Symbols

    6.10 Coding Conventions

    Chapter 7 Performance

    7.1 Pass Input Arguments by Const Reference

    7.2 Minimize #include Dependencies

    7.2.1 Avoid “Winnebago” Headers

    7.2.2 Forward Declarations

    7.2.3 Redundant #include Guards

    7.3 Declaring Constants

    7.3.1 The New constexpr Keyword

    7.4 Initialization Lists

    7.5 Memory Optimization

    7.6 Don’t Inline Until You Need To

    7.7 Copy on Write

    7.8 Iterating Over Elements

    7.8.1 Iterators

    7.8.2 Random Access

    7.8.3 Array References

    7.9 Performance Analysis

    7.9.1 Time-Based Analysis

    7.9.2 Memory-Based Analysis

    7.9.3 Multithreading Analysis

    Chapter 8 Versioning

    8.1 Version Numbers

    8.1.1 Version Number Significance

    8.1.2 Esoteric Numbering Schemes

    8.1.3 Creating a Version API

    8.2 Software Branching Strategies

    8.2.1 Branching Strategies

    8.2.2 Branching Policies

    8.2.3 APIs and Parallel Branches

    8.2.4 File Formats and Parallel Products

    8.3 Life Cycle of an API

    8.4 Levels of Compatibility

    8.4.1 Backward Compatibility

    8.4.2 Functional Compatibility

    8.4.3 Source Compatibility

    8.4.4 Binary Compatibility

    8.4.5 Forward Compatibility

    8.5 How to Maintain Backward Compatibility

    8.5.1 Adding Functionality

    8.5.2 Changing Functionality

    8.5.3 Deprecating Functionality

    8.5.4 Removing Functionality

    8.6 API Reviews

    8.6.1 The Purpose of API Reviews

    8.6.2 Prerelease API Reviews

    8.6.3 Precommit API Reviews

    Chapter 9 Documentation

    9.1 Reasons to Write Documentation

    9.1.1 Defining Behavior

    9.1.2 Documenting the Interface’s Contract

    9.1.3 Communicating Behavioral Changes

    9.1.4 What to Document

    9.2 Types of Documentation

    9.2.1 Automated API Documentation

    9.2.2 Overview Documentation

    9.2.3 Examples and Tutorials

    9.2.4 Release Notes

    9.2.5 License Information

    9.3 Documentation Usability

    9.4 Using Doxygen

    9.4.1 The Configuration File

    9.4.2 Comment Style and Commands

    9.4.3 API Comments

    9.4.4 File Comments

    9.4.5 Class Comments

    9.4.6 Method Comments

    9.4.7 Enum Comments

    9.4.8 Sample Header with Documentation

    Chapter 10 Testing

    10.1 Reasons to Write Tests

    10.2 Types of API Testing

    10.2.1 Unit Testing

    10.2.2 Integration Testing

    10.2.3 Performance Testing

    10.3 Writing Good Tests

    10.3.1 Qualities of a Good Test

    10.3.2 What to Test

    10.3.3 Focusing the Testing Effort

    10.3.4 Working with QA

    10.4 Writing Testable Code

    10.4.1 Test-Driven Development

    10.4.2 Stub and Mock Objects

    10.4.3 Testing Private Code

    10.4.4 Using Assertions

    10.4.5 Contract Programming

    10.4.6 Record and Playback Functionality

    10.4.7 Supporting Internationalization

    10.5 Automated Testing Tools

    10.5.1 Test Harnesses

    10.5.2 Code Coverage

    10.5.3 Bug Tracking

    10.5.4 Continuous Build System

    Chapter 11 Scripting

    11.1 Adding Script Bindings

    11.1.1 Extending versus Embedding

    11.1.2 Advantages of Scripting

    11.1.3 Language Compatibility Issues

    11.1.4 Crossing the Language Barrier

    11.2 Script-Binding Technologies

    11.2.1 Boost Python

    11.2.2 SWIG

    11.2.3. Python-SIP

    11.2.4 COM Automation

    11.2.5 CORBA

    11.3 Adding Python Bindings with Boost Python

    11.3.1 Building Boost Python

    11.3.2 Wrapping a C++ API with Boost Python

    11.3.3 Constructors

    11.3.4 Extending the Python API

    11.3.5 Inheritance in C++

    11.3.6 Cross-Language Polymorphism

    11.3.7 Supporting Iterators

    11.3.8 Putting It All Together

    11.4 Adding Ruby Bindings with SWIG

    11.4.1 Wrapping a C++ API with SWIG

    11.4.2 Tuning the Ruby API

    11.4.3 Constructors

    11.4.4 Extending the Ruby API

    11.4.5 Inheritance in C++

    11.4.6 Cross-Language Polymorphism

    11.4.7 Putting It All Together

    Chapter 12 Extensibility

    12.1 Extending via Plugins

    12.1.1 Plugin Model Overview

    12.1.2 Plugin System Design Issues

    12.1.3 Implementing Plugins in C

    12.1.4 The Plugin API

    12.1.5 An Example Plugin

    12.1.6 The Plugin Manager

    12.1.7 Plugin Versioning

    12.2 Extending via Inheritance

    12.2.1 Adding Functionality

    12.2.2 Modifying Functionality

    12.2.3 Inheritance and the STL

    12.2.4 Inheritance and Enums

    12.2.5 The Visitor Pattern

    12.2.6 Prohibiting Subclassing

    12.3 Extending via Templates

    12.3.1 Policy-Based Templates

    12.3.2 The Curiously Recurring Template Pattern

    Appendix A Libraries

    A.1 Static versus Dynamic Libraries

    A.1.1 Static Libraries

    A.1.2 Dynamic Libraries

    A.1.3 Dynamic Libraries as Plugins

    A.2 Libraries on Windows

    A.2.1 Importing and Exporting Functions

    A.2.2 The DLL Entry Point

    A.2.3 Creating Libraries on Windows

    A.2.4 Useful Windows Utilities

    A.2.5 Loading Plugins on Windows

    A.3 Libraries on Linux

    A.3.1 Creating Static Libraries on Linux

    A.3.2 Creating Dynamic Libraries on Linux

    A.3.3 Shared Library Entry Points

    A.3.4 Useful Linux Utilities

    A.3.5 Loading Plugins on Linux

    A.3.6 Finding Dynamic Libraries at Run Time

    A.4 Libraries on Mac OS X

    A.4.1 Creating Static Libraries on Mac OS X

    A.4.2 Creating Dynamic Libraries on Mac OS X

    A.4.3 Frameworks on Mac OS X

    A.4.4 Finding Dynamic Libraries at Run Time

    Bibliography

    Index






Advertisement

advert image