API
API Design Patterns
John J. Geewax, 2021
Inhaltsverzeichnis des Buches
- front matter
- foreword
- preface
- acknowledgments
- about this book
- Who should read this book
- How this book is organized: A roadmap
- About the code
- Live book discussion forum
- Other online resources
- about the author
- about the cover illustration
- Part 1 Introduction
- 1 Introduction to APIs
- 1.1 What are web APIs?
- 1.2 Why do APIs matter?
- 1.3 What are resource-oriented APIs?
- 1.4 What makes an API “good”?
- 1.4.1 Operational
- 1.4.2 Expressive
- 1.4.3 Simple
- 1.4.4 Predictable
- Summary
- 2 Introduction to API design patterns
- 2.1 What are API design patterns?
- 2.2 Why are API design patterns important?
- 2.3 Anatomy of an API design pattern
- 2.3.1 Name and synopsis
- 2.3.2 Motivation
- 2.3.3 Overview
- 2.3.4 Implementation
- 2.3.5 Trade-offs
- 2.4 Case study: Twapi, a Twitter-like API
- 2.4.1 Overview
- 2.4.2 Listing messages
- 2.4.3 Exporting data
- Summary
- Part 2 Design principles
- 3 Naming
- 3.1 Why do names matter?
- 3.2 What makes a name “good”?
- 3.2.1 Expressive
- 3.2.2 Simple
- 3.2.3 Predictable
- 3.3 Language, grammar, and syntax
- 3.3.1 Language
- 3.3.2 Grammar
- 3.3.3 Syntax
- 3.4 Context
- 3.5 Data types and units
- 3.6 Case study: What happens when you choose bad names?
- 3.7 Exercises
- Summary
- 4 Resource scope and hierarchy
- 4.1 What is resource layout?
- 4.1.1 Types of relationships
- 4.1.2 Entity relationship diagrams
- 4.2 Choosing the right relationship
- 4.2.1 Do you need a relationship at all?
- 4.2.2 References or in-line data
- 4.2.3 Hierarchy
- 4.3 Anti-patterns
- 4.3.1 Resources for everything
- 4.3.2 Deep hierarchies
- 4.3.3 In-line everything
- 4.4 Exercises
- Summary
- 5 Data types and defaults
- 5.1 Introduction to data types
- 5.1.1 Missing vs. null
- 5.2 Booleans
- 5.3 Numbers
- 5.3.1 Bounds
- 5.3.2 Default values
- 5.3.3 Serialization
- 5.4 Strings
- 5.4.1 Bounds
- 5.4.2 Default values
- 5.4.3 Serialization
- 5.5 Enumerations
- 5.6 Lists
- 5.6.1 Atomicity
- 5.6.2 Bounds
- 5.6.3 Default values
- 5.7 Maps
- 5.7.1 Bounds
- 5.7.2 Default values
- 5.8 Exercises
- Summary
- Part 3 Fundamentals
- 6 Resource identification
- 6.1 What is an identifier?
- 6.2 What makes a good identifier?
- 6.2.1 Easy to use
- 6.2.2 Unique
- 6.2.3 Permanent
- 6.2.4 Fast and easy to generate
- 6.2.5 Unpredictable
- 6.2.6 Readable, shareable, and verifiable
- 6.2.7 Informationally dense
- 6.3 What does a good identifier look like?
- 6.3.1 Data type
- 6.3.2 Character set
- 6.3.3 Identifier format
- 6.3.4 Checksums
- 6.3.5 Resource type
- 6.3.6 Hierarchy and uniqueness scope
- 6.4 Implementation
- 6.4.1 Size
- 6.4.2 Generation
- 6.4.3 Tomb-stoning
- 6.4.4 Checksum
- 6.4.5 Database storage
- 6.5 What about UUIDs?
- 6.6 Exercises
- Summary
- 7 Standard methods
- 7.1 Motivation
- 7.2 Overview
- 7.3 Implementation
- 7.3.1 Which methods should be supported?
- 7.3.2 Idempotence and side effects
- 7.3.3 Get
- 7.3.4 List
- 7.3.5 Create
- 7.3.6 Update
- 7.3.7 Delete
- 7.3.8 Replace
- 7.3.9 Final API definition
- 7.4 Trade-offs
- 7.5 Exercises
- Summary
- 8 Partial updates and retrievals
- 8.1 Motivation
- 8.1.1 Partial retrieval
- 8.1.2 Partial update
- 8.2 Overview
- 8.3 Implementation
- 8.3.1 Transport
- 8.3.2 Maps and nested interfaces
- 8.3.3 Repeated fields
- 8.3.4 Default values
- 8.3.5 Implicit field masks
- 8.3.6 Updating dynamic data structures
- 8.3.7 Invalid fields
- 8.3.8 Final API definition
- 8.4 Trade-offs
- 8.4.1 Universal support
- 8.4.2 Alternative implementations
- 8.5 Exercises
- Summary
- 9 Custom methods
- 9.1 Motivation
- 9.1.1 Why not just standard methods?
- 9.2 Overview
- 9.3 Implementation
- 9.3.1 Side effects
- 9.3.2 Resources vs. collections
- 9.3.3 Stateless custom methods
- 9.3.4 Final API definition
- 9.4 Trade-offs
- 9.5 Exercises
- Summary
- 10 Long-running operations
- 10.1 Motivation
- 10.2 Overview
- 10.3 Implementation
- 10.3.1 What does an LRO look like?
- 10.3.2 Resource hierarchy
- 10.3.3 Resolution
- 10.3.4 Error handling
- 10.3.5 Monitoring progress
- 10.3.6 Canceling operations
- 10.3.7 Pausing and resuming operations
- 10.3.8 Exploring operations
- 10.3.9 Persistence
- 10.3.10 Final API definition
- 10.4 Trade-offs
- 10.5 Exercises
- Summary
- 11 Rerunnable jobs
- 11.1 Motivation
- 11.2 Overview
- 11.3 Implementation
- 11.3.1 Job resources
- 11.3.2 The custom run method
- 11.3.3 Job execution resources
- 11.3.4 Final API definition
- 11.4 Trade-offs
- 11.5 Exercises
- Summary
- Part 4 Resource relationships
- 12 Singleton sub-resources
- 12.1 Motivation
- 12.1.1 Why should we use a singleton sub-resource?
- 12.2 Overview
- 12.3 Implementation
- 12.3.1 Standard methods
- 12.3.2 Resetting
- 12.3.3 Hierarchy
- 12.3.4 Final API definition
- 12.4 Trade-offs
- 12.4.1 Atomicity
- 12.4.2 Exactly one sub-resource
- 12.5 Exercises
- Summary
- 13 Cross references
- 13.1 Motivation
- 13.2 Overview
- 13.3 Implementation
- 13.3.1 Reference field name
- 13.3.2 Data integrity
- 13.3.3 Value vs. reference
- 13.3.4 Final API definition
- 13.4 Trade-offs
- 11.5 Exercises
- Summary
- 14 Association resources
- 14.1 Motivation
- 14.2 Overview
- 14.2.1 Association alias methods
- 14.3 Implementation
- 14.3.1 Naming the association resource
- 14.3.2 Standard method behavior
- 14.3.3 Uniqueness
- 14.3.4 Read-only fields
- 14.3.5 Association alias methods
- 14.3.6 Referential integrity
- 14.3.7 Final API definition
- 14.4 Trade-offs
- 14.4.1 Complexity
- 14.4.2 Separation of associations
- 14.5 Exercises
- Summary
- 15 Add and remove custom methods
- 15.1 Motivation
- 15.2 Overview
- 15.3 Implementation
- 15.3.1 Listing associated resources
- 15.3.2 Data integrity
- 15.3.3 Final API definition
- 15.4 Trade-offs
- 15.4.1 Nonreciprocal relationship
- 15.4.2 Relationship metadata
- 15.5 Exercises
- Summary
- 16 Polymorphism
- 16.1 Motivation
- 16.2 Overview
- 16.3 Implementation
- 16.3.1 Deciding when to use polymorphic resources
- 16.3.2 Polymorphic structure
- 16.3.3 Polymorphic behavior
- 16.3.4 Why not polymorphic methods?
- 16.3.5 Final API definition
- 16.4 Trade-offs
- 16.5 Exercises
- Summary
- Part 5 Collective operations
- 17 Copy and move
- 17.1 Motivation
- 17.2 Overview
- 17.3 Implementation
- 17.3.1 Identifiers
- 17.3.2 Child resources
- 17.3.3 Related resources
- 17.3.4 External data
- 17.3.5 Inherited metadata
- 17.3.6 Atomicity
- 17.3.7 Final API definition
- 17.4 Trade-offs
- 17.5 Exercises
- Summary
- 18 Batch operations
- 18.1 Motivation
- 18.2 Overview
- 18.3 Implementation
- 18.3.1 Atomicity
- 18.3.2 Operation on the collection
- 18.3.3 Ordering of results
- 18.3.4 Common fields
- 18.3.5 Operating across parents
- 18.3.6 Batch Get
- 18.3.7 Batch Delete
- 18.3.8 Batch Create
- 18.3.9 Batch Update
- 18.3.10 Final API definition
- 18.4 Trade-offs
- 18.5 Exercises
- Summary
- 19 Criteria-based deletion
- 19.1 Motivation
- 19.2 Overview
- 19.3 Implementation
- 19.3.1 Filtering results
- 19.3.2 Validation only by default
- 19.3.3 Result count
- 19.3.4 Result sample set
- 19.3.5 Consistency
- 19.3.6 Final API definition
- 19.4 Trade-offs
- 19.5 Exercises
- Summary
- 20 Anonymous writes
- 20.1 Motivation
- 20.2 Overview
- 20.3 Implementation
- 20.3.1 Consistency
- 20.3.2 Final API definition
- 20.4 Trade-offs
- 20.5 Exercises
- Summary
- 21 Pagination
- 21.1 Motivation
- 21.2 Overview
- 21.3 Implementation
- 21.3.1 Page size
- 21.3.2 Page tokens
- 21.3.3 Total count
- 21.3.4 Paging inside resources
- 21.3.5 Final API definition
- 21.4 Trade-offs
- 21.4.1 Bi-directional paging
- 21.4.2 Arbitrary windows
- 21.5 Anti-pattern: Offsets and limits
- 21.6 Exercises
- Summary
- 22 Filtering
- 22.1 Motivation
- 22.2 Overview
- 22.3 Implementation
- 22.3.1 Structure
- 22.3.2 Filter syntax and behavior
- 22.3.3 Final API definition
- 22.4 Trade-offs
- 22.5 Exercises
- Summary
- 23 Importing and exporting
- 23.1 Motivation
- 23.2 Overview
- 23.3 Implementation
- 23.3.1 Import and export methods
- 23.3.2 Interacting with storage systems
- 23.3.3 Converting between resources and bytes
- 23.3.4 Consistency
- 23.3.5 Identifiers and collisions
- 23.3.6 Handling related resources
- 23.3.7 Failures and retries
- 23.3.8 Filtering and field masks
- 23.3.9 Final API definition
- 23.4 Trade-offs
- 23.5 Exercises
- Summary
- Part 6 Safety and security
- 24 Versioning and compatibility
- 24.1 Motivation
- 24.2 Overview
- 24.2.1 What is compatibility?
- 24.2.2 Defining backward compatibility
- 24.3 Implementation
- 24.3.1 Perpetual stability
- 24.3.2 Agile instability
- 24.3.3 Semantic versioning
- 24.4 Trade-offs
- 24.4.1 Granularity vs. simplicity
- 24.4.2 Stability vs. new functionality
- 24.4.3 Happiness vs. ubiquity
- 24.5 Exercises
- Summary
- 25 Soft deletion
- 25.1 Motivation
- 25.2 Overview
- 25.3 Implementation
- 25.3.1 Deleted designation
- 25.3.2 Modifying standard methods
- 25.3.3 Undeleting
- 25.3.4 Expunging
- 25.3.5 Expiration
- 25.3.6 Referential integrity
- 25.3.7 Effects on other methods
- 25.3.8 Adding soft delete across versions
- 25.3.9 Final API definition
- 25.4 Trade-offs
- 25.5 Exercises
- Summary
- 26 Request deduplication
- 26.1 Motivation
- 26.2 Overview
- 26.3 Implementation
- 26.3.1 Request identifier
- 26.3.2 Response caching
- 26.3.3 Consistency
- 26.3.4 Request ID collisions
- 26.3.5 Cache expiration
- 26.3.6 Final API definition
- 26.4 Trade-offs
- 26.5 Exercises
- Summary
- 27 Request validation
- 27.1 Motivation
- 27.2 Overview
- 27.3 Implementation
- 27.3.1 External dependencies
- 27.3.2 Special side effects
- 27.3.3 Final API definition
- 27.4 Trade-offs
- 27.5 Exercises
- Summary
- 28 Resource revisions
- 28.1 Motivation
- 28.2 Overview
- 28.3 Implementation
- 28.3.1 Revision identifiers
- 28.3.2 Creating revisions
- 28.3.3 Retrieving specific revisions
- 28.3.4 Listing revisions
- 28.3.5 Restoring a previous revision
- 28.3.6 Deleting revisions
- 28.3.7 Handling child resources
- 28.3.8 Final API definition
- 28.4 Trade-offs
- 28.5 Exercises
- Summary
- 29 Request retrial
- 29.1 Motivation
- 29.2 Overview
- 29.2.1 Client-side retry timing
- 29.2.2 Server-specified retry timing
- 29.3 Implementation
- 29.3.1 Retry eligibility
- 29.3.2 Exponential back-off
- 29.3.3 Retry After
- 29.3.4 Final API definition
- 29.4 Trade-offs
- 29.5 Exercises
- Summary
- 30 Request authentication
- 30.1 Motivation
- 30.1.1 Origin
- 30.1.2 Integrity
- 30.1.3 Nonrepudiation
- 30.2 Overview
- 30.3 Implementation
- 30.3.1 Credential generation
- 30.3.2 Registration and credential exchange
- 30.3.3 Generating and verifying raw signatures
- 30.3.4 Request fingerprinting
- 30.3.5 Including the signature
- 30.3.6 Authenticating requests
- 30.3.7 Final API definition
- 30.4 Trade-offs
- 30.5 Exercises
- Summary
- index