This appendix provides guidance on when to apply which pattern in the form of a cheat sheet. It also connects our pattern language with responsibility-driven design (RDD), domain-driven design (DDD), and the Align-Define-Design-Refine (ADDR) process.
The cheat sheet provides issue-pattern tables to indicate when a particular pattern is eligible. Please note that this is a gross simplification of a set of complex design problems and considerations. The decision models in Part 1 and the pattern texts in Part 2 discuss context, forces, and consequences of related solutions in much more depth. Chapter 4 provides several more entry points for book content and pattern language.
Foundation patterns address the early and basic API scoping issues. Table A.1 lists such issues and corresponding patterns.
The selection of these patterns is driven by criteria such as type of client, business model, product/project vision, and project/product context. The client portfolio (that is, number and location of clients, information needs of these clients), and security requirements are important criteria to consider. Chapters 1, 3, and 4 collect many more decision drivers and desired qualities.
Table A.1 Eligibility of API Foundation Patterns (Covered in Chapter 4)
Issue | Patterns to Consider |
An end-user application wants data from or activity in a backend | Realize a FRONTEND INTEGRATION API |
Two backends have to collaborate to fulfill a business requirement | Realize a BACKEND INTEGRATION API |
A new API should be broadly accessible | Introduce a PUBLIC API |
The visibility of a new API should be restricted to a group of clients | Introduce a COMMUNITY API |
A new API targets a single application only, for instance to decompose it into services | Introduce a SOLUTION-INTERNAL API |
Next up, in Table A.2, responsibility patterns can jumpstart API endpoint design.
Table A.2 How to Identify and Classify API Endpoints by Role (from Chapter 5)
Issue | Pattern(s) |
Identify API endpoint candidates | Apply DDD and/or stepwise API design practice such as ADDR or one of those compiled in Design Practice Reference [Zimmermann 2021b] |
Model a business capability that is action-oriented (representing business activities or commands) | Define a PROCESSING RESOURCE and realize the required activities as well as coordination and state management in its operations (see Table A.3) |
Model a business capability that is data-oriented | Define an INFORMATION HOLDER RESOURCE, being aware of the coupling introduced and provide suited create, read, update, delete, and search operations for it (Table A.3) |
Let applications exchange transient data without coupling them directly | Define a DATA TRANSFER RESOURCE and add API clients to the applications |
Decouple provider locations from clients | Provide a LINK LOOKUP RESOURCE as an directory serving dynamic endpoint references |
Expose short-lived, transactional data | Mark an INFORMATION HOLDER RESOURCE as OPERATIONAL DATA HOLDER |
Expose long-lived, mutable data | Mark an INFORMATION HOLDER RESOURCE as MASTER DATA HOLDER |
Expose long-lived data not mutable for clients | Mark an INFORMATION HOLDER RESOURCE as REFERENCE DATA HOLDER |
During endpoint identification, one might decide to define one API or one API endpoint for each “Bounded Context” from DDD if logic and data are highly cohesive [Singjai 2021a]. If fine-grained decomposition is desired and possible, “Aggregate” may initiate API and API endpoint identification [Singjai 2021b; Singjai 2021c].
The operations exposed by API endpoints differ in the way they touch (or do not touch) provider-side state: read, write, read-write, or neither read nor write (Table A.3).
Table A.3 How to Classify Operations (from Chapter 5)
Issue | Pattern(s) |
Allow API client to initialize provider-side state (including domain-layer entities) | Mark an operation as write-only STATE CREATION OPERATION |
Allow API client to query and read provider-side state | Mark an operation as read-only RETRIEVAL OPERATION |
Allow API client to update or delete provider-side state | Mark an operation as read-write STATE TRANSITION OPERATION (variants: full/partial state replacement, state deletion) |
Allow API client to invoke a state-agnostic operation | Mark an operation as COMPUTATION FUNCTION |
Once the roles and responsibilities of API endpoints and their operations have been characterized, it is time to specify the data contract (the structure of headers and body in request and response messages, that is). Table A.4 shows the different options.
Table A.4 Basic Message Structure Patterns (from Chapter 4)
Issue | Pattern(s) |
Data is simple | Design ATOMIC PARAMETER and/or ATOMIC PARAMETER LIST for request and response messages |
Data is complex | Design PARAMETER TREE, possibly arranged as PARAMETER FOREST for requests and responses; PARAMETER TREES may contain others and ATOMIC PARAMETERS or ATOMIC PARAMETER LISTS as leaves |
Table A.5 shows how, in message payload design, both basic and structured message elements may receive certain stereotypical roles.
Table A.5 Element Stereotypes (from Chapter 6)
Issue | Pattern(s) |
Exchange structured data (for instance, domain entity representations) | Add DATA ELEMENT with EMBEDDED ENTITIES to message payload (following entity relationships) |
Distinguish representation elements or other API parts | Add ID ELEMENT to message payload (locally or globally unique) |
Make operation flow flexible | Upgrade from ID ELEMENT to LINK ELEMENT to support the REST principle of hypertext as the engine of application state (hypermedia controls); links may refer to PROCESSING RESOURCES or INFORMATION HOLDER RESOURCES |
Annotate payload to ease processing | Add METADATA ELEMENTS (control, provenance, aggregated metadata) |
Patterns related to API quality can help solve interoperability issues and size message representations right if the goal is to achieve data transfer parsimony (Table A.6).
Table A.6 When to Apply Which Quality Improvement (from Chapters 6, 7, and 9)
Issue | Pattern(s) |
API clients report interoperability and usability problems | Switch from minimal to elaborate API DESCRIPTION |
Add METADATA ELEMENTS to PARAMETER TREES | |
Introduce a CONTEXT REPRESENTATION in the payload encapsulating control metadata such as quality-of-service properties | |
API usage mistakes and other faults are difficult to analyze and fix | Add an ERROR REPORT to response representations to describe failures in detail |
API clients report performance problems | Switch from EMBEDDED ENTITIES to LINKED INFORMATION HOLDERS to adjust message size and service granularity (the two patterns can be combined flexibly) |
Reduce the amount of transferred data with a WISH LIST or a WISH TEMPLATE | |
Consider other quality patterns improving data transfer parsimony (for instance, CONDITIONAL REQUEST or REQUEST BUNDLE) | |
Introduce PAGINATION | |
Access control is needed | Introduce API KEYS or more advanced security solutions |
API providers have to deal with change and must balance compatibility and extensibility. The evolution patterns in Table A.7 cover strategies and tactics for doing so.
Table A.7 When to Apply Which Evolution Pattern (from Chapter 8)
Issue | Pattern(s) |
Indicate changes that are not backward compatible | Introduce a new major API version with a new, explicit VERSION IDENTIFIER |
Communicate the impact and significance of changes from version to version | Apply SEMANTIC VERSIONING to distinguish major, minor, and patch versions |
Maintain several versions of API endpoints and their operations | Offer TWO IN PRODUCTION (variant: N IN PRODUCTION) |
Avoid having to support multiple versions of API endpoints and their parts (including message structure elements) | Announce an AGGRESSIVE OBSOLESCENCE strategy and announce a decommissioning/removal date at any time (but grant an intermediate deprecation period) |
Commit to keeping API available and supported for a fixed amount of time | Give a LIMITED LIFETIME GUARANTEE and communicate it at API publication time |
Avoid committing to stability and future existence of API | Position API as an EXPERIMENTAL PREVIEW |
Once an API goes into production, documentation and governance tasks come into play. Table A.8 introduces some common issues and applicable patterns.
Table A.8 API Specification and Documentation (from Chapter 9)
Issue | Pattern(s) |
Clients need to know how to call the API | Create and publish a minimal or elaborate API DESCRIPTION |
Ensure fair use of the API | Enforce a RATE LIMIT |
Charge for API usage | Establish a PRICING PLAN |
Communicate quality-of-service characteristics | Issue a SERVICE LEVEL AGREEMENT or informal specification |
This section provides background information on RDD, summarizes how to leverage DDD to craft APIs, and revisits the complementary nature of the ADDR process (introduced at the beginning of Part 2) and our patterns.
To order and structure the endpoint and operation design space (or, in ADDR, the Define phase), we adopt some of the terminology and the role stereotypes from RDD [Wirfs-Brock 2002]. RDD was originally created for the context of object-oriented analysis and design (OOAD), which becomes apparent in its core definitions:
An application is a set of interacting objects.
An object is an implementation of one or more roles.
A role groups related responsibilities.
A responsibility is an obligation to perform a task or know information.
A collaboration may be an interaction of objects or roles, or a combination of both.
A contract is an agreement outlining the terms of a collaboration.
In our experience, RDD works equally well on the code level and on the architecture level. As API design has both architectural and developmental ramifications, the role stereotypes in RDD are a natural choice to express API behavior. For instance, all API endpoints can be seen to have (remote) interfacers that provide and protect access to service providers, controllers/coordinators, and information holder roles. The read-write operations exposed by API endpoints correspond to responsibilities. The API DESCRIPTION specifies the RDD contract, and collaborations arise from calls to API operations.
The patterns in Chapter 5 pick up these terms and concepts for the context of API design.
DDD [Evans 2003; Vernon 2013] and our patterns are also related in several ways:
DDD “Services” are good candidates for remote API exposure.
A DDD “Bounded Context” may correspond to a single API (with several endpoints).
A DDD “Aggregate” can also be exposed via an API (possibly having several endpoints, starting with the root “Entity”). Depending on the nature of an Aggregate, a PROCESSING RESOURCE is often preferred over an INFORMATION HOLDER RESOURCE; see the discussions in these two patterns for rationale.
DDD “Repositories” deal with entity life-cycle management, which involves read and write access to API provider-side application state (as defined by our operation responsibility patterns). For instance, repositories usually provide lookup capabilities, which may turn into API-level RETRIEVAL OPERATIONS. Special-purpose repositories may yield LINK LOOKUP RESOURCES. DDD “Factories” also deal with life-cycle management and may donate additional API operations (unless their functionality should remain an API-implementation detail).
DDD “Value Objects” can be exposed as data transfer representations (DTRs) in the Published Language established by the data part of the API DESCRIPTION. DATA ELEMENT from Chapter 6 is a related pattern.
In DDD, the Aggregate and Entity patterns often expose process-like properties (as they represent groups of domain concepts that have an identity and a life cycle at runtime). Hence, these patterns can help identify STATE CREATION OPERATION and STATE TRANSITION OPERATION candidates during endpoint identification. However, it is important not to expose the entire domain model as Published Language on the API level because this creates an undesired tight coupling between the API clients and the provider-side API implementation.
DDD does not distinguish between master data and operational data in its tactic patterns; both operational data and master data may be part of the Published Language and appear in dedicated Bounded Contexts and Aggregates as Entities (see [Vernon 2013]). In DDD, domain event sourcing [Fowler 2006] is the recommended practice to integrate Aggregates (both within the same and in different Bounded Contexts) because it decouples them and allows replaying events up to the current state in case of failures that lead to consistency issues. APIs may support this.
In Principles of Web API Design, James Higginbotham reminds us that “resources are not data models” and “resources are not objects or domain models” [Higginbotham 2021], with resources corresponding to endpoints in our technology-neutral terminology. And “REST was never about CRUD” either. That said, data and domain models may still serve as API design input when taken with a grain of salt.
Principles of Web API Design [Higginbotham 2021] also is the source of the ADDR process that we roughly followed in Part 2.
Table A.9 summarizes the correspondences between ADDR phases/steps and the patterns from this book. It also provides application examples from our sample case (note that some of the pattern selection decisions appeared in the narratives in Chapter 3).
Table A.9 ADDR to Pattern Mapping (with Examples)
Phase/Step | Pattern(s) | Example |
Align | ||
1. Identify Digital Capabilities | Foundation patterns (Chapter 4) | User story about “contact information updates” in Chapter 2 |
2. Capture Activity Steps | n/a | The agile practice of story splitting could be applied; same for event storming (examples available online)* |
Define | ||
3. Identify API Boundaries | Foundation patterns (Chapter 4) | Lakeside Mutual domain model and context map in Chapter 2 |
Responsibility patterns (Chapter 5) | For example, PROCESSING RESOURCE, INFORMATION HOLDER RESOURCE USAGE IN LAKESIDE MUTUAL | |
4. Model API Profiles | Foundation patterns (Chapter 4) | See interludes in Chapter 3 |
Responsibility patterns (Chapter 5) | See interludes in Chapter 3 | |
Initial SERVICE LEVEL AGREEMENT (Chapter 9) | See interludes in Chapter 3 | |
Design | ||
5. High-Level Design | Basic structure patterns (Chapter 4) | See interludes in Chapter 3 |
Element stereotype patterns (Chapter 6) | See interludes in Chapter 3 | |
EMBEDDED ENTITY and LINKED INFORMATION HOLDER patterns (Chapter 7) | The HTTP resource APIs for Lakeside Mutual, implemented in Java, provide examples of pattern use (see Appendix B) | |
Technology realization of patterns (for instance, as HTTP resources) | See Appendix B | |
Refine | ||
6. Refine the Design | Quality patterns (Chapters 6 and 7) | WISH LIST in operations of Customer Information Holder in Lakeside Mutual |
7. Document the API | API DESCRIPTION, RATE LIMIT (Chapter 9) | See OpenAPI snippet in Appendix B for a minimal technical contract |
Evolution patterns such as VERSION IDENTIFIER (Chapter 8) | See sample decisions in Chapter 3 |
More details on the Identify API Boundaries step. Our messages are very much in line with James Higginbotham’s advice; for instance, our patterns help avoid the antipatterns he discusses [Higginbotham 2021, p. 70 ff.]. By considering our end-point role patterns from Chapter 5 when deciding between activity- or data-oriented semantics of endpoints and being aware of the differences in the responsibilities of their operations, antipatterns like the “Mega All-In-One API,” “Overloaded API,” and “Helper API” can be avoided.
More details on the Model API Profiles step. This is an ADDR step in which many of our patterns are eligible. For instance, the LINK ELEMENT pattern and related METADATA ELEMENTS from Chapter 6 may be used to describe the “resource taxonomies” (independent/dependent/associative resources) [Higginbotham 2021, p. 87], and the “operation safety classification” (safe/unsafe/idempotent operations) [p. 91] can be expressed with the operation responsibilities from Chapter 5.
More details on the High-Level Design step. This ADDR step is complementary to our Chapters 4, 5, and 7; the patterns from these chapters fit here. A RATE LIMIT (Chapter 9) can be part of the “API Management Layer.” Deciding whether to include related or nested resources, discussed in the context of “hypermedia serialization” [Higginbotham 2021, p. 127], is covered by our EMBEDDED ENTITY and LINKED INFORMATION HOLDER patterns. Our WISH TEMPLATE pattern provides complementary advice on “query-based APIs.”
More details on the Refine the Design step. Note that optimizing for performance on a platform-neutral level (as our Chapters 6 and 7 patterns do) is not covered as such in ADDR. That said, our Chapters 6 and 7 patterns belong to this phase and step in ADDR. Higginbotham’s process and our patterns complement each other here.
3.136.17.105