Designing a good function API is not an easy task, but many useful guidelines exist to facilitate this process. However, one aspect of a good API is often given insufficient attention: what to do when the function is called with arguments outside of its domain — i.e., when the function preconditions are violated. Artificially expanding the function domain — e.g., by throwing an exception or returning an error code — might be a tempting option to handle inputs that are syntactically but not semantically valid. Instead, we will show how using a contract-checking facility — even one as simple as C assert — to detect misuse leads to reducing the incidence of software defects and facilitates robust, maintainable, and high-performance software.
We will start by considering what constitutes a complete function contract; when and why narrow contracts (those with preconditions) are preferable to wide ones, and how to use defensive checks to detect the function’s misuse by its programmatic clients. We will then focus on the practical aspects of using function contracts in real-world software. We will touch on rendering function contracts for consumption by the function’s (human) clients, on the necessity and implementation of testing the contract checks themselves, and the design considerations for a contract-checking facility suitable for use at scale.