1
0
mirror of https://github.com/twirl/The-API-Book.git synced 2025-10-30 23:37:47 +02:00

The book completely rebuilt with book-builder v1

This commit is contained in:
Sergey Konstantinov
2025-01-21 23:39:37 +02:00
parent 4db5d4d014
commit 862784ffb1
160 changed files with 2791 additions and 3876 deletions

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@@ -80,7 +80,7 @@ a.share-linkedin {
a.twitter,
a.share-twitter {
background-image: url(twitter.svg);
background-image: url(x.png);
width: 1.392em;
}

View File

@@ -1,16 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Logo" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 248 204" style="enable-background:new 0 0 248 204;" xml:space="preserve">
<style type="text/css">
.st0{fill:#1D9BF0;}
</style>
<g id="Logo_1_">
<path id="white_background" class="st0" d="M221.95,51.29c0.15,2.17,0.15,4.34,0.15,6.53c0,66.73-50.8,143.69-143.69,143.69v-0.04
C50.97,201.51,24.1,193.65,1,178.83c3.99,0.48,8,0.72,12.02,0.73c22.74,0.02,44.83-7.61,62.72-21.66
c-21.61-0.41-40.56-14.5-47.18-35.07c7.57,1.46,15.37,1.16,22.8-0.87C27.8,117.2,10.85,96.5,10.85,72.46c0-0.22,0-0.43,0-0.64
c7.02,3.91,14.88,6.08,22.92,6.32C11.58,63.31,4.74,33.79,18.14,10.71c25.64,31.55,63.47,50.73,104.08,52.76
c-4.07-17.54,1.49-35.92,14.61-48.25c20.34-19.12,52.33-18.14,71.45,2.19c11.31-2.23,22.15-6.38,32.07-12.26
c-3.77,11.69-11.66,21.62-22.2,27.93c10.01-1.18,19.79-3.86,29-7.95C240.37,35.29,231.83,44.14,221.95,51.29z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

BIN
docs/assets/x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

View File

@@ -1,51 +1,50 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" type="image/png" href="assets/favicon.png" />
<title>
Sergey Konstantinov. The API
</title>
<meta
name="description"
content="API-first development is one of the hottest technical topics nowadays since many companies have started to realize that APIs serves as a multiplier to their opportunities — but it amplifies the design mistakes as well. This book is written to share expertise and describe best practices in designing and developing APIs. It comprises six sections dedicated to the following topics: the API design, API patterns, maintaining backward compatibility, HTTP APIs & the REST architectural principles, SDKs and UI libraries, API product management."
/>
<meta property="og:type" content="article" />
<meta
property="og:title"
content="Sergey Konstantinov. The API"
/>
<meta
property="og:description"
content="API-first development is one of the hottest technical topics nowadays since many companies have started to realize that APIs serves as a multiplier to their opportunities — but it amplifies the design mistakes as well. This book is written to share expertise and describe best practices in designing and developing APIs. It comprises six sections dedicated to the following topics: the API design, API patterns, maintaining backward compatibility, HTTP APIs & the REST architectural principles, SDKs and UI libraries, API product management."
/>
<meta property="og:image" content="assets/header.png" />
<meta
property="og:url"
content="https://github.com/twirl/The-API-Book"
/>
<link rel="stylesheet" href="assets/fonts.css"/>
<link rel="stylesheet" href="assets/landing.css"/>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" type="image/png" href="assets/favicon.png" />
<title>
Sergey Konstantinov. The API
</title>
<meta
name="description"
content="API-first development is one of the hottest technical topics nowadays since many companies have started to realize that APIs serves as a multiplier to their opportunities — but it amplifies the design mistakes as well. This book is written to share expertise and describe best practices in designing and developing APIs. It comprises six sections dedicated to the following topics: the API design, API patterns, maintaining backward compatibility, HTTP APIs & the REST architectural principles, SDKs and UI libraries, API product management."
/>
<meta property="og:type" content="article" />
<meta
property="og:title"
content="Sergey Konstantinov. The API"
/>
<meta
property="og:description"
content="API-first development is one of the hottest technical topics nowadays since many companies have started to realize that APIs serves as a multiplier to their opportunities — but it amplifies the design mistakes as well. This book is written to share expertise and describe best practices in designing and developing APIs. It comprises six sections dedicated to the following topics: the API design, API patterns, maintaining backward compatibility, HTTP APIs & the REST architectural principles, SDKs and UI libraries, API product management."
/>
<meta property="og:image" content="assets/header.png" />
<meta
property="og:url"
content="https://github.com/twirl/The-API-Book"
/>
<link rel="stylesheet" href="assets/fonts.css"/>
<link rel="stylesheet" href="assets/landing.css"/>
</head>
<body>
<nav>
<img
class="header"
src="assets/header.jpg"
alt="Sergey Konstantinov. The API"
/><br />
<header>
<h1>Sergey Konstantinov<br/><span class="title">The API</span></h1>
<h2>Free e-book</h2>
</header>
<br />Subscribe for updates on <a class="github" href="https://github.com/twirl/The-API-Book"></a>
<br/>Follow me on <a class="linkedin" href="https://www.linkedin.com/in/twirl/"></a> · <a class="twitter" href="https://twitter.com/blogovodoved"></a> · <a class="substack" href="https://twirl.substack.com/">Substack</a>
<br />Support this work: buy it on <a class="kindle" href="https://www.amazon.com/gp/product/B09RHH44S5/">Amazon Kindle</a> · <a class="apple" href="http://books.apple.com/us/book/id6467567700">Apple Books</a>
<br />Share: <a class="share share-facebook" href="https://www.facebook.com/sharer.php?u=https%3A%2F%2Ftwirl.github.io%2FThe-API-Book%2F" target="_blank"></a> · <a class="share share-twitter" href="https://twitter.com/intent/tweet?text=The%20API%20by%20Sergey%20Konstantinov%20%E2%80%94%20a%20book%20about%20designing%20APIs%2C%20extending%20them%20and%20finding%20a%20proper%20place%20in%20the%20market&url=https%3A%2F%2Ftwirl.github.io%2FThe-API-Book%2F&hashtags=API%2CTheAPIBook&via=blogovodoved" target="_blank"></a> · <a class="share share-linkedin" href="https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Ftwirl.github.io%2FThe-API-Book%2F" target="_blank"></a> · <a class="share share-reddit" href="https://www.reddit.com/submit?url=https%3A%2F%2Ftwirl.github.io%2FThe-API-Book%2F&title=The%20API%20by%20Sergey%20Konstantinov%20%E2%80%94%20a%20book%20about%20designing%20APIs%2C%20extending%20them%20and%20finding%20a%20proper%20place%20in%20the%20market" target="_blank"></a><br/>⚙️⚙️⚙️
</nav>
<p>API-first development is one of the hottest technical topics nowadays since many companies have started to realize that APIs serves as a multiplier to their opportunities — but it amplifies the design mistakes as well.</p>
<nav>
<img
class="header"
src="assets/header.jpg"
alt="Sergey Konstantinov. The API"
/><br />
<header>
<h1>Sergey Konstantinov<br/><span class="title">The API</span></h1>
<h2>Free e-book</h2>
</header>
<br />Subscribe for updates on <a class="github" href="https://github.com/twirl/The-API-Book"></a>
<br/>Follow me on <a class="linkedin" href="https://www.linkedin.com/in/twirl/"></a> · <a class="twitter" href="https://x.com/blogovodoved"></a> · <a class="substack" href="https://twirl.substack.com/">Substack</a>
<br />Support this work: buy it on <a class="kindle" href="https://www.amazon.com/gp/product/B09RHH44S5/">Amazon Kindle</a> · <a class="apple" href="http://books.apple.com/us/book/id6467567700">Apple Books</a>
<br />Share: <a class="share share-facebook" href="https://www.facebook.com/sharer.php?u=https%3A%2F%2Ftwirl.github.io%2FThe-API-Book%2F" target="_blank"></a> · <a class="share share-twitter" href="https://x.com/intent/tweet?url=https%3A%2F%2Ftwirl.github.io%2FThe-API-Book%2F" target="_blank"></a> · <a class="share share-linkedin" href="https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Ftwirl.github.io%2FThe-API-Book%2F" target="_blank"></a> · <a class="share share-reddit" href="https://www.reddit.com/submit?url=https%3A%2F%2Ftwirl.github.io%2FThe-API-Book%2F&title=The%20API%20by%20Sergey%20Konstantinov%20%E2%80%94%20a%20book%20about%20designing%20APIs%2C%20extending%20them%20and%20finding%20a%20proper%20place%20in%20the%20market" target="_blank"></a><br/>⚙️⚙️⚙️
</nav>
<p>API-first development is one of the hottest technical topics nowadays since many companies have started to realize that APIs serves as a multiplier to their opportunities — but it amplifies the design mistakes as well.</p>
<p>This book is written to share expertise and describe best practices in designing and developing APIs. It comprises six sections dedicated to the following topics:</p>
<ul><li>— The API design</li>
<li>— API patterns</li>
@@ -54,122 +53,121 @@
<li>— SDKs and UI libraries</li>
<li>— API product management.</ul>
<p>Illustration &amp; inspiration: <a href="https://www.instagram.com/art.mari.ka/">art.mari.ka</a>.</p>
<p>You might download ‘The API’ in <a href="API.en.pdf">PDF</a> / <a href="API.en.epub">EPUB</a> or <a href="API.en.html">read it online</a>.
</p>
<h3>Table of Contents</h3>
<ul class="toc"><li>
<h4><a href="API.en.html#section-1">Introduction</a></h4>
<p>You might download ‘The API’ in <a href="API.en.pdf">PDF</a> / <a href="API.en.epub">EPUB</a> or <a href="API.en.html">read it online</a>.
</p>
<h3>Table of Contents</h3>
<ul class="toc"><li>
<h4><a href="API.en.html#introduction">Introduction</a></h4>
<ul class="section">
<li><a href="API.en.html#intro-structure">Chapter 1. On the Structure of This Book</a></li>
<li><a href="API.en.html#intro-api-definition">Chapter 2. The API Definition</a></li>
<li><a href="API.en.html#intro-api-quality">Chapter 3. API Quality Criteria</a></li>
<li><a href="API.en.html#intro-api-choosing-solutions">Chapter 4. Choosing Solutions for API Development</a></li>
<li><a href="API.en.html#intro-api-first-approach">Chapter 5. The API-First Approach</a></li>
<li><a href="API.en.html#intro-back-compat">Chapter 6. On Backward Compatibility</a></li>
<li><a href="API.en.html#intro-versioning">Chapter 7. On Versioning</a></li>
<li><a href="API.en.html#intro-terms-notation">Chapter 8. Terms and Notation Keys</a></li>
<li><a href="API.en.html#intro-structure">Chapter 1. On the Structure of This Book</a></li>
<li><a href="API.en.html#intro-api-definition">Chapter 2. The API Definition</a></li>
<li><a href="API.en.html#intro-api-quality">Chapter 3. API Quality Criteria</a></li>
<li><a href="API.en.html#intro-api-choosing-solutions">Chapter 4. Choosing Solutions for API Development</a></li>
<li><a href="API.en.html#intro-api-first-approach">Chapter 5. The API-First Approach</a></li>
<li><a href="API.en.html#intro-back-compat">Chapter 6. On Backward Compatibility</a></li>
<li><a href="API.en.html#intro-versioning">Chapter 7. On Versioning</a></li>
<li><a href="API.en.html#intro-terms-notation">Chapter 8. Terms and Notation Keys</a></li>
</ul>
</li>
<li>
<h4><a href="API.en.html#section-2">Section I. The API Design</a></h4>
<h4><a href="API.en.html#section-i-the-api-design">Section I. The API Design</a></h4>
<ul class="section">
<li><a href="API.en.html#api-design-context-pyramid">Chapter 9. The API Contexts Pyramid</a></li>
<li><a href="API.en.html#api-design-defining-field">Chapter 10. Defining an Application Field</a></li>
<li><a href="API.en.html#api-design-separating-abstractions">Chapter 11. Separating Abstraction Levels</a></li>
<li><a href="API.en.html#api-design-isolating-responsibility">Chapter 12. Isolating Responsibility Areas</a></li>
<li><a href="API.en.html#api-design-describing-interfaces">Chapter 13. Describing Final Interfaces</a></li>
<li><a href="API.en.html#api-design-annex">Chapter 14. Annex to Section I. Generic API Example</a></li>
<li><a href="API.en.html#api-design-context-pyramid">Chapter 9. The API Contexts Pyramid</a></li>
<li><a href="API.en.html#api-design-defining-field">Chapter 10. Defining an Application Field</a></li>
<li><a href="API.en.html#api-design-separating-abstractions">Chapter 11. Separating Abstraction Levels</a></li>
<li><a href="API.en.html#api-design-isolating-responsibility">Chapter 12. Isolating Responsibility Areas</a></li>
<li><a href="API.en.html#api-design-describing-interfaces">Chapter 13. Describing Final Interfaces</a></li>
<li><a href="API.en.html#api-design-annex">Chapter 14. Annex to Section I. Generic API Example</a></li>
</ul>
</li>
<li>
<h4><a href="API.en.html#section-3">Section II. The API Patterns</a></h4>
<h4><a href="API.en.html#section-ii-the-api-patterns">Section II. The API Patterns</a></h4>
<ul class="section">
<li><a href="API.en.html#api-patterns-context">Chapter 15. On Design Patterns in the API Context</a></li>
<li><a href="API.en.html#api-patterns-aa">Chapter 16. Authenticating Partners and Authorizing API Calls</a></li>
<li><a href="API.en.html#api-patterns-sync-strategies">Chapter 17. Synchronization Strategies</a></li>
<li><a href="API.en.html#api-patterns-weak-consistency">Chapter 18. Eventual Consistency</a></li>
<li><a href="API.en.html#api-patterns-async">Chapter 19. Asynchronicity and Time Management</a></li>
<li><a href="API.en.html#api-patterns-lists">Chapter 20. Lists and Accessing Them</a></li>
<li><a href="API.en.html#api-patterns-push-vs-poll">Chapter 21. Bidirectional Data Flows. Push and Poll Models</a></li>
<li><a href="API.en.html#api-patterns-async-event-processing">Chapter 22. Multiplexing Notifications. Asynchronous Event Processing</a></li>
<li><a href="API.en.html#api-patterns-atomicity">Chapter 23. Atomicity of Bulk Changes</a></li>
<li><a href="API.en.html#api-patterns-partial-updates">Chapter 24. Partial Updates</a></li>
<li><a href="API.en.html#api-patterns-degrading">Chapter 25. Degradation and Predictability</a></li>
<li><a href="API.en.html#api-patterns-context">Chapter 15. On Design Patterns in the API Context</a></li>
<li><a href="API.en.html#api-patterns-aa">Chapter 16. Authenticating Partners and Authorizing API Calls</a></li>
<li><a href="API.en.html#api-patterns-sync-strategies">Chapter 17. Synchronization Strategies</a></li>
<li><a href="API.en.html#api-patterns-weak-consistency">Chapter 18. Eventual Consistency</a></li>
<li><a href="API.en.html#api-patterns-async">Chapter 19. Asynchronicity and Time Management</a></li>
<li><a href="API.en.html#api-patterns-lists">Chapter 20. Lists and Accessing Them</a></li>
<li><a href="API.en.html#api-patterns-push-vs-poll">Chapter 21. Bidirectional Data Flows. Push and Poll Models</a></li>
<li><a href="API.en.html#api-patterns-async-event-processing">Chapter 22. Multiplexing Notifications. Asynchronous Event Processing</a></li>
<li><a href="API.en.html#api-patterns-atomicity">Chapter 23. Atomicity of Bulk Changes</a></li>
<li><a href="API.en.html#api-patterns-partial-updates">Chapter 24. Partial Updates</a></li>
<li><a href="API.en.html#api-patterns-degrading">Chapter 25. Degradation and Predictability</a></li>
</ul>
</li>
<li>
<h4><a href="API.en.html#section-4">Section III. The Backward Compatibility</a></h4>
<h4><a href="API.en.html#section-iii-the-backward-compatibility">Section III. The Backward Compatibility</a></h4>
<ul class="section">
<li><a href="API.en.html#back-compat-statement">Chapter 26. The Backward Compatibility Problem Statement</a></li>
<li><a href="API.en.html#back-compat-iceberg-waterline">Chapter 27. On the Waterline of the Iceberg</a></li>
<li><a href="API.en.html#back-compat-abstracting-extending">Chapter 28. Extending through Abstracting</a></li>
<li><a href="API.en.html#back-compat-strong-coupling">Chapter 29. Strong Coupling and Related Problems</a></li>
<li><a href="API.en.html#back-compat-weak-coupling">Chapter 30. Weak Coupling</a></li>
<li><a href="API.en.html#back-compat-universal-interfaces">Chapter 31. Interfaces as a Universal Pattern</a></li>
<li><a href="API.en.html#back-compat-serenity-notepad">Chapter 32. The Serenity Notepad</a></li>
<li><a href="API.en.html#back-compat-statement">Chapter 26. The Backward Compatibility Problem Statement</a></li>
<li><a href="API.en.html#back-compat-iceberg-waterline">Chapter 27. On the Waterline of the Iceberg</a></li>
<li><a href="API.en.html#back-compat-abstracting-extending">Chapter 28. Extending through Abstracting</a></li>
<li><a href="API.en.html#back-compat-strong-coupling">Chapter 29. Strong Coupling and Related Problems</a></li>
<li><a href="API.en.html#back-compat-weak-coupling">Chapter 30. Weak Coupling</a></li>
<li><a href="API.en.html#back-compat-universal-interfaces">Chapter 31. Interfaces as a Universal Pattern</a></li>
<li><a href="API.en.html#back-compat-serenity-notepad">Chapter 32. The Serenity Notepad</a></li>
</ul>
</li>
<li>
<h4><a href="API.en.html#section-5">Section IV. HTTP APIs & the REST Architectural Principles</a></h4>
<h4><a href="API.en.html#section-iv-http-apis-the-rest-architectural-principles">Section IV. HTTP APIs &amp; the REST Architectural Principles</a></h4>
<ul class="section">
<li><a href="API.en.html#http-api-concepts">Chapter 33. On the HTTP API Concept. Paradigms of Developing Client-Server Communication</a></li>
<li><a href="API.en.html#http-api-pros-and-cons">Chapter 34. Advantages and Disadvantages of HTTP APIs Compared to Alternative Technologies</a></li>
<li><a href="API.en.html#http-api-rest-myth">Chapter 35. The REST Myth</a></li>
<li><a href="API.en.html#http-api-requests-semantics">Chapter 36. Components of an HTTP Request and Their Semantics</a></li>
<li><a href="API.en.html#http-api-rest-organizing">Chapter 37. Organizing HTTP APIs Based on the REST Principles</a></li>
<li><a href="API.en.html#http-api-urls-crud">Chapter 38. Designing a Nomenclature of URLs. The CRUD Operations</a></li>
<li><a href="API.en.html#http-api-errors">Chapter 39. Working with HTTP API Errors</a></li>
<li><a href="API.en.html#http-api-final-recommendations">Chapter 40. Final Provisions and General Recommendations</a></li>
<li><a href="API.en.html#http-api-concepts">Chapter 33. On the HTTP API Concept. Paradigms of Developing Client-Server Communication</a></li>
<li><a href="API.en.html#http-api-pros-and-cons">Chapter 34. Advantages and Disadvantages of HTTP APIs Compared to Alternative Technologies</a></li>
<li><a href="API.en.html#http-api-rest-myth">Chapter 35. The REST Myth</a></li>
<li><a href="API.en.html#http-api-requests-semantics">Chapter 36. Components of an HTTP Request and Their Semantics</a></li>
<li><a href="API.en.html#http-api-rest-organizing">Chapter 37. Organizing HTTP APIs Based on the REST Principles</a></li>
<li><a href="API.en.html#http-api-urls-crud">Chapter 38. Designing a Nomenclature of URLs. The CRUD Operations</a></li>
<li><a href="API.en.html#http-api-errors">Chapter 39. Working with HTTP API Errors</a></li>
<li><a href="API.en.html#http-api-final-recommendations">Chapter 40. Final Provisions and General Recommendations</a></li>
</ul>
</li>
<li>
<h4><a href="API.en.html#section-6">Section V. SDKs & UI Libraries</a></h4>
<h4><a href="API.en.html#section-v-sdks-ui-libraries">Section V. SDKs &amp; UI Libraries</a></h4>
<ul class="section">
<li><a href="API.en.html#sdk-toc-technology-overview">Chapter 41. On Terminology. An Overview of Technologies for UI Development</a></li>
<li><a href="API.en.html#sdk-problems-solutions">Chapter 42. SDKs: Problems and Solutions</a></li>
<li><a href="API.en.html#sdk-ui-components">Chapter 43. Problems of Introducing UI Components</a></li>
<li><a href="API.en.html#sdk-decomposing">Chapter 44. Decomposing UI Components</a></li>
<li><a href="API.en.html#sdk-mv-frameworks">Chapter 45. The MV* Frameworks</a></li>
<li><a href="API.en.html#sdk-backend-driven">Chapter 46. The Backend-Driven UI</a></li>
<li><a href="API.en.html#sdk-shared-resources">Chapter 47. Shared Resources and Asynchronous Locks</a></li>
<li><a href="API.en.html#sdk-computed-properties">Chapter 48. Computed Properties</a></li>
<li><a href="API.en.html#sdk-conclusion">Chapter 49. Conclusion</a></li>
<li><a href="API.en.html#sdk-toc-technology-overview">Chapter 41. On Terminology. An Overview of Technologies for UI Development</a></li>
<li><a href="API.en.html#sdk-problems-solutions">Chapter 42. SDKs: Problems and Solutions</a></li>
<li><a href="API.en.html#sdk-ui-components">Chapter 43. Problems of Introducing UI Components</a></li>
<li><a href="API.en.html#sdk-decomposing">Chapter 44. Decomposing UI Components</a></li>
<li><a href="API.en.html#sdk-mv-frameworks">Chapter 45. The MV* Frameworks</a></li>
<li><a href="API.en.html#sdk-backend-driven">Chapter 46. The Backend-Driven UI</a></li>
<li><a href="API.en.html#sdk-shared-resources">Chapter 47. Shared Resources and Asynchronous Locks</a></li>
<li><a href="API.en.html#sdk-computed-properties">Chapter 48. Computed Properties</a></li>
<li><a href="API.en.html#sdk-conclusion">Chapter 49. Conclusion</a></li>
</ul>
</li>
<li>
<h4><a href="API.en.html#section-7">Section VI. The API Product</a></h4>
<h4><a href="API.en.html#section-vi-the-api-product">Section VI. The API Product</a></h4>
<ul class="section">
<li><a href="API.en.html#api-product">Chapter 50. The API as a Product</a></li>
<li><a href="API.en.html#api-product-business-models">Chapter 51. API Business Models</a></li>
<li><a href="API.en.html#api-product-vision">Chapter 52. Developing a Product Vision</a></li>
<li><a href="API.en.html#api-product-devrel">Chapter 53. Communicating with Developers</a></li>
<li><a href="API.en.html#api-product-business-comms">Chapter 54. Communicating with Business Owners</a></li>
<li><a href="API.en.html#api-product-lineup">Chapter 55. An API Services Lineup</a></li>
<li><a href="API.en.html#api-product-kpi">Chapter 56. API Key Performance Indicators</a></li>
<li><a href="API.en.html#api-product-antifraud">Chapter 57. Identifying Users and Preventing Fraud</a></li>
<li><a href="API.en.html#api-product-tos-violations">Chapter 58. The Technical Means of Preventing ToS Violations</a></li>
<li><a href="API.en.html#api-product-customer-support">Chapter 59. Supporting Customers</a></li>
<li><a href="API.en.html#api-product-documentation">Chapter 60. Documentation</a></li>
<li><a href="API.en.html#api-product-testing">Chapter 61. Testing Environments</a></li>
<li><a href="API.en.html#api-product-expectations">Chapter 62. Managing Expectations</a></li>
<li><a href="API.en.html#api-product">Chapter 50. The API as a Product</a></li>
<li><a href="API.en.html#api-product-business-models">Chapter 51. API Business Models</a></li>
<li><a href="API.en.html#api-product-vision">Chapter 52. Developing a Product Vision</a></li>
<li><a href="API.en.html#api-product-devrel">Chapter 53. Communicating with Developers</a></li>
<li><a href="API.en.html#api-product-business-comms">Chapter 54. Communicating with Business Owners</a></li>
<li><a href="API.en.html#api-product-lineup">Chapter 55. An API Services Lineup</a></li>
<li><a href="API.en.html#api-product-kpi">Chapter 56. API Key Performance Indicators</a></li>
<li><a href="API.en.html#api-product-antifraud">Chapter 57. Identifying Users and Preventing Fraud</a></li>
<li><a href="API.en.html#api-product-tos-violations">Chapter 58. The Technical Means of Preventing ToS Violations</a></li>
<li><a href="API.en.html#api-product-customer-support">Chapter 59. Supporting Customers</a></li>
<li><a href="API.en.html#api-product-documentation">Chapter 60. Documentation</a></li>
<li><a href="API.en.html#api-product-testing">Chapter 61. Testing Environments</a></li>
<li><a href="API.en.html#api-product-expectations">Chapter 62. Managing Expectations</a></li>
</ul>
</li>
<li>
<h4>Live Examples</h3>
<ul class="section"><li><a href="examples/01. Decomposing UI Components">Decomposing UI Components</a></li>
<li><h4>Live Examples</h3>
<ul class="section"><li><a href="examples/01. Decomposing UI Components/index.html">Decomposing UI Components</a></li>
</ul>
</li>
</ul>
<p>This book is distributed under the <a href="https://creativecommons.org/licenses/by-nc/4.0/">Creative Commons Attribution-NonCommercial 4.0 International licence</a>.</p>
<p>Source code available at <a href="https://github.com/twirl/The-API-Book">github.com/twirl/The-API-Book</a></p>
<h3><a name="about-author">About the Author</a></h3>
<section class="about-me">
<aside><img src="https://konstantinov.cc/static/me.png"/><br/>Photo by <a href="https://linkedin.com/in/zloylos/">Denis Hananein</a></aside>
<div class="content">
<p>Sergey Konstantinov has been working with APIs for over a decade. He began his career as a software engineer in the Maps API division at Yandex and eventually became the head of the service. In this role, he was responsible for both technical architecture and product management.</p>
<p>This book is distributed under the <a href="https://creativecommons.org/licenses/by-nc/4.0/">Creative Commons Attribution-NonCommercial 4.0 International licence</a>.</p>
<p>Source code available at <a href="https://github.com/twirl/The-API-Book">github.com/twirl/The-API-Book</a></p>
<h3><a name="about-author">About the Author</a></h3>
<section class="about-me">
<aside><img src="https://konstantinov.cc/static/me.png"/><br/>Photo by <a href="https://linkedin.com/in/zloylos/">Denis Hananein</a></aside>
<div class="content">
<p>Sergey Konstantinov has been working with APIs for over a decade. He began his career as a software engineer in the Maps API division at Yandex and eventually became the head of the service. In this role, he was responsible for both technical architecture and product management.</p>
<p>During this tenure, Sergey gained unique experience in building world-class APIs with a daily audience of tens of millions, planning roadmaps for such a service, and delivering numerous public speeches. Additionaly, he served as a member of the W3C Technical Architecture Group for a year and a half.</p>
<p>After being nine years in Maps, Sergey transitioned to technical lead roles in other departments and companies. In these positions, he led integration efforts and was responsible for the technical architecture of entire business units. Currently, Sergey resides in Tallinn, Estonia, and works as a staff software engineer at Bolt.</p></div>
</section>
<p>Книгу «API» можно <a href="index.ru.html">читать по-русски</a>.</p>
</section>
<p>Книгу «API» можно <a href="index.ru.html">читать по-русски</a>.</p>
</body>
</html>

View File

@@ -1,51 +1,50 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" type="image/png" href="assets/favicon.png" />
<title>
Сергей Константинов. API
</title>
<meta
name="description"
content="Разработка API — особый навык: API является как мультипликатором ваших возможностей, так и мультипликатором ваших ошибок. Эта книга написана для того, чтобы поделиться опытом и изложить лучшие практики разработки API. Книга состоит из шести разделов, посвящённых проектированию API, паттернам дизайна API, поддержанию обратной совместимости, HTTP API и архитектурным принципам REST, SDK и UI-библиотекам, продуктовому управлению API."
/>
<meta property="og:type" content="article" />
<meta
property="og:title"
content="Сергей Константинов. API"
/>
<meta
property="og:description"
content="Разработка API — особый навык: API является как мультипликатором ваших возможностей, так и мультипликатором ваших ошибок. Эта книга написана для того, чтобы поделиться опытом и изложить лучшие практики разработки API. Книга состоит из шести разделов, посвящённых проектированию API, паттернам дизайна API, поддержанию обратной совместимости, HTTP API и архитектурным принципам REST, SDK и UI-библиотекам, продуктовому управлению API."
/>
<meta property="og:image" content="assets/header.png" />
<meta
property="og:url"
content="https://github.com/twirl/The-API-Book"
/>
<link rel="stylesheet" href="assets/fonts.css"/>
<link rel="stylesheet" href="assets/landing.css"/>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" type="image/png" href="assets/favicon.png" />
<title>
Сергей Константинов. API
</title>
<meta
name="description"
content="Разработка API — особый навык: API является как мультипликатором ваших возможностей, так и мультипликатором ваших ошибок. Эта книга написана для того, чтобы поделиться опытом и изложить лучшие практики разработки API. Книга состоит из шести разделов, посвящённых проектированию API, паттернам дизайна API, поддержанию обратной совместимости, HTTP API и архитектурным принципам REST, SDK и UI-библиотекам, продуктовому управлению API."
/>
<meta property="og:type" content="article" />
<meta
property="og:title"
content="Сергей Константинов. API"
/>
<meta
property="og:description"
content="Разработка API — особый навык: API является как мультипликатором ваших возможностей, так и мультипликатором ваших ошибок. Эта книга написана для того, чтобы поделиться опытом и изложить лучшие практики разработки API. Книга состоит из шести разделов, посвящённых проектированию API, паттернам дизайна API, поддержанию обратной совместимости, HTTP API и архитектурным принципам REST, SDK и UI-библиотекам, продуктовому управлению API."
/>
<meta property="og:image" content="assets/header.png" />
<meta
property="og:url"
content="https://github.com/twirl/The-API-Book"
/>
<link rel="stylesheet" href="assets/fonts.css"/>
<link rel="stylesheet" href="assets/landing.css"/>
</head>
<body>
<nav>
<img
class="header"
src="assets/header.jpg"
alt="Сергей Константинов. API"
/><br />
<header>
<h1>Сергей Константинов<br/><span class="title">API</span></h1>
</header>
<br />Подпишитесь на обновления на <a class="habr" href="https://habr.com/ru/users/forgotten/">Хабре</a>
<br/>Follow me on <a class="linkedin" href="https://www.linkedin.com/in/twirl/"></a> · <a class="twitter" href="https://twitter.com/blogovodoved"></a> · <a class="substack" href="https://twirl.substack.com/">Substack</a>
<br />Поддержите эту работу: купите книгу на <a class="kindle" href="https://www.amazon.com/gp/product/B09RHH44S5/">Amazon Kindle</a> · <a class="apple" href="http://books.apple.com/us/book/id6467567700">Apple Books</a>
<br />Поделиться: <a class="share share-facebook" href="https://www.facebook.com/sharer.php?u=https%3A%2F%2Ftwirl.github.io%2FThe-API-Book%2Findex.ru.html" target="_blank"></a> · <a class="share share-twitter" href="https://twitter.com/intent/tweet?text=%C2%ABAPI%C2%BB%20%D0%A1%D0%B5%D1%80%D0%B3%D0%B5%D1%8F%20%D0%9A%D0%BE%D0%BD%D1%81%D1%82%D0%B0%D0%BD%D1%82%D0%B8%D0%BD%D0%BE%D0%B2%D0%B0%20%E2%80%94%20%D0%BA%D0%BD%D0%B8%D0%B3%D0%B0%20%D0%BE%20%D0%B4%D0%B8%D0%B7%D0%B0%D0%B9%D0%BD%D0%B5%20API%20%D0%B8%20%D0%B5%D0%B3%D0%BE%20%D0%BF%D1%80%D0%BE%D0%B4%D1%83%D0%BA%D1%82%D0%BE%D0%B2%D0%BE%D0%BC%20%D0%B8%20%D1%82%D0%B5%D1%85%D0%BD%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%BC%20%D1%80%D0%B0%D0%B7%D0%B2%D0%B8%D1%82%D0%B8%D0%B8&url=https%3A%2F%2Ftwirl.github.io%2FThe-API-Book%2Findex.ru.html&hashtags=API%2CTheAPIBook&via=blogovodoved" target="_blank"></a> · <a class="share share-linkedin" href="https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Ftwirl.github.io%2FThe-API-Book%2Findex.ru.html" target="_blank"></a> · <a class="share share-reddit" href="https://www.reddit.com/submit?url=https%3A%2F%2Ftwirl.github.io%2FThe-API-Book%2Findex.ru.html&title=%C2%ABAPI%C2%BB%20%D0%A1%D0%B5%D1%80%D0%B3%D0%B5%D1%8F%20%D0%9A%D0%BE%D0%BD%D1%81%D1%82%D0%B0%D0%BD%D1%82%D0%B8%D0%BD%D0%BE%D0%B2%D0%B0%20%E2%80%94%20%D0%BA%D0%BD%D0%B8%D0%B3%D0%B0%20%D0%BE%20%D0%B4%D0%B8%D0%B7%D0%B0%D0%B9%D0%BD%D0%B5%20API%20%D0%B8%20%D0%B5%D0%B3%D0%BE%20%D0%BF%D1%80%D0%BE%D0%B4%D1%83%D0%BA%D1%82%D0%BE%D0%B2%D0%BE%D0%BC%20%D0%B8%20%D1%82%D0%B5%D1%85%D0%BD%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%BC%20%D1%80%D0%B0%D0%B7%D0%B2%D0%B8%D1%82%D0%B8%D0%B8" target="_blank"></a><br/>⚙️⚙️⚙️
</nav>
<p>«API-first» подход — одна из самых горячих горячих тем в разработке программного обеспечения в наше время. Многие компании начали понимать, что API выступает мультипликатором их возможностей — но также умножает и допущенные ошибки.</p>
<nav>
<img
class="header"
src="assets/header.jpg"
alt="Сергей Константинов. API"
/><br />
<header>
<h1>Сергей Константинов<br/><span class="title">API</span></h1>
</header>
<br />Подпишитесь на обновления на <a class="habr" href="https://habr.com/ru/users/forgotten/">Хабре</a>
<br/>Follow me on <a class="linkedin" href="https://www.linkedin.com/in/twirl/"></a> · <a class="twitter" href="https://x.com/blogovodoved"></a> · <a class="substack" href="https://twirl.substack.com/">Substack</a>
<br />Поддержите эту работу: купите книгу на <a class="kindle" href="https://www.amazon.com/gp/product/B09RHH44S5/">Amazon Kindle</a> · <a class="apple" href="http://books.apple.com/us/book/id6467567700">Apple Books</a>
<br />Поделиться: <a class="share share-facebook" href="https://www.facebook.com/sharer.php?u=https%3A%2F%2Ftwirl.github.io%2FThe-API-Book%2Findex.ru.html" target="_blank"></a> · <a class="share share-twitter" href="https://x.com/intent/tweet?url=https%3A%2F%2Ftwirl.github.io%2FThe-API-Book%2Findex.ru.html" target="_blank"></a> · <a class="share share-linkedin" href="https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Ftwirl.github.io%2FThe-API-Book%2Findex.ru.html" target="_blank"></a> · <a class="share share-reddit" href="https://www.reddit.com/submit?url=https%3A%2F%2Ftwirl.github.io%2FThe-API-Book%2Findex.ru.html&title=%C2%ABAPI%C2%BB%20%D0%A1%D0%B5%D1%80%D0%B3%D0%B5%D1%8F%20%D0%9A%D0%BE%D0%BD%D1%81%D1%82%D0%B0%D0%BD%D1%82%D0%B8%D0%BD%D0%BE%D0%B2%D0%B0%20%E2%80%94%20%D0%BA%D0%BD%D0%B8%D0%B3%D0%B0%20%D0%BE%20%D0%B4%D0%B8%D0%B7%D0%B0%D0%B9%D0%BD%D0%B5%20API%20%D0%B8%20%D0%B5%D0%B3%D0%BE%20%D0%BF%D1%80%D0%BE%D0%B4%D1%83%D0%BA%D1%82%D0%BE%D0%B2%D0%BE%D0%BC%20%D0%B8%20%D1%82%D0%B5%D1%85%D0%BD%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%BC%20%D1%80%D0%B0%D0%B7%D0%B2%D0%B8%D1%82%D0%B8%D0%B8" target="_blank"></a><br/>⚙️⚙️⚙️
</nav>
<p>«API-first» подход — одна из самых горячих горячих тем в разработке программного обеспечения в наше время. Многие компании начали понимать, что API выступает мультипликатором их возможностей — но также умножает и допущенные ошибки.</p>
<p>Эта книга написана для того, чтобы поделиться опытом и изложить лучшие практики разработки API. Книга состоит из шести разделов, посвящённых:</p>
<ul><li>— проектированию API,</li>
<li>— паттернам дизайна API,</li>
@@ -54,121 +53,120 @@
<li>— SDK и UI-библиотекам,</li>
<li>— продуктовому управлению API.</li></ul>
<p>Иллюстрации и вдохновение: Maria Konstantinova &middot; <a href="https://www.instagram.com/art.mari.ka/">art.mari.ka</a>.</p>
<p>Вы можете прочитать онлайн-версию «The API».</p>
<h3>Содержание</h3>
<ul class="toc"><li>
<h4><a href="API.ru.html#section-1">Введение</a></h4>
<p>Вы можете прочитать онлайн-версию «The API».</p>
<h3>Содержание</h3>
<ul class="toc"><li>
<h4><a href="API.ru.html#-">Введение</a></h4>
<ul class="section">
<li><a href="API.ru.html#intro-structure">Глава 1. О структуре этой книги</a></li>
<li><a href="API.ru.html#intro-api-definition">Глава 2. Определение API</a></li>
<li><a href="API.ru.html#intro-api-quality">Глава 3. Критерии качества API</a></li>
<li><a href="API.ru.html#intro-api-choosing-solutions">Глава 4. Выбор подхода к разработке API</a></li>
<li><a href="API.ru.html#intro-api-first-approach">Глава 5. API-first подход</a></li>
<li><a href="API.ru.html#intro-back-compat">Глава 6. Обратная совместимость</a></li>
<li><a href="API.ru.html#intro-versioning">Глава 7. О версионировании</a></li>
<li><a href="API.ru.html#intro-terms-notation">Глава 8. Условные обозначения и терминология</a></li>
<li><a href="API.ru.html#intro-structure">Глава 1. О структуре этой книги</a></li>
<li><a href="API.ru.html#intro-api-definition">Глава 2. Определение API</a></li>
<li><a href="API.ru.html#intro-api-quality">Глава 3. Критерии качества API</a></li>
<li><a href="API.ru.html#intro-api-choosing-solutions">Глава 4. Выбор подхода к разработке API</a></li>
<li><a href="API.ru.html#intro-api-first-approach">Глава 5. API-first подход</a></li>
<li><a href="API.ru.html#intro-back-compat">Глава 6. Обратная совместимость</a></li>
<li><a href="API.ru.html#intro-versioning">Глава 7. О версионировании</a></li>
<li><a href="API.ru.html#intro-terms-notation">Глава 8. Условные обозначения и терминология</a></li>
</ul>
</li>
<li>
<h4><a href="API.ru.html#section-2">Раздел I. Проектирование API</a></h4>
<h4><a href="API.ru.html#-i-api">Раздел I. Проектирование API</a></h4>
<ul class="section">
<li><a href="API.ru.html#api-design-context-pyramid">Глава 9. Пирамида контекстов API</a></li>
<li><a href="API.ru.html#api-design-defining-field">Глава 10. Определение области применения</a></li>
<li><a href="API.ru.html#api-design-separating-abstractions">Глава 11. Разделение уровней абстракции</a></li>
<li><a href="API.ru.html#api-design-isolating-responsibility">Глава 12. Разграничение областей ответственности</a></li>
<li><a href="API.ru.html#api-design-describing-interfaces">Глава 13. Описание конечных интерфейсов</a></li>
<li><a href="API.ru.html#api-design-annex">Глава 14. Приложение к разделу I. Модельный API</a></li>
<li><a href="API.ru.html#api-design-context-pyramid">Глава 9. Пирамида контекстов API</a></li>
<li><a href="API.ru.html#api-design-defining-field">Глава 10. Определение области применения</a></li>
<li><a href="API.ru.html#api-design-separating-abstractions">Глава 11. Разделение уровней абстракции</a></li>
<li><a href="API.ru.html#api-design-isolating-responsibility">Глава 12. Разграничение областей ответственности</a></li>
<li><a href="API.ru.html#api-design-describing-interfaces">Глава 13. Описание конечных интерфейсов</a></li>
<li><a href="API.ru.html#api-design-annex">Глава 14. Приложение к разделу I. Модельный API</a></li>
</ul>
</li>
<li>
<h4><a href="API.ru.html#section-3">Раздел II. Паттерны дизайна API</a></h4>
<h4><a href="API.ru.html#-ii-api">Раздел II. Паттерны дизайна API</a></h4>
<ul class="section">
<li><a href="API.ru.html#chapter-15">Глава 15. О паттернах проектирования в контексте API</a></li>
<li><a href="API.ru.html#api-patterns-aa">Глава 16. Аутентификация партнёров и авторизация вызовов API</a></li>
<li><a href="API.ru.html#api-patterns-sync-strategies">Глава 17. Стратегии синхронизации</a></li>
<li><a href="API.ru.html#api-patterns-weak-consistency">Глава 18. Слабая консистентность</a></li>
<li><a href="API.ru.html#api-patterns-async">Глава 19. Асинхронность и управление временем</a></li>
<li><a href="API.ru.html#api-patterns-lists">Глава 20. Списки и организация доступа к ним</a></li>
<li><a href="API.ru.html#api-patterns-push-vs-poll">Глава 21. Двунаправленные потоки данных. Push и poll-модели</a></li>
<li><a href="API.ru.html#api-patterns-async-event-processing">Глава 22. Мультиплексирование сообщений. Асинхронная обработка событий</a></li>
<li><a href="API.ru.html#api-patterns-atomicity">Глава 23. Атомарность массовых изменений</a></li>
<li><a href="API.ru.html#api-patterns-partial-updates">Глава 24. Частичные обновления</a></li>
<li><a href="API.ru.html#api-patterns-degrading">Глава 25. Деградация и предсказуемость</a></li>
<li><a href="API.ru.html#api-patterns-context">Глава 15. О паттернах проектирования в контексте API</a></li>
<li><a href="API.ru.html#api-patterns-aa">Глава 16. Аутентификация партнёров и авторизация вызовов API</a></li>
<li><a href="API.ru.html#api-patterns-sync-strategies">Глава 17. Стратегии синхронизации</a></li>
<li><a href="API.ru.html#api-patterns-weak-consistency">Глава 18. Слабая консистентность</a></li>
<li><a href="API.ru.html#api-patterns-async">Глава 19. Асинхронность и управление временем</a></li>
<li><a href="API.ru.html#api-patterns-lists">Глава 20. Списки и организация доступа к ним</a></li>
<li><a href="API.ru.html#api-patterns-push-vs-poll">Глава 21. Двунаправленные потоки данных. Push и poll-модели</a></li>
<li><a href="API.ru.html#api-patterns-async-event-processing">Глава 22. Мультиплексирование сообщений. Асинхронная обработка событий</a></li>
<li><a href="API.ru.html#api-patterns-atomicity">Глава 23. Атомарность массовых изменений</a></li>
<li><a href="API.ru.html#api-patterns-partial-updates">Глава 24. Частичные обновления</a></li>
<li><a href="API.ru.html#api-patterns-degrading">Глава 25. Деградация и предсказуемость</a></li>
</ul>
</li>
<li>
<h4><a href="API.ru.html#section-4">Раздел III. Обратная совместимость</a></h4>
<h4><a href="API.ru.html#-iii-">Раздел III. Обратная совместимость</a></h4>
<ul class="section">
<li><a href="API.ru.html#back-compat-statement">Глава 26. Постановка проблемы обратной совместимости</a></li>
<li><a href="API.ru.html#back-compat-iceberg-waterline">Глава 27. О ватерлинии айсберга</a></li>
<li><a href="API.ru.html#back-compat-abstracting-extending">Глава 28. Расширение через абстрагирование</a></li>
<li><a href="API.ru.html#back-compat-strong-coupling">Глава 29. Сильная связность и сопутствующие проблемы</a></li>
<li><a href="API.ru.html#back-compat-weak-coupling">Глава 30. Слабая связность</a></li>
<li><a href="API.ru.html#back-compat-universal-interfaces">Глава 31. Интерфейсы как универсальный паттерн</a></li>
<li><a href="API.ru.html#back-compat-serenity-notepad">Глава 32. Блокнот душевного покоя</a></li>
<li><a href="API.ru.html#back-compat-statement">Глава 26. Постановка проблемы обратной совместимости</a></li>
<li><a href="API.ru.html#back-compat-iceberg-waterline">Глава 27. О ватерлинии айсберга</a></li>
<li><a href="API.ru.html#back-compat-abstracting-extending">Глава 28. Расширение через абстрагирование</a></li>
<li><a href="API.ru.html#back-compat-strong-coupling">Глава 29. Сильная связность и сопутствующие проблемы</a></li>
<li><a href="API.ru.html#back-compat-weak-coupling">Глава 30. Слабая связность</a></li>
<li><a href="API.ru.html#back-compat-universal-interfaces">Глава 31. Интерфейсы как универсальный паттерн</a></li>
<li><a href="API.ru.html#back-compat-serenity-notepad">Глава 32. Блокнот душевного покоя</a></li>
</ul>
</li>
<li>
<h4><a href="API.ru.html#section-5">Раздел IV. HTTP API и архитектурные принципы REST</a></h4>
<h4><a href="API.ru.html#-iv-http-api-rest">Раздел IV. HTTP API и архитектурные принципы REST</a></h4>
<ul class="section">
<li><a href="API.ru.html#http-api-concepts">Глава 33. О концепции HTTP API. Парадигмы разработки клиент-серверного взаимодействия</a></li>
<li><a href="API.ru.html#http-api-pros-and-cons">Глава 34. Преимущества и недостатки HTTP API в сравнении с альтернативными технологиями</a></li>
<li><a href="API.ru.html#http-api-rest-myth">Глава 35. Мифология REST</a></li>
<li><a href="API.ru.html#http-api-requests-semantics">Глава 36. Составляющие HTTP запросов и их семантика</a></li>
<li><a href="API.ru.html#http-api-rest-organizing">Глава 37. Организация HTTP API согласно принципам REST</a></li>
<li><a href="API.ru.html#http-api-urls-crud">Глава 38. Разработка номенклатуры URL ресурсов. CRUD-операции</a></li>
<li><a href="API.ru.html#http-api-errors">Глава 39. Работа с ошибками в HTTP API</a></li>
<li><a href="API.ru.html#http-api-final-recommendations">Глава 40. Заключительные положения и общие рекомендации</a></li>
<li><a href="API.ru.html#http-api-concepts">Глава 33. О концепции HTTP API. Парадигмы разработки клиент-серверного взаимодействия</a></li>
<li><a href="API.ru.html#http-api-pros-and-cons">Глава 34. Преимущества и недостатки HTTP API в сравнении с альтернативными технологиями</a></li>
<li><a href="API.ru.html#http-api-rest-myth">Глава 35. Мифология REST</a></li>
<li><a href="API.ru.html#http-api-requests-semantics">Глава 36. Составляющие HTTP запросов и их семантика</a></li>
<li><a href="API.ru.html#http-api-rest-organizing">Глава 37. Организация HTTP API согласно принципам REST</a></li>
<li><a href="API.ru.html#http-api-urls-crud">Глава 38. Разработка номенклатуры URL ресурсов. CRUD-операции</a></li>
<li><a href="API.ru.html#http-api-errors">Глава 39. Работа с ошибками в HTTP API</a></li>
<li><a href="API.ru.html#http-api-final-recommendations">Глава 40. Заключительные положения и общие рекомендации</a></li>
</ul>
</li>
<li>
<h4><a href="API.ru.html#section-6">Раздел V. SDK и UI</a></h4>
<h4><a href="API.ru.html#-v-sdk-ui-">Раздел V. SDK и UI-библиотеки</a></h4>
<ul class="section">
<li><a href="API.ru.html#sdk-toc-technology-overview">Глава 41. Терминология. Обзор технологий разработки SDK</a></li>
<li><a href="API.ru.html#sdk-problems-solutions">Глава 42. SDK: проблемы и решения</a></li>
<li><a href="API.ru.html#sdk-ui-components">Глава 43. Проблемы встраивания UI-компонентов</a></li>
<li><a href="API.ru.html#sdk-decomposing">Глава 44. Декомпозиция UI-компонентов</a></li>
<li><a href="API.ru.html#sdk-mv-frameworks">Глава 45. MV*-фреймворки</a></li>
<li><a href="API.ru.html#sdk-backend-driven">Глава 46. Backend-Driven UI</a></li>
<li><a href="API.ru.html#sdk-shared-resources">Глава 47. Разделяемые ресурсы и асинхронные блокировки</a></li>
<li><a href="API.ru.html#sdk-computed-properties">Глава 48. Вычисляемые свойства</a></li>
<li><a href="API.ru.html#sdk-conclusion">Глава 49. Заключение</a></li>
<li><a href="API.ru.html#sdk-toc-technology-overview">Глава 41. Терминология. Обзор технологий разработки SDK</a></li>
<li><a href="API.ru.html#sdk-problems-solutions">Глава 42. SDK: проблемы и решения</a></li>
<li><a href="API.ru.html#sdk-ui-components">Глава 43. Проблемы встраивания UI-компонентов</a></li>
<li><a href="API.ru.html#sdk-decomposing">Глава 44. Декомпозиция UI-компонентов</a></li>
<li><a href="API.ru.html#sdk-mv-frameworks">Глава 45. MV*-фреймворки</a></li>
<li><a href="API.ru.html#sdk-backend-driven">Глава 46. Backend-Driven UI</a></li>
<li><a href="API.ru.html#sdk-shared-resources">Глава 47. Разделяемые ресурсы и асинхронные блокировки</a></li>
<li><a href="API.ru.html#sdk-computed-properties">Глава 48. Вычисляемые свойства</a></li>
<li><a href="API.ru.html#sdk-conclusion">Глава 49. Заключение</a></li>
</ul>
</li>
<li>
<h4><a href="API.ru.html#section-7">Раздел VI. API как продукт</a></h4>
<h4><a href="API.ru.html#-vi-api-">Раздел VI. API как продукт</a></h4>
<ul class="section">
<li><a href="API.ru.html#api-product">Глава 50. Продукт API</a></li>
<li><a href="API.ru.html#api-product-business-models">Глава 51. Бизнес-модели API</a></li>
<li><a href="API.ru.html#api-product-vision">Глава 52. Формирование продуктового видения</a></li>
<li><a href="API.ru.html#api-product-devrel">Глава 53. Взаимодействие с разработчиками</a></li>
<li><a href="API.ru.html#api-product-business-comms">Глава 54. Взаимодействие с бизнес-аудиторией</a></li>
<li><a href="API.ru.html#api-product-lineup">Глава 55. Линейка сервисов API</a></li>
<li><a href="API.ru.html#api-product-kpi">Глава 56. Ключевые показатели эффективности API</a></li>
<li><a href="API.ru.html#api-product-antifraud">Глава 57. Идентификация пользователей и борьба с фродом</a></li>
<li><a href="API.ru.html#api-product-tos-violations">Глава 58. Технические способы борьбы с несанкционированным доступом к API</a></li>
<li><a href="API.ru.html#api-product-customer-support">Глава 59. Поддержка пользователей API</a></li>
<li><a href="API.ru.html#api-product-documentation">Глава 60. Документация</a></li>
<li><a href="API.ru.html#api-product-testing">Глава 61. Тестовая среда</a></li>
<li><a href="API.ru.html#api-product-expectations">Глава 62. Управление ожиданиями</a></li>
<li><a href="API.ru.html#api-product">Глава 50. Продукт API</a></li>
<li><a href="API.ru.html#api-product-business-models">Глава 51. Бизнес-модели API</a></li>
<li><a href="API.ru.html#api-product-vision">Глава 52. Формирование продуктового видения</a></li>
<li><a href="API.ru.html#api-product-devrel">Глава 53. Взаимодействие с разработчиками</a></li>
<li><a href="API.ru.html#api-product-business-comms">Глава 54. Взаимодействие с бизнес-аудиторией</a></li>
<li><a href="API.ru.html#api-product-lineup">Глава 55. Линейка сервисов API</a></li>
<li><a href="API.ru.html#api-product-kpi">Глава 56. Ключевые показатели эффективности API</a></li>
<li><a href="API.ru.html#api-product-antifraud">Глава 57. Идентификация пользователей и борьба с фродом</a></li>
<li><a href="API.ru.html#api-product-tos-violations">Глава 58. Технические способы борьбы с несанкционированным доступом к API</a></li>
<li><a href="API.ru.html#api-product-customer-support">Глава 59. Поддержка пользователей API</a></li>
<li><a href="API.ru.html#api-product-documentation">Глава 60. Документация</a></li>
<li><a href="API.ru.html#api-product-testing">Глава 61. Тестовая среда</a></li>
<li><a href="API.ru.html#api-product-expectations">Глава 62. Управление ожиданиями</a></li>
</ul>
</li>
<li>
<h4>Интерактивные примеры</h3>
<ul class="section"><li><a href="examples/01. Decomposing UI Components">Decomposing UI Components</a></li>
<li><h4>Интерактивные примеры</h3>
<ul class="section"><li><a href="examples/01. Decomposing UI Components/index.html">Decomposing UI Components</a></li>
</ul>
</li>
</ul>
<p>Это произведение доступно по <a href="https://creativecommons.org/licenses/by-nc/4.0/">лицензии Creative Commons «Attribution-NonCommercial» («Атрибуция — Некоммерческое использование») 4.0 Всемирная</a>.</p>
<p>Исходный код доступен на <a href="https://github.com/twirl/The-API-Book">github.com/twirl/The-API-Book</a></p>
<h3><a name="about-author">Об авторе</a></h3>
<section class="about-me">
<aside><img src="https://konstantinov.cc/static/me.png"/><br/>Фото: <a href="https://linkedin.com/in/zloylos/">Denis Hananein</a></aside>
<div class="content">
<p>Сергей Константинов работает с API уже больше десятилетия. Он начинал свою карьеру разработчиком в подразделении API Яндекс.Карт, и со временем стал руководителем всего сервиса, отвечая и за техническую, и за продуктовую составляющую.</p>
<p>Это произведение доступно по <a href="https://creativecommons.org/licenses/by-nc/4.0/">лицензии Creative Commons «Attribution-NonCommercial» («Атрибуция — Некоммерческое использование») 4.0 Всемирная</a>.</p>
<p>Исходный код доступен на <a href="https://github.com/twirl/The-API-Book">github.com/twirl/The-API-Book</a></p>
<h3><a name="about-author">Об авторе</a></h3>
<section class="about-me">
<aside><img src="https://konstantinov.cc/static/me.png"/><br/>Фото: <a href="https://linkedin.com/in/zloylos/">Denis Hananein</a></aside>
<div class="content">
<p>Сергей Константинов работает с API уже больше десятилетия. Он начинал свою карьеру разработчиком в подразделении API Яндекс.Карт, и со временем стал руководителем всего сервиса, отвечая и за техническую, и за продуктовую составляющую.</p>
<p>За это время Сергей получил уникальный опыт построения API мирового уровня с дневной аудиторией в десятки миллионов человек, планирования роадмапов для такого продукта и многочисленных публичных выступлений. Он также проработал полтора года в составе Технической архитектурной группы W3C.</p>
<p>После девяти лет в Картах Сергей переключился на технические роли в других департаментах и компаниях, занимаясь интеграционными проектами и будучи ответственным за техническую архитектуру целых продуктов компании. Сегодня Сергей живёт в Таллинне, Эстония, и работает ведущим инженером в компании Bolt.</p></div>
</section>
<p>You might also <a href="index.html">read ‘The API’ in English</a>.</p>
</section>
<p>You might also <a href="index.html">read ‘The API’ in English</a>.</p>
</body>
</html>

View File

@@ -7,7 +7,7 @@
"version": "3.0.0",
"devDependencies": {
"@jest/globals": "^29.6.4",
"@twirl/book-builder": "0.0.28",
"@twirl/book-builder": "1.0.3",
"@types/jest": "^29.5.4",
"express": "^4.19.2",
"jest": "^29.6.4",
@@ -21,8 +21,8 @@
"webpack": "^5.88.2"
},
"scripts": {
"build": "node scripts/build.mjs",
"build-samples": "node scripts/build.mjs en,ru epub 21-22 --sample",
"build": "tsx scripts/build.ts",
"build-landing": "node scripts/build-landing.mjs",
"build-v1": "node scripts/build-v1.mjs",
"build-graphs": "node scripts/build-graphs.mjs",
"build-examples": "node scripts/build-examples.js \"docs/examples/01. Decomposing UI Components\"",

View File

@@ -1,27 +0,0 @@
import { resolve } from 'path';
import { readdirSync, writeFileSync, statSync } from 'fs';
const examplesDir = resolve('docs', 'examples');
export const buildLanding = (structure, lang, l10n, templates) => {
const examples = readdirSync(examplesDir);
const landingHtml = templates.landing({
structure: structure,
examples: examples.reduce((examples, folder) => {
const fullName = resolve(examplesDir, folder);
if (statSync(fullName).isDirectory()) {
const name = folder.match(/^\d+\. (.+)$/)[1];
examples.push({
name,
path: `examples/${folder}`
});
}
return examples;
}, []),
l10n: l10n[lang],
lang,
templates
});
writeFileSync(resolve('docs', l10n[lang].landingFile), landingHtml);
};

182
scripts/build-landing.ts Normal file
View File

@@ -0,0 +1,182 @@
import { resolve } from 'node:path';
import { readdir, writeFile } from 'node:fs/promises';
import { statSync } from 'node:fs';
import {
Path,
Structure
} from '@twirl/book-builder';
import {
CustomTemplates,
Example,
ExtraStrings,
linker,
shareLink,
toc
} from '../src/templates';
export const buildLanding = async ({
structure,
examplesDir,
lang,
outFile,
strings,
templates
}: LandingParameters) => {
const examples = await readdir(examplesDir);
const landingHtml = await landingTemplate(
{
structure,
strings,
lang,
templates
},
examples.reduce((examples: Example[], folder) => {
const fullName = resolve(examplesDir, folder);
if (statSync(fullName).isDirectory()) {
const name = folder.match(/^\d+\. (.+)$/)![1];
examples.push({
name,
path: `examples/${folder}` as Path
});
}
return examples;
}, [])
);
await writeFile(outFile, landingHtml);
};
export const landingTemplate = async (
{
structure,
strings,
lang,
templates
}: Omit<LandingParameters, 'examplesDir' | 'outFile'>,
examples: Example[]
) => {
const link = linker(strings, lang);
return `<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" type="image/png" href="assets/favicon.png" />
<title>
${strings.author}. ${strings.title}
</title>
<meta
name="description"
content="${strings.description}"
/>
<meta property="og:type" content="article" />
<meta
property="og:title"
content="${strings.author}. ${strings.title}"
/>
<meta
property="og:description"
content="${strings.description}"
/>
<meta property="og:image" content="assets/header.png" />
<meta
property="og:url"
content="${strings.links.githubHref}"
/>
<link rel="stylesheet" href="assets/fonts.css"/>
<link rel="stylesheet" href="assets/landing.css"/>
</head>
<body>
<nav>
<img
class="header"
src="assets/header.jpg"
alt="${strings.author}. ${strings.title}"
/><br />
<header>
<h1>${strings.author}<br/><span class="title">${
strings.title
}</span></h1>
${
strings.landing.subTitle
? `<h2>${strings.landing.subTitle}</h2>`
: ''
}
</header>
<br />${strings.landing.subscribeOn} ${strings.landing.updates
.map(
(source) =>
`<a class="${source}" href="${
strings.links[source + 'Href']
}">${strings.links[source + 'Tag'] || ''}</a>`
)
.join(' · ')}
${
strings.landing.follow && strings.landing.follow.length
? `<br/>${strings.landing.followOn} ${strings.landing.follow
.map(
(source) =>
`<a class="${source}" href="${
strings.links[source + 'Href']
}">${strings.links[source + 'Tag'] || ''}</a>`
)
.join(' · ')}`
: ''
}
<br />${strings.landing.supportThisWork} ${strings.landing.support
.map(
(source) =>
`<a class="${source}" href="${
strings.links[source + 'Href']
}">${strings.links[source + 'Tag'] || ''}</a>`
)
.join(' · ')}
<br />${strings.sidePanel.shareTo}: ${strings.sidePanel.services
.map(
({ key, link }) =>
`<a class="share share-${key}" href="${shareLink(
link,
strings.sidePanel.shareParameters
)}" target="_blank"></a>`
)
.join(' · ')}<br/>⚙️⚙️⚙️
</nav>
${strings.landing.content.join('\n')}
${
strings.landing.download
? `<p>${strings.landing.download} <a href="${link(
undefined,
'pdf'
)}">PDF</a> / <a href="${link(undefined, 'epub')}">EPUB</a> ${
strings.landing.or
} <a href="${link()}">${strings.landing.readOnline}</a>.
</p>`
: `<p>${strings.landing.readOnline}.</p>`
}
<h3>${strings.toc}</h3>
${await toc({ structure, strings, templates, lang }, examples)}
<p>${strings.landing.license}</p>
<p>${strings.sourceCodeAt} <a href="${strings.links.githubHref}">${
strings.links.githubString
}</a></p>
<h3><a name="about-author">${strings.aboutMe.title}</a></h3>
<section class="about-me">
<aside><img src="https://konstantinov.cc/static/me.png"/><br/>${
strings.aboutMe.imageCredit
}</aside>
<div class="content">
${strings.aboutMe.content.join('\n')}</div>
</section>
${strings.landing.footer.join('\n')}
</body>
</html>`;
};
export interface LandingParameters {
structure: Structure;
examplesDir: Path;
lang: string;
outFile: Path;
strings: ExtraStrings;
templates: CustomTemplates;
}

View File

@@ -1,163 +0,0 @@
import { readFileSync, readdirSync, unlinkSync } from 'fs';
import { resolve as pathResolve } from 'path';
import { init, plugins } from '@twirl/book-builder';
import { templates } from '../src/templates.mjs';
import { apiHighlight } from '../src/api-highlight.mjs';
import { buildLanding } from './build-landing.mjs';
const { flags, args } = process.argv.slice(2).reduce(
({ flags, args }, v) => {
switch (v) {
case '--no-cache':
flags.noCache = true;
break;
case '--sample':
flags.sample = true;
}
if (!v.startsWith('--')) {
args.push(v);
}
return { flags, args };
},
{
args: [],
flags: {}
}
);
const l10n = {
en: JSON.parse(readFileSync('./src/en/l10n.json', 'utf-8')),
ru: JSON.parse(readFileSync('./src/ru/l10n.json', 'utf-8'))
};
const css = ['fonts', 'common', 'screen', 'print', 'page', 'epub'].reduce(
(css, file) => {
css[file] = readFileSync(`src/css/${file}.css`).toString('utf-8');
return css;
},
{}
);
const targetCss = {
html: [css.fonts, css.common, css.screen, css.print],
pdf: [css.fonts, css.common, css.print],
epub: [css.common, css.epub]
};
const extraCss = {
html: css.page,
pdf: css.page
};
const langsToBuild = (args[0] && args[0].split(',').map((s) => s.trim())) || [
'ru',
'en'
];
const targets = (
(args[1] && args[1].split(',')) || ['html', 'pdf', 'epub', 'landing']
).reduce((targets, arg) => {
targets[arg.trim()] = true;
return targets;
}, {});
const chapters = args[2];
const noCache = flags.noCache;
if (flags.noCache) {
clean();
}
console.log(`Building langs: ${langsToBuild.join(', ')}`);
(async () => {
for (const lang of langsToBuild) {
await init({
lang,
l10n: l10n[lang],
basePath: pathResolve(`src`),
path: pathResolve(`src/${lang}/clean-copy`),
templates,
pipeline: {
css: {
beforeAll: [
plugins.css.backgroundImageDataUri,
plugins.css.fontFaceDataUri
]
},
ast: {
preProcess: [
plugins.ast.h3ToTitle,
plugins.ast.h5Counter,
plugins.ast.aImg,
plugins.ast.imgSrcResolve,
plugins.ast.highlighter({
languages: ['javascript', 'typescript', 'json'],
languageDefinitions: {
json: apiHighlight
}
}),
plugins.ast.ref,
plugins.ast.ghTableFix,
plugins.ast.stat
]
},
htmlSourceValidator: {
validator: 'WHATWG',
ignore: [
'heading-level',
'no-raw-characters',
'wcag/h37',
'no-missing-references'
]
},
html: {
postProcess: [plugins.html.imgDataUri]
}
},
chapters,
noCache,
sample: flags.sample,
cover: 'src/cover_embed.png'
}).then(async (builder) => {
for (const target of Object.keys(targets)) {
if (target !== 'landing') {
await builder.build(
target,
pathResolve(
'docs',
`${l10n[lang].file}.${lang}${
flags.sample ? '.sample' : ''
}.${target}`
),
{
css: targetCss[target],
extraCss: extraCss[target]
}
);
console.log(
`Finished lang=${lang} target=${target}\n${Object.entries(
{
sources: 'Sources',
references: 'references',
words: 'words',
characters: 'characters'
}
)
.map(([k, v]) => `${v}: ${builder.structure[k]}`)
.join(', ')}`
);
} else {
buildLanding(builder.structure, lang, l10n, templates);
}
}
});
}
})();
function clean() {
const tmpDir = pathResolve('.', '.tmp');
const files = readdirSync(tmpDir);
for (const fileName of files) {
const file = pathResolve(tmpDir, fileName);
unlinkSync(file);
}
}

327
scripts/build.ts Normal file
View File

@@ -0,0 +1,327 @@
import { readFile } from 'node:fs/promises';
import { resolve } from 'node:path';
import {
Bibliography,
init,
Path,
plugins,
LogLevel,
applyAstPluginToStructure,
L10n,
} from '@twirl/book-builder';
import { buildLanding } from './build-landing';
import { CustomTemplates, ExtraStrings } from '../src/templates';
const SRC = resolve('./src') as Path;
const LOCALES: { [language: string]: string } = {
en: 'en-US',
ru: 'ru-RU'
};
const { args, flags } = process.argv.slice(2).reduce(
({ args, flags }, v) => {
if (v.startsWith('--')) {
flags.add(
v.slice(2).replace(/-\w/g, (m) => m.charAt(1).toUpperCase())
);
} else {
args.push(v);
}
return { args, flags };
},
{ args: [] as string[], flags: new Set<string>() }
);
async function initBuilder(
language: string,
locale: string,
strings: ExtraStrings,
target: 'epub' | 'html' | 'pdf'
): Promise<{
bookBuilder: Awaited<ReturnType<typeof init>>;
templates: CustomTemplates;
l10n: L10n<CustomTemplates, ExtraStrings>;
}> {
const bookBuilder = await init({
source: {
dir: resolve(SRC, language, 'clean-copy') as Path,
base: SRC
},
options: {
tmpDir: resolve('./.tmp') as Path,
noCache: flags.has('noCache'),
purgeCache: flags.has('purgeCache'),
logLevel: LogLevel.DEBUG
}
});
const templates = new CustomTemplates(
target,
bookBuilder.context,
language,
locale,
{
...strings,
favicon: await bookBuilder.toDataUri(strings.favicon)
},
{ anchorLink: 'anchor', externalLink: 'external' }
);
return {
bookBuilder,
templates,
l10n: { language, locale, strings, templates }
};
}
const builders = {
html: async ({
outFile,
language,
locale,
strings,
bibliography,
cssFiles
}) => {
const { bookBuilder, templates, l10n } = await initBuilder(
language,
locale,
strings,
'html'
);
await bookBuilder.build<CustomTemplates, ExtraStrings, 'html'>(
'html',
l10n,
{
structure: {
plugins: [
plugins.structure.h3Title(),
plugins.structure.h5Counter(),
plugins.structure.highlighter({
languages: ['javascript', 'typescript', 'json']
}),
plugins.structure.hoistSingleChapters(),
plugins.structure.tableOfContents(),
plugins.structure.imprintPages(
templates.htmlImprintPages(),
'front-page'
),
plugins.structure.reference({
bibliography
}),
plugins.structure.imgDataUri(),
plugins.structure.aImg()
]
},
html: {
plugins: [plugins.html.validator()]
},
css: {
plugins: [plugins.css.dataUri()]
}
},
{
css: [cssFiles.FONTS, cssFiles.COMMON, cssFiles.SCREEN].join(
'\n'
),
outFile
}
);
},
epub: async ({
outFile,
language,
locale,
strings,
bibliography,
cssFiles,
baseDir
}) => {
const { bookBuilder, templates, l10n } = await initBuilder(
language,
locale,
strings,
'epub'
);
await bookBuilder.build<CustomTemplates, ExtraStrings, 'epub'>(
'epub',
l10n,
{
structure: {
plugins: [
plugins.structure.h3Title(),
plugins.structure.h5Counter(),
plugins.structure.highlighter({
languages: ['javascript', 'typescript', 'json']
}),
plugins.structure.hoistSingleChapters(),
plugins.structure.imprintPages(
templates.htmlImprintPages(),
'front-page'
),
plugins.structure.reference({
bibliography,
prependPath: 'bibliography.xhtml'
}),
plugins.structure.epubLink(),
plugins.structure.aImg(),
plugins.structure.imgSrcToFileUrl(baseDir)
]
},
epub: {
plugins: []
},
css: {
plugins: []
}
},
{
css: [cssFiles.COMMON, cssFiles.EPUB].join('\n'),
outFile
}
);
},
pdf: async ({
outFile,
language,
locale,
strings,
bibliography,
cssFiles
}) => {
const { bookBuilder, templates, l10n } = await initBuilder(
language,
locale,
strings,
'pdf'
);
await bookBuilder.build<CustomTemplates, ExtraStrings, 'pdf'>(
'pdf',
l10n,
{
structure: {
plugins: [
plugins.structure.h3Title(),
plugins.structure.h5Counter(),
plugins.structure.highlighter({
languages: ['javascript', 'typescript', 'json']
}),
plugins.structure.hoistSingleChapters(),
plugins.structure.tableOfContents(),
plugins.structure.imprintPages(
templates.htmlImprintPages(),
'front-page'
),
plugins.structure.reference({
bibliography
}),
plugins.structure.imgDataUri(),
plugins.structure.aImg()
]
},
pdf: {
plugins: []
},
css: {
plugins: [plugins.css.dataUri()]
}
},
{
css: [
cssFiles.FONTS,
cssFiles.COMMON,
cssFiles.PAGE,
cssFiles.PRINT
].join('\n'),
outFile,
useCachedContent: false
}
);
},
landing: async ({ language, locale, strings }) => {
const { bookBuilder, templates } = await initBuilder(
language,
locale,
strings,
'html'
);
await applyAstPluginToStructure(
bookBuilder.context,
{ language, locale, strings, templates },
bookBuilder.structure,
plugins.structureAst.h3Title()
);
await buildLanding({
structure: bookBuilder.structure,
lang: language,
examplesDir: resolve('docs', 'examples') as Path,
outFile: resolve('docs', strings.landingFile) as Path,
strings,
templates
});
}
} as {
[target: string]: (params: {
outFile: Path;
language: string;
locale: string;
strings: ExtraStrings;
bibliography: Bibliography;
cssFiles: Record<string, string>;
baseDir: Path;
}) => Promise<void>;
};
async function main() {
const cssFiles = {
COMMON: await readFile(resolve(SRC, 'css', 'common.css'), 'utf-8'),
FONTS: await readFile(resolve(SRC, 'css', 'fonts.css'), 'utf-8'),
SCREEN: await readFile(resolve(SRC, 'css', 'screen.css'), 'utf-8'),
EPUB: await readFile(resolve(SRC, 'css', 'epub.css'), 'utf-8'),
PRINT: await readFile(resolve(SRC, 'css', 'print.css'), 'utf-8'),
PAGE: await readFile(resolve(SRC, 'css', 'page.css'), 'utf-8')
};
const languages = (args[0] ?? 'en,ru').split(',').map((s) => s.trim());
const targets = (args[1] ?? 'html,epub,pdf')
.split(',')
.map((s) => s.trim());
for (const language of languages) {
const locale = LOCALES[language];
if (!locale) {
throw new Error(`Unknown locale ${locale}`);
}
const strings = JSON.parse(
await readFile(resolve(SRC, language, 'l10n.json'), 'utf-8')
) as ExtraStrings;
const bibliography = JSON.parse(
await readFile(resolve(SRC, language, 'bibliography.json'), 'utf-8')
) as Bibliography;
for (const target of targets) {
const builder = builders[target];
if (typeof builder !== 'function') {
throw new Error(`Unknown target ${target}`);
}
const outFile = resolve(
'docs',
`API.${language}.${target}`
) as Path;
await builder({
outFile,
language,
locale,
strings,
bibliography,
cssFiles,
baseDir: SRC
});
}
}
}
main()
.catch((e) => console.error(e, e.stack))
.then(() => process.exit(0));

View File

@@ -1,40 +0,0 @@
export const apiHighlight = (hljs) => {
const ATTRIBUTE = {
begin: /(?<!":\s*)"(\\.|[^\\"\r\n])*"/,
className: 'attr'
};
const PUNCTUATION = {
match: /{}[[\],:]/,
className: 'punctuation'
};
const LITERALS = ['true', 'false', 'null'];
const LITERALS_MODE = {
scope: 'literal',
beginKeywords: LITERALS.join(' ')
};
return {
name: 'json',
keywords: {
keyword: 'GET POST PUT PATCH DELETE → …',
literal: LITERALS
},
contains: [
ATTRIBUTE,
{
scope: 'string',
begin: /(?!^:\s*)"/,
end: '"'
},
{
match: /{[\w\d-_]+}|<[\w\d-_\s\\n]+>/,
className: 'substitution'
},
PUNCTUATION,
LITERALS_MODE,
hljs.C_NUMBER_MODE,
hljs.C_LINE_COMMENT_MODE,
hljs.C_BLOCK_COMMENT_MODE
]
};
};

View File

@@ -68,10 +68,14 @@ pre code em * {
max-width: 100%;
}
.app-img-wrapper img {
img.size-s {
max-width: 390px;
}
img.size-s {
max-width: 540px;
}
pre {
margin: 1em auto;
padding: 1em;

View File

@@ -1,82 +1,75 @@
@media print {
html,
body {
margin: 0;
padding: 0;
font-size: 14pt;
}
.toc a,
ul li,
ol li {
text-size-adjust: none;
}
pre {
margin: 0 0 1em 0;
width: calc(100% - 2px);
line-height: 0.8em !important;
}
p code,
pre code {
font-size: 12pt !important;
}
img {
margin: 1px;
}
img.cc-by-nc-img {
width: 90px;
}
h1,
h2,
h3,
h4,
h5 {
break-after: avoid;
line-height: 1.2em;
font-size: 120%;
}
h6 {
break-before: avoid;
}
p,
li {
orphans: 5;
widows: 5;
}
img {
margin-top: 1em;
break-after: avoid;
}
.cover {
display: none;
}
.toc ul li ul li + li,
h4 + ul,
h4 + p {
break-inside: avoid;
break-before: avoid;
break-after: avoid;
}
.page-break {
break-after: page;
}
.no-page-break {
break-inside: avoid;
}
nav.page-main {
display: none;
}
html,
body {
font-size: 14pt;
}
.toc a,
ul li,
ol li {
text-size-adjust: none;
}
pre {
margin: 0 0 1em 0;
width: calc(100% - 2px);
line-height: 0.8em !important;
}
p code,
pre code {
font-size: 12pt !important;
}
img.cc-by-nc-img {
width: 90px;
}
h1,
h2,
h3,
h4,
h5 {
break-after: avoid;
line-height: 1.2em;
}
h6 {
break-before: avoid;
}
p,
li {
orphans: 5;
widows: 5;
}
img {
margin-top: 1em;
break-after: avoid;
border: transparent none !important;
box-shadow: none !important;
}
.cover {
display: none;
}
.toc ul li ul li + li,
h4 + ul,
h4 + p {
break-inside: avoid;
break-before: avoid;
break-after: avoid;
}
.page-break {
break-after: page;
}
.no-page-break {
break-inside: avoid;
}
nav.page-main {
display: none;
}

View File

@@ -144,7 +144,7 @@ article ul.share {
}
.side-panel ul.share li a.share-twitter {
background-image: url(/img/share/twitter.svg);
background-image: url(/img/share/x.png);
}
.side-panel ul.share li a.share-linkedin {

56
src/en/bibliography.json Normal file
View File

@@ -0,0 +1,56 @@
{
"birrel-nelson-implementing-rpc": {
"authors": "Birrell, A. D., Nelson, B. J.",
"publicationDate": "1984",
"title": "Implementing Remote Procedure Calls",
"subtitle": [
"ACM Transactions on Computer Systems (TOCS), Volume 2, Issue 1",
"Pages 39 - 59"
],
"hrefs": ["https://dl.acm.org/doi/10.1145/2080.357392"]
},
"fielding-architectural-styles": {
"authors": "Fielding, R. T.",
"publicationDate": "2001",
"title": "Architectural Styles and the Design of Network-based Software Architectures",
"hrefs": ["https://ics.uci.edu/~fielding/pubs/dissertation/top.htm"]
},
"fowler-gui-architectures": {
"authors": "Fowler, M.",
"publicationDate": "2006",
"title": "GUI Architectures",
"hrefs": ["https://www.martinfowler.com/eaaDev/uiArchs.html"]
},
"gang-of-four-patterns": {
"authors": "Gamma, E., Helm, R., Johnson, R., Vlissides, J.",
"publicationDate": "1994",
"title": "Design Patterns",
"subtitle": ["Elements of Reusable Object-Oriented Software"],
"hrefs": ["isbn:9780321700698"]
},
"grigorik-high-performance-browser-networking": {
"authors": "Grigorik, I.",
"publicationDate": "2013",
"title": "High Performance Browser Networking",
"hrefs": ["isbn:9781449344764", "https://hpbn.co"]
},
"hoffman-web-application-security": {
"authors": "Hoffman, A.",
"publicationDate": "2024",
"title": "Web Application Security",
"subtitle": ["Second Edition"],
"hrefs": ["isbn:9781098143930"]
},
"martin-functional-design": {
"authors": "Martin, R. C.",
"publicationDate": "2023",
"title": "Functional Design: Principles, Patterns, and Practices",
"hrefs": ["isbn:9780138176518"]
},
"nelson-rpc": {
"authors": "Nelson, B. J.",
"publicationDate": "1981",
"title": "Remote Procedure Call",
"hrefs": ["https://dl.acm.org/doi/10.5555/910306"]
}
}

View File

@@ -1,4 +1,4 @@
### [On the Structure of This Book][intro-structure]
### On the Structure of This Book
The book you're holding in your hands is dedicated to developing APIs as a separate engineering task. Although many concepts we're going to discuss apply to any type of software, our primary goal is to describe those problems and approaches to solving them that are most relevant in the context of the API subject area.

View File

@@ -1,4 +1,4 @@
### [The API Definition][intro-api-definition]
### The API Definition
Before we start talking about the API design, we need to explicitly define what the API is. Encyclopedias tell us that “API” is an acronym for “Application Program Interface.” This definition is fine but useless, much like the “Man” definition by Plato: “Man stands upright on two legs without feathers.” This definition is fine again, but it gives us no understanding of what's so important about a Man. (Actually, it's not even “fine”: Diogenes of Sinope once brought a plucked chicken, saying “That's Plato's Man.” And Plato had to add “with broad nails” to his definition.)

View File

@@ -1,4 +1,4 @@
### [API Quality Criteria][intro-api-quality]
### API Quality Criteria
Before we start laying out the recommendations for designing API architecture, we ought to specify what constitutes a “high-quality API,” and what the benefits of having a high-quality API are. Quite obviously, the quality of an API is primarily defined through its capability to solve developers' and users' problems. (Let's leave out the part where an API vendor pursues its own goals, not providing a useful product.)

View File

@@ -1,4 +1,4 @@
### [Choosing Solutions for API Development][intro-api-choosing-solutions]
### Choosing Solutions for API Development
Let's return to the metaphor of an API as an aqueduct connecting two contexts. While striving to make the use of our construct convenient for customers, we encounter another side of the problem: how would our customers prefer our API to be designed? Are there any widely adopted techniques for connecting water pipes in our subject area?

View File

@@ -1,4 +1,4 @@
### [The API-First Approach][intro-api-first-approach]
### The API-First Approach
Today, more and more IT companies are recognizing the importance of the “API-first” approach, which is the paradigm of developing software with a heavy focus on APIs.

View File

@@ -1,4 +1,4 @@
### [On Backward Compatibility][intro-back-compat]
### On Backward Compatibility
Backward compatibility is a *temporal* characteristic of an API. The obligation to maintain backward compatibility is the crucial point where API development differs from software development in general.

View File

@@ -1,4 +1,4 @@
### [On Versioning][intro-versioning]
### On Versioning
Here and throughout this book, we firmly adhere to the Semantic Versioning (*semver*)[ref Semantic Versioning 2.0.0](https://semver.org/) principles:

View File

@@ -1,4 +1,4 @@
### [Terms and Notation Keys][intro-terms-notation]
### Terms and Notation Keys
Software development is characterized, among other things, by the existence of many different engineering paradigms, whose adherents are sometimes quite aggressive towards other paradigms' adherents. While writing this book, we are deliberately avoiding using terms like “method,” “object,” “function,” and so on, using the neutral term “entity” instead. “Entity” means some atomic functionality unit, like a class, method, object, monad, prototype (underline what you think is right).

View File

@@ -1,4 +1,4 @@
### [The API Contexts Pyramid][api-design-context-pyramid]
### The API Contexts Pyramid
The approach we use to design APIs comprises four steps:
* Defining an application field

View File

@@ -1,4 +1,4 @@
### [Defining an Application Field][api-design-defining-field]
### Defining an Application Field
The key question you should ask yourself before starting to develop any software product, including an API, is: what problem do we solve? It should be asked four times, each time putting emphasis on a different word.

View File

@@ -1,4 +1,4 @@
### [Separating Abstraction Levels][api-design-separating-abstractions]
### Separating Abstraction Levels
“Separate abstraction levels in your code” is possibly the most general advice for software developers. However, we don't think it would be a grave exaggeration to say that separating abstraction levels is also the most challenging task for API developers.

View File

@@ -1,4 +1,4 @@
### [Isolating Responsibility Areas][api-design-isolating-responsibility]
### Isolating Responsibility Areas
In the previous chapter, we concluded that the hierarchy of abstractions in our hypothetical project would comprise:
* The user level (the entities formulated in terms understandable by users and acted upon by them: orders, coffee recipes)

View File

@@ -1,4 +1,4 @@
### [Describing Final Interfaces][api-design-describing-interfaces]
### Describing Final Interfaces
When all entities, their responsibilities, and their relations to each other are defined, we proceed to the development of the API itself. We need to describe the objects, fields, methods, and functions nomenclature in detail. In this chapter, we provide practical advice on making APIs usable and understandable.
@@ -532,7 +532,7 @@ POST /v1/coffee-machines/search
}
```
Formally speaking, having such behavior is feasible: why not have a “default geographical coordinates” concept? However, in reality, such policies of “silently” fixing mistakes lead to absurd situations like “the null island” — the most visited place in the world[ref Hrala, J. Welcome to Null Island, The Most 'Visited' Place on Earth That Doesn't Actually Exist](https://www.sciencealert.com/welcome-to-null-island-the-most-visited-place-that-doesn-t-exist). The more popular an API becomes, the higher the chances that partners will overlook these edge cases.
Formally speaking, having such behavior is feasible: why not have a “default geographical coordinates” concept? However, in reality, such policies of “silently” fixing mistakes lead to absurd situations like “the null island” — the most visited place in the world.[ref Hrala, J. Welcome to Null Island, The Most 'Visited' Place on Earth That Doesn't Actually Exist](https://www.sciencealert.com/welcome-to-null-island-the-most-visited-place-that-doesn-t-exist) The more popular an API becomes, the higher the chances that partners will overlook these edge cases.
**Better**:
@@ -890,11 +890,11 @@ However, be warned: clients are bad at implementing idempotency tokens. Two comm
If the author of this book were given a dollar each time he had to implement an additional security protocol invented by someone, he would be retired by now. API developers' inclination to create new signing procedures for requests or complex schemes of exchanging passwords for tokens is both obvious and meaningless.
**First**, there is no need to reinvent the wheel when it comes to security-enhancing procedures for various operations. All the algorithms you need are already invented, just adopt and implement them. No self-invented algorithm for request signature checking can provide the same level of protection against a Manipulator-in-the-middle (*MitM*) attack[ref Manipulator-in-the-middle Attack](https://owasp.org/www-community/attacks/Manipulator-in-the-middle_attack) as a mutual TLS authentication with certificate pinning[ref Mutual Authentication. mTLS](https://en.wikipedia.org/wiki/Mutual_authentication#mTLS).
**First**, there is no need to reinvent the wheel when it comes to security-enhancing procedures for various operations. All the algorithms you need are already invented, just adopt and implement them. No self-invented algorithm for request signature checking can provide the same level of protection against a Manipulator-in-the-middle (*MitM*) attack[ref Manipulator-in-the-middle Attack](https://owasp.org/www-community/attacks/Manipulator-in-the-middle_attack) as a mutual TLS authentication with certificate pinning.[ref Mutual Authentication. mTLS](https://en.wikipedia.org/wiki/Mutual_authentication#mTLS)
**Second**, assuming oneself to be an expert in security is presumptuous and dangerous. New attack vectors emerge daily, and staying fully aware of all actual threats is a full-time job. If you do something different during workdays, the security system you design will contain vulnerabilities that you have never heard about — for example, your password-checking algorithm might be susceptible to a timing attack[ref Timing Attack](https://en.wikipedia.org/wiki/Timing_attack) or your webserver might be vulnerable to a request splitting attack[ref HTTP Request Splitting](https://capec.mitre.org/data/definitions/105.html).
**Second**, assuming oneself to be an expert in security is presumptuous and dangerous. New attack vectors emerge daily, and staying fully aware of all actual threats is a full-time job. If you do something different during workdays, the security system you design will contain vulnerabilities that you have never heard about — for example, your password-checking algorithm might be susceptible to a timing attack[ref Timing Attack](https://en.wikipedia.org/wiki/Timing_attack) or your webserver might be vulnerable to a request splitting attack.[ref HTTP Request Splitting](https://capec.mitre.org/data/definitions/105.html)
The OWASP Foundation compiles a list of the most common vulnerabilities in APIs every year,[ref OWASP API Security Project](https://owasp.org/www-project-api-security/) which we strongly recommend studying.
The OWASP Foundation compiles a list of the most common vulnerabilities in APIs every year,[ref OWASP API Security Project](https://owasp.org/www-project-api-security/) which we strongly recommend studying. We also recommend a definitive work by Andrew Hoffman[ref:hoffman-web-application-security]() for everyone interested in Web security.
And just in case: all APIs must be provided over TLS 1.2 or higher (preferably 1.3).

View File

@@ -1,4 +1,4 @@
### [Annex to Section I. Generic API Example][api-design-annex]
### Annex to Section I. Generic API Example
Let's summarize the current state of our API study.

View File

@@ -1,6 +1,6 @@
### [On Design Patterns in the API Context][api-patterns-context]
### On Design Patterns in the API Context
The concept of “patterns” in the field of software engineering was introduced by Kent Beck and Ward Cunningham in 1987[ref Software Design Pattern. History](https://en.wikipedia.org/wiki/Software_design_pattern#History) and popularized by “The Gang of Four” (Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides) in their book “Design Patterns: Elements of Reusable Object-Oriented Software,” which was published in 1994[ref:{"short":"Gamma, E., Helm, R., Johnson, R., Vlissides, J. (1994)","extra":["Design Patterns","Elements of Reusable Object-Oriented Software"]}](isbn:9780321700698). According to the most widespread definition, a software design pattern is a “general, reusable solution to a commonly occurring problem within a given context.”
The concept of “patterns” in the field of software engineering was introduced by Kent Beck and Ward Cunningham in 1987[ref Software Design Pattern. History](https://en.wikipedia.org/wiki/Software_design_pattern#History) and popularized by “The Gang of Four” (Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides) in their book “Design Patterns: Elements of Reusable Object-Oriented Software,” which was published in 1994.[ref:gang-of-four-patterns]() According to the most widespread definition, a software design pattern is a “general, reusable solution to a commonly occurring problem within a given context.”
If we talk about APIs, especially those to which developers are end users (e.g., frameworks or operating system interfaces), the classical software design patterns are well applicable to them. Indeed, many examples in the previous Section of this book are just about applying some design patterns.

View File

@@ -1,4 +1,4 @@
### [Authenticating Partners and Authorizing API Calls][api-patterns-aa]
### Authenticating Partners and Authorizing API Calls
Before we proceed further to discussing technical matters, we feel obliged to provide an overview of the problems related to authorizing API calls and authenticating clients. Based on the main principle that “an API serves as a multiplier to both your opportunities and mistakes,” organizing authorization and authentication (AA) is one of the most important challenges that any API vendor faces, especially when it comes to public APIs. It is rather surprising that there is no standard approach to this issue, as every big vendor develops its own interface to solve AA problems, and these interfaces are often quite archaic.

View File

@@ -1,4 +1,4 @@
### [Synchronization Strategies][api-patterns-sync-strategies]
### Synchronization Strategies
Let's proceed to the technical problems that API developers face. We begin with the last one described in the introductory chapter: the necessity to synchronize states. Let us imagine that a user creates a request to order coffee through our API. While this request travels from the client to the coffee house and back, many things might happen. Consider the following chain of events:

View File

@@ -1,4 +1,4 @@
### [Eventual Consistency][api-patterns-weak-consistency]
### Eventual Consistency
The approach described in the previous chapter is in fact a trade-off: the API performance issues are traded for “normal” (i.e., expected) background errors that happen while working with the API. This is achieved by isolating the component responsible for controlling concurrency and only exposing read-only tokens in the public API. Still, the achievable throughput of the API is limited, and the only way of scaling it up is removing the strict consistency from the external API and thus allowing reading system state from read-only replicas:

View File

@@ -1,4 +1,4 @@
### [Asynchronicity and Time Management][api-patterns-async]
### Asynchronicity and Time Management
Let's continue working with the previous example: the application retrieves some system state upon start-up, perhaps not the most recent one. What else does the probability of collision depend on, and how can we lower it?

View File

@@ -1,4 +1,4 @@
### [Lists and Accessing Them][api-patterns-lists]
### Lists and Accessing Them
In the previous chapter, we concluded with the following interface that allows minimizing collisions while creating orders:

View File

@@ -1,4 +1,4 @@
### [Bidirectional Data Flows. Push and Poll Models][api-patterns-push-vs-poll]
### Bidirectional Data Flows. Push and Poll Models
In the previous chapter, we discussed the following scenario: a partner receives information about new events occuring in the system by periodically requesting an endpoint that supports retrieving ordered lists.

View File

@@ -1,4 +1,4 @@
### [Multiplexing Notifications. Asynchronous Event Processing][api-patterns-async-event-processing]
### Multiplexing Notifications. Asynchronous Event Processing
One of the vexing restrictions of almost every technology mentioned in the previous chapter is the limited size of messages. With client push notifications the situation is the most problematic: Google Firebase Messaging at the moment this chapter is being written allowed no more than 4000 bytes of payload. In backend development, the restrictions are also notable; let's say, Amazon SQS limits the size of messages to 256 KiB. While developing *webhook*-based integrations, you risk hitting the maximum body size allowed by the partner's webserver (for example, in nginx the default value is 1MB). This leads us to the necessity of making two technical decisions regarding the notification formats:
* Whether a message contains all data needed to process it or just notifies some state change has happened

View File

@@ -1,4 +1,4 @@
### [Atomicity of Bulk Changes][api-patterns-atomicity]
### Atomicity of Bulk Changes
Let's transition from *webhooks* back to developing direct-call APIs. The design of the `orders/bulk-status-change` endpoint, as described in the previous chapter, raises an interesting question: what should we do if some changes were successfully processed by our backend while others were not?

View File

@@ -1,4 +1,4 @@
### [Partial Updates][api-patterns-partial-updates]
### Partial Updates
The case of partial application of the list of changes described in the previous chapter naturally leads us to the next typical API design problem. What if the operation involves a low-level overwriting of several data fields rather than an atomic idempotent procedure (as in the case of changing the order status)? Let's take a look at the following example:

View File

@@ -1,4 +1,4 @@
### [Degradation and Predictability][api-patterns-degrading]
### Degradation and Predictability
In the previous chapters, we repeatedly discussed that the background level of errors is not just unavoidable, but in many cases, APIs are deliberately designed to tolerate errors to make the system more scalable and predictable.

View File

@@ -1,4 +1,4 @@
### [The Backward Compatibility Problem Statement][back-compat-statement]
### The Backward Compatibility Problem Statement
As usual, let's conceptually define “backward compatibility” before we start.

View File

@@ -1,4 +1,4 @@
### [On the Waterline of the Iceberg][back-compat-iceberg-waterline]
### On the Waterline of the Iceberg
Before we start talking about extensible API design, we should discuss the hygienic minimum. Many problems would have never occurred if API vendors had paid more attention to clearly marking their area of responsibility.

View File

@@ -1,4 +1,4 @@
### [Extending through Abstracting][back-compat-abstracting-extending]
### Extending through Abstracting
In the previous chapters, we have attempted to outline theoretical rules and illustrate them with practical examples. However, understanding the principles of designing change-proof APIs requires practice above all else. The ability to anticipate future growth problems comes from a handful of grave mistakes once made. While it is impossible to foresee everything, one can develop a certain technical intuition.

View File

@@ -1,4 +1,4 @@
### [Strong Coupling and Related Problems][back-compat-strong-coupling]
### Strong Coupling and Related Problems
To demonstrate the problems of strong coupling, let's move on to *interesting* topics. Let's continue our “variation analysis”: what if partners wish to offer their own unique coffee recipes to end users in addition to the standard beverages? The challenge is that the partner API, as described in the previous chapter, does not expose the very existence of the partner network to the end user, thus presenting a simple case. However, once we start providing methods to modify the core functionality, not just API extensions, we will soon face next-level problems.

View File

@@ -1,4 +1,4 @@
### [Weak Coupling][back-compat-weak-coupling]
### Weak Coupling
In the previous chapter, we demonstrated how breaking strong coupling of components leads to decomposing entities and collapsing their public interfaces down to a reasonable minimum. But let us return to the question we previously mentioned in the “[Extending through Abstracting](#back-compat-abstracting-extending)” chapter: how should we parametrize the order preparation process implemented via a third-party API? In other words, what *is* the `order_execution_endpoint` required in the API type registration handler?

View File

@@ -1,4 +1,4 @@
### [Interfaces as a Universal Pattern][back-compat-universal-interfaces]
### Interfaces as a Universal Pattern
Let us summarize what we have written in the three previous chapters:
@@ -6,7 +6,7 @@ Let us summarize what we have written in the three previous chapters:
2. Higher-level entities are to be the informational contexts for low-level ones, meaning they don't prescribe any specific behavior but rather translate their state and expose functionality to modify it, either directly through calling some methods or indirectly through firing events.
3. Concrete functionality, such as working with “bare metal” hardware or underlying platform APIs, should be delegated to low-level entities.
**NB**: There is nothing novel about these rules: one might easily recognize them as the *SOLID* architecture principles[ref SOLID](https://en.wikipedia.org/wiki/SOLID)[ref:{"short":"Martin, R. C.","extra":["Design Principles and Design Patterns"]}](http://staff.cs.utu.fi/~jounsmed/doos_06/material/DesignPrinciplesAndPatterns.pdf). This is not surprising either, as *SOLID* focuses on contract-oriented development, and APIs are contracts by definition. We have simply introduced the concepts of “abstraction levels” and “informational contexts” to these principles.
**NB**: There is nothing novel about these rules: one might easily recognize them as the *SOLID* architecture principles[ref SOLID](https://en.wikipedia.org/wiki/SOLID)[ref:martin-functional-design 12. Solid](). This is not surprising either, as *SOLID* focuses on contract-oriented development, and APIs are contracts by definition. We have simply introduced the concepts of “abstraction levels” and “informational contexts” to these principles.
However, there remains an unanswered question: how should we design the entity nomenclature from the beginning so that extending the API won't result in a mess of assorted inconsistent methods from different stages of development? The answer is quite obvious: to avoid clumsy situations during abstracting (as with the recipe properties), all the entities must be originally considered as specific implementations of a more general interface, even if there are no planned alternative implementations for them.

View File

@@ -1,4 +1,4 @@
### [The Serenity Notepad][back-compat-serenity-notepad]
### The Serenity Notepad
Apart from the abovementioned abstract principles, let us give a list of concrete recommendations on how to make changes in existing APIs to maintain backward compatibility

View File

@@ -1,8 +1,8 @@
### [On the HTTP API Concept. Paradigms of Developing Client-Server Communication][http-api-concepts]
### On the HTTP API Concept. Paradigms of Developing Client-Server Communication
The problem of designing HTTP APIs is, unfortunately, one of the most “holywar”-inspiring issues. On one hand, it is one of the most popular technologies; on the other hand, it is quite complex and difficult to comprehend due to the large and fragmented standard split into many RFCs. As a result, the HTTP specification is doomed to be poorly understood and imperfectly interpreted by millions of software engineers and thousands of textbook writers. Therefore, before proceeding to the useful part of this Section, we must clarify exactly what we are going to discuss.
Let's start with a short historical overview. Performing users' requests on a remote server has been one of the basic tasks in software engineering since mainframes, and it naturally gained additional momentum with the development of ARPANET. The first high-level protocol for network communication worked in the paradigm of sending messages over the network (as an example, see the DEL protocol that was proposed in one of the very first RFCs — RFC-5 published in 1969[ref RFC-5. DEL](https://datatracker.ietf.org/doc/html/rfc5)). However, scholars quickly understood that it would be much more convenient if calling a remote server and accessing remote resources wasn't any different from working with local memory and resources *in terms of function signatures*. This concept was strictly formulated under the name “Remote Procedure Call” (RPC) by Bruce Nelson, an employee of the famous Xerox Palo Alto Research Center in 1981.[ref Nelson, B. J. (1981) Remote procedure call](https://www.semanticscholar.org/paper/Remote-procedure-call-Nelson/c860de40a88090055948b72d04dd79b02195e06b) Nelson was also the co-author of the first practical implementation of the proposed paradigm, namely Sun RPC[ref Birrell, A. D., Nelson, B. J. (1984) Implementing remote procedure calls](https://dl.acm.org/doi/10.1145/2080.357392)[ref RPC: Remote Procedure Call Protocol Specification](https://datatracker.ietf.org/doc/html/rfc1050), which still exists as ONC RPC.
Let's start with a short historical overview. Performing users' requests on a remote server has been one of the basic tasks in software engineering since mainframes, and it naturally gained additional momentum with the development of ARPANET. The first high-level protocol for network communication worked in the paradigm of sending messages over the network (as an example, see the DEL protocol that was proposed in one of the very first RFCs — RFC-5 published in 1969[ref RFC-5. DEL](https://datatracker.ietf.org/doc/html/rfc5)). However, scholars quickly understood that it would be much more convenient if calling a remote server and accessing remote resources wasn't any different from working with local memory and resources *in terms of function signatures*. This concept was strictly formulated under the name “Remote Procedure Call” (RPC) by Bruce Nelson, an employee of the famous Xerox Palo Alto Research Center in 1981.[ref:nelson-rpc]() Nelson was also the co-author of the first practical implementation of the proposed paradigm, namely Sun RPC[ref:birrel-nelson-implementing-rpc]()[ref RPC: Remote Procedure Call Protocol Specification](https://datatracker.ietf.org/doc/html/rfc1050), which still exists as ONC RPC.
First widely adopted RPC protocols (such as the aforementioned Sun RPC, Java RMI[ref Remote Method Invocation (RMI)](https://www.oracle.com/java/technologies/javase/remote-method-invocation-home.html), and CORBA[ref CORBA](https://www.corba.org/)) strictly followed the paradigm. The technology allowed achieving exactly what Nelson was writing about — that is, making no difference between local and remote code execution. The “magic” is hidden within tooling that generates the implementation of working with remote servers, and developers don't need to know how the protocol works.

View File

@@ -1,4 +1,4 @@
### [Advantages and Disadvantages of HTTP APIs Compared to Alternative Technologies][http-api-pros-and-cons]
### Advantages and Disadvantages of HTTP APIs Compared to Alternative Technologies
As we discussed in the previous chapter, today, the choice of a technology for developing client-server APIs comes down to selecting either a resource-oriented approach (commonly referred to as “REST API”; let us reiterate that we will use the term “HTTP API” instead) or a modern RPC protocol. As we mentioned earlier, *conceptually* the difference is not that significant. However, *technically* these frameworks use the HTTP protocol quite differently:

View File

@@ -1,8 +1,8 @@
### [The REST Myth][http-api-rest-myth]
### The REST Myth
Before we proceed to discuss HTTP API design patterns, we feel obliged to clarify one more important terminological issue. Often, an API matching the description we gave in the “[On the HTTP API Concept](#http-api-concepts)” chapter is called a “REST API” or a “RESTful API.” In this Section, we don't use any of these terms as it makes no practical sense.
What is “REST”? As we mentioned earlier, in 2000, Roy Fielding, one of the authors of the HTTP and URI specifications, published his doctoral dissertation titled “Architectural Styles and the Design of Network-based Software Architectures,” the fifth chapter of which was named “Representational State Transfer (REST).[ref:{"short":"Fielding, R. (2000)","extra":["Architectural Styles and the Design of Network-based Software Architectures","Representational State Transfer (REST)"]}](https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm)
What is “REST”? As we mentioned earlier, in 2000, Roy Fielding, one of the authors of the HTTP and URI specifications, published his doctoral dissertation titled “Architectural Styles and the Design of Network-based Software Architectures,” the fifth chapter of which was named “Representational State Transfer (REST).”[ref:fielding-architectural-styles CHAPTER 5. Representational State Transfer (REST)"](https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm)
As anyone can attest by reading this chapter, it features a very much abstract overview of a distributed client-server architecture that is not bound to either HTTP or URL. Furthermore, it does not discuss any API design recommendations. In this chapter, Fielding methodically *enumerates restrictions* that any software engineer encounters when developing distributed client-server software. Here they are:
* The client and the server do not know how each of them is implemented

View File

@@ -1,4 +1,4 @@
### [Components of an HTTP Request and Their Semantics][http-api-requests-semantics]
### Components of an HTTP Request and Their Semantics
The important exercise we must conduct is to describe the format of an HTTP request and response and explain the basic concepts. Many of these may seem obvious to the reader. However, the situation is that even the basic knowledge we require to move further is scattered across vast and fragmented documentation, causing even experienced developers to struggle with some nuances. Below, we will try to compile a structured overview that is sufficient to design HTTP APIs.
@@ -33,7 +33,7 @@ Content-Type: application/json
}
```
**NB**: In HTTP/2 (and future HTTP/3), separate binary frames are used for headers and data instead of the holistic text format.[ref:{"short":"Grigorik, I. (2013)","extra":["High Performance Browser Networking","Chapter 12. HTTP/2"]}](https://hpbn.co/http2/) However, this doesn't affect the architectural concepts we will describe below. To avoid ambiguity, we will provide examples in the HTTP/1.1 format.
**NB**: In HTTP/2 (and future HTTP/3), separate binary frames are used for headers and data instead of the holistic text format.[ref:grigorik-high-performance-browser-networking Chapter 12. HTTP/2](https://hpbn.co/http2/) However, this doesn't affect the architectural concepts we will describe below. To avoid ambiguity, we will provide examples in the HTTP/1.1 format.
##### A URL

View File

@@ -1,4 +1,4 @@
### [Organizing HTTP APIs Based on the REST Principles][http-api-rest-organizing]
### Organizing HTTP APIs Based on the REST Principles
Now let's discuss the specifics: what does it mean exactly to “follow the protocol's semantics” and “develop applications in accordance with the REST architectural style”? Remember, we are talking about the following principles:
* Operations must be stateless

View File

@@ -1,4 +1,4 @@
### [Designing a Nomenclature of URLs. The CRUD Operations][http-api-urls-crud]
### Designing a Nomenclature of URLs. The CRUD Operations
As we noted on several occasions in the previous chapters, neither the HTTP and URL standards nor REST architectural principles prescribe concrete semantics for the meaningful parts of a URL (notably, path fragments and key-value pairs in the query). **The rules for organizing URLs in an HTTP API exist *only* to improve the API's readability and consistency from the developers' perspective**. However, this doesn't mean they are unimportant. Quite the opposite: URLs in HTTP APIs are a means of describing abstraction levels and entities' responsibility areas. A well-designed API hierarchy should be reflected in a well-designed URL nomenclature.

View File

@@ -1,4 +1,4 @@
### [Working with HTTP API Errors][http-api-errors]
### Working with HTTP API Errors
The examples of organizing HTTP APIs discussed in the previous chapters were mostly about “happy paths,” i.e., the direct path of working with an API in the absence of obstacles. It's now time to talk about the opposite case: how HTTP APIs should work with errors and how the standard and the REST architectural principles can help us.

View File

@@ -1,4 +1,4 @@
### [Final Provisions and General Recommendations][http-api-final-recommendations]
### Final Provisions and General Recommendations
Let's summarize what was discussed in the previous chapters. To design a fine HTTP API one needs to:
1. Describe a happy path, i.e. draw a diagram of all HTTP calls that occur during a normal work cycle of an application.

View File

@@ -1,4 +1,4 @@
### [On Terminology. An Overview of Technologies for UI Development][sdk-toc-technology-overview]
### On Terminology. An Overview of Technologies for UI Development
As we mentioned in the Introduction, the term “SDK” (which stands for “Software Development Kit”) lacks concrete meaning. The common understanding is that an SDK differs from an API as it provides both program interfaces and tools to work with them. This definition is hardly satisfactory as today any technology is likely to be provided with a bundled toolset.

View File

@@ -1,4 +1,4 @@
### [SDKs: Problems and Solutions][sdk-problems-solutions]
### SDKs: Problems and Solutions
The first question we need to clarify about SDKs (let us reiterate that we use this term to denote a native client library that allows for working with a technology-agnostic underlying client-server API) is why SDKs exist in the first place. In other words, why is using “wrappers” more convenient for frontend developers than working with the underlying API directly?

View File

@@ -1,14 +1,14 @@
### [Problems of Introducing UI Components][sdk-ui-components]
### Problems of Introducing UI Components
Introducing UI components to an SDK brings an additional dimension to an already complex setup comprising a low-level API and a client wrapper on top of it. Now both developers (who write the application) and end users (who use the application) interact with your API. This might not appear as a game changer at first glance; however, we assure you that it is. Involving an end-user has significant consequences from the API / SDK design point of view as it requires much more careful and elaborate program interfaces compared to a “pure” client-server API. Let us explain this statement with a concrete example.
Imagine that we decided to provide a client SDK for our API that features ready-to-use components for application developers. The functionality is simple: the user enters a search phrase and observes the results in the form of a list.
[![APP](/img/mockups/01.png "The main screen of an application with search results")]()
[![APP](/img/mockups/01.size-s.png "The main screen of an application with search results")]()
The user can select an item and view the offer details with available actions.
[![APP](/img/mockups/02.png "Offer view panel")]()
[![APP](/img/mockups/02.size-s.png "Offer view panel")]()
To implement this scenario, we provide an object-oriented API in the form of, let's say, a class named `SearchBox` that realizes the aforementioned functionality by utilizing the `search` method in our client-server API.
@@ -49,11 +49,11 @@ Any asynchronous operation in a UI component, especially if it is visibly indica
Imagine that a developer decided to enhance the design of the offer list with icons of coffee shop chains. If the icon is set, it should be shown in every place related to a specific coffee shop's offer.
[![APP](/img/mockups/03.png "Search results with a coffee shop chain icon")]()
[![APP](/img/mockups/03.size-s.png "Search results with a coffee shop chain icon")]()
Now let's also imagine that the developer additionally customized all buttons in the SDK by adding action icons.
[![APP](/img/mockups/04.png "The offer view panel with action icons")]()
[![APP](/img/mockups/04.size-s.png "The offer view panel with action icons")]()
A question arises: if an offer of the coffee chain is shown in the panel, which icon should be featured on the order creation button: the one inherited from the offer properties (the coffee chain logo) or the one inherited from the action type of the button itself? The order creation control element is incorporated into two entity hierarchies [visual one and data-bound (semantic) one] and inherits from both equally.

View File

@@ -1,4 +1,4 @@
### [Decomposing UI Components][sdk-decomposing]
### Decomposing UI Components
Let's transition to a more substantive conversation and try to understand why the requirement to allow the replacement of a component's subsystems with alternative implementations leads to a dramatic increase in interface complexity. We will continue studying the `SearchBox` component from the previous chapter. Allow us to remind the reader of the factors that complicate the design of APIs for visual components:
* Coupling heterogeneous functionality (such as business logic, appearance styling, and behavior) into a single entity
@@ -8,21 +8,21 @@ Let's transition to a more substantive conversation and try to understand why th
Let's make the task more specific. Imagine that we need to develop a `SearchBox` that allows for the following modifications:
1. Replacing the textual paragraphs representing an offer with a map with markers that could be highlighted:
[![APP](/img/mockups/05.png "Search results on a map")]()
[![APP](/img/mockups/05.size-s.png "Search results on a map")]()
* This illustrates the problem of replacing a subcomponent (the offer list) while preserving the behavior and design of other parts of the system as well as the complexity of implementing shared states.
2. Combining short and full descriptions of an offer in a single UI (a list item could be expanded, and the order can be created in-place):
[![APP](/img/mockups/06.png "A list of offers with short descriptions")]()
[![APP](/img/mockups/06.size-s.png "A list of offers with short descriptions")]()
[![APP](/img/mockups/07.png "A list of offers with some of them expanded")]()
[![APP](/img/mockups/07.size-s.png "A list of offers with some of them expanded")]()
* This illustrates the problem of fully removing a subcomponent and transferring its business logic to other parts of the system.
3. Manipulating the data presented to the user and the available actions for an offer through adding new buttons, such as “Previous offer,” “Next offer,” and “Make a call.”
[![APP](/img/mockups/08.png "An offer panel with additional icons and buttons")]()
[![APP](/img/mockups/08.size-s.png "An offer panel with additional icons and buttons")]()
In this scenario, we're evaluating different chains of propagating data and options down to the offer panel and building dynamic UIs on top of it:

View File

@@ -1,4 +1,4 @@
### [The MV* Frameworks][sdk-mv-frameworks]
### The MV* Frameworks
One obvious approach to reducing the complexity of implementing the multi-layered component hierarchies we described in the previous chapter is to restrict possible interaction directions. As we described in the “[Weak Coupling](#back-compat-weak-coupling)” chapter, we could simplify the implementation if we allow subcomponents to call the parent context's methods directly:
@@ -89,9 +89,9 @@ Such a full model poses a problem not only semantically and theoretically (as it
Another ideological problem is organizing nested controllers. If there are subordinate subcomponents in the system, all the problems that an MV* approach solved return at a higher level: we have to allow nested controllers either to modify a global model or to call parent controllers. Both solutions imply strong coupling and require exquisite interface design skill; otherwise reusing components will be very hard.
If we take a closer look at modern UI libraries that claim to employ MV* paradigms, we will learn they employ it quite loosely. Usually, only the main principle that a model defines UI and can only be modified through controllers is adopted. Nested components usually have their own models (in most cases, comprising a subset of the parent model enriched with the component's own state), and the global model contains only a limited number of fields. This approach is implemented in many modern UI frameworks, including those that claim they have nothing to do with MV* paradigms (React, for instance[ref Why did we build React?](https://legacy.reactjs.org/blog/2013/06/05/why-react.html) [ref Mattiazzi, R. How React and Redux brought back MVC and everyone loved it](https://rangle.io/blog/how-react-and-redux-brought-back-mvc-and-everyone-loved-it)).
If we take a closer look at modern UI libraries that claim to employ MV* paradigms, we will learn they employ it quite loosely. Usually, only the main principle that a model defines UI and can only be modified through controllers is adopted. Nested components usually have their own models (in most cases, comprising a subset of the parent model enriched with the component's own state), and the global model contains only a limited number of fields. This approach is implemented in many modern UI frameworks, including those that claim they have nothing to do with MV* paradigms (React, for instance[ref Why did we build React?](https://legacy.reactjs.org/blog/2013/06/05/why-react.html)[ref Mattiazzi, R. How React and Redux brought back MVC and everyone loved it](https://rangle.io/blog/how-react-and-redux-brought-back-mvc-and-everyone-loved-it)).
All these problems of the MVC paradigm were highlighted by Martin Fowler in his “GUI Architectures” essay.[ref Fowler, M. GUI Architectures](https://www.martinfowler.com/eaaDev/uiArchs.html) The proposed solution is the “Model-View-*Presenter*” framework, in which the controller entity is replaced with a *presenter*. The responsibility of the presenter is not only translating events, but preparing data for views as well. This allows for full separation of abstraction levels (a model now stores only semantic data while a presenter transforms it into low-level parameters that define UI look; the set of these parameters is called the “Application Model” or “Presentation Model” in Fowler's text).
All these problems of the MVC paradigm were highlighted by Martin Fowler in his “GUI Architectures” essay.[ref:fowler-gui-architectures]() The proposed solution is the “Model-View-*Presenter*” framework, in which the controller entity is replaced with a *presenter*. The responsibility of the presenter is not only translating events, but preparing data for views as well. This allows for full separation of abstraction levels (a model now stores only semantic data while a presenter transforms it into low-level parameters that define UI look; the set of these parameters is called the “Application Model” or “Presentation Model” in Fowler's text).
[![PLOT](/img/graphs/sdk-mvp.en.png "MVP entities interaction chart")]()

View File

@@ -1,4 +1,4 @@
### [The Backend-Driven UI][sdk-backend-driven]
### The Backend-Driven UI
Another method of reducing the complexity of building “bridges” that connect different subject areas in one component is to eliminate one of them. For instance, business logic could be removed: components might be entirely abstract, and the translation of UI events into useful actions hidden beyond the developer's control.

View File

@@ -1,4 +1,4 @@
### [Shared Resources and Asynchronous Locks][sdk-shared-resources]
### Shared Resources and Asynchronous Locks
Another important pattern we need to discuss is accessing shared resources. Imagine that in our study application, opening an offer panel required making an additional request to the server and thus became asynchronous. Let's modify the `OfferPanelComponent` code:

View File

@@ -1,4 +1,4 @@
### [Computed Properties][sdk-computed-properties]
### Computed Properties
Let's revisit one of the problems we outlined in the “[Problems of Introducing UI Components](#sdk-ui-components)” chapter: the existence of multiple inheritance lines complicates customizing UI components as it implies that component properties could be inherited from any such line.

View File

@@ -1,4 +1,4 @@
### [Conclusion][sdk-conclusion]
### Conclusion
In the previous eight chapters, we aimed to convey two important observations:
* Developing a high-quality UI library is a very complex engineering task.

View File

@@ -1,4 +1,4 @@
### [The API as a Product][api-product]
### The API as a Product
There are two important statements regarding APIs viewed as products.

View File

@@ -1,4 +1,4 @@
### [API Business Models][api-product-business-models]
### API Business Models
Before we proceed to the API product management principles, let us draw your attention to the matter of profits that the API vendor company might extract from it. As we will demonstrate in the next chapters, this is not an idle question as it directly affects making product decisions and setting KPIs for the API team. In this chapter, we will enumerate the main API monetization models. [In brackets, we will provide examples of such models applicable to our coffee-machine API study.]

View File

@@ -1,4 +1,4 @@
### [Developing a Product Vision][api-product-vision]
### Developing a Product Vision
The above-mentioned fragmentation of the API target audience, i.e., the “developers — business — end users” triad, makes API product management quite a non-trivial problem. Yes, the basics are the same: find your audience's needs and satisfy them. The problem is that your product has several different audiences, and their interests sometimes diverge. The end users' request for an affordable cup of coffee does not automatically imply business demand for a coffee machine API.

View File

@@ -1,4 +1,4 @@
### [Communicating with Developers][api-product-devrel]
### Communicating with Developers
As we have described in the previous chapters, managing an API product requires building relationships with both business partners and developers. (Ideally, with end users as well, although this option is seldom available to API providers.)

View File

@@ -1,4 +1,4 @@
### [Communicating with Business Owners][api-product-business-comms]
### Communicating with Business Owners
The basics of interacting with business partners are to some extent paradoxically contrary to the basics of communicating with developers:
* On one hand, partners are much more loyal and sometimes even enthusiastic regarding the opportunities you offer (especially free ones).

View File

@@ -1,4 +1,4 @@
### [An API Services Lineup][api-product-lineup]
### An API Services Lineup
The important rule of API product management that any major API provider will soon learn is this: don't just ship one specific API; there is always room for a lineup of products, and this lineup is two-dimensional.

View File

@@ -1,4 +1,4 @@
### [API Key Performance Indicators][api-product-kpi]
### API Key Performance Indicators
As we described in the previous chapters, there are many API monetization models, both direct and indirect. Importantly, most of them are fully or conditionally free for partners, and the direct-to-indirect benefits ratio tends to change during the API lifecycle. That naturally leads us to the question of how exactly shall we measure the API's success and what goals are to be set for the product team.

View File

@@ -1,4 +1,4 @@
### [Identifying Users and Preventing Fraud][api-product-antifraud]
### Identifying Users and Preventing Fraud
In the context of working with an API, we talk about two kinds of users of the system:
* Users-developers, i.e., your partners writing code atop of the API

View File

@@ -1,4 +1,4 @@
### [The Technical Means of Preventing ToS Violations][api-product-tos-violations]
### The Technical Means of Preventing ToS Violations
Implementing the centralized system to prevent partner endpoint-bound fraud, as described in the previous chapter, faces practical challenges.

View File

@@ -1,4 +1,4 @@
### [Supporting Customers][api-product-customer-support]
### Supporting Customers
Let's shift our focus from banning users to supporting them. First and foremost, it's essential to clarify that when we discuss supporting API customers, we are referring to aiding developers and to some extent business partners. End users rarely directly interact with APIs directly, except for a few non-standard cases:

View File

@@ -1,4 +1,4 @@
### [Documentation][api-product-documentation]
### Documentation
Regrettably, many API providers pay miserable attention to the quality of documentation. Meanwhile, documentation is the face of the product and the entry point to it. The problem becomes even worse when we acknowledge that it's almost impossible to write help articles that developers will find satisfactory.

View File

@@ -1,4 +1,4 @@
### [Testing Environments][api-product-testing]
### Testing Environments
If the operations executed via the API have consequences for end users or partners (especially those that involve costs) you must provide a test version of the API. In this testing API, real-world actions either don't occur at all (for instance, orders are created but nobody serves them) or are simulated using cost-effective methods (for example, sending an email to the developer's mailbox instead of an SMS to the user).

View File

@@ -1,4 +1,4 @@
### [Managing Expectations][api-product-expectations]
### Managing Expectations
Finally, the last aspect we would like to shed light on is managing partners' expectations regarding the further development of the API. When we talk about consumer qualities, APIs differ little from other B2B software products: in both cases, you need to form an understanding of SLA conditions, available features, interface responsiveness and other characteristics that are important for clients. Still, APIs have their specificities.

View File

@@ -2,10 +2,13 @@
"title": "The API",
"author": "Sergey Konstantinov",
"chapter": "Chapter",
"chapterTitle": "Chapter",
"toc": "Table of Contents",
"bibliography": "Bibliography",
"description": "API-first development is one of the hottest technical topics nowadays since many companies have started to realize that APIs serves as a multiplier to their opportunities — but it amplifies the design mistakes as well. This book is written to share expertise and describe best practices in designing and developing APIs. It comprises six sections dedicated to the following topics: the API design, API patterns, maintaining backward compatibility, HTTP APIs & the REST architectural principles, SDKs and UI libraries, API product management.",
"publisher": "Sergey Konstantinov",
"copyright": "© Sergey Konstantinov, 2023",
"clickToEnlarge": "Click to enlarge",
"locale": "en-US",
"file": "API",
"isbn": "ISBN",
@@ -25,6 +28,7 @@
"sidePanel": {
"shareTo": "Share",
"copyLink": "Link",
"shareLink": "Share link",
"shareParameters": {
"url": "https://twirl.github.io/The-API-Book/",
"text": "The API by Sergey Konstantinov — a book about designing APIs, extending them and finding a proper place in the market",
@@ -38,7 +42,7 @@
},
{
"key": "twitter",
"link": "https://twitter.com/intent/tweet?text=${text}&url=${url}&hashtags=${tags}&via=${viaTwitter}"
"link": "https://x.com/intent/tweet?url=${url}"
},
{
"key": "linkedin",
@@ -58,7 +62,7 @@
"linkedinString": "linkedin.com/in/twirl",
"githubHref": "https://github.com/twirl/The-API-Book",
"githubString": "github.com/twirl/The-API-Book",
"twitterHref": "https://twitter.com/blogovodoved",
"twitterHref": "https://x.com/blogovodoved",
"kindleTag": "Amazon Kindle",
"kindleHref": "https://www.amazon.com/gp/product/B09RHH44S5/",
"appleTag": "Apple Books",

View File

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 KiB

View File

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 68 KiB

View File

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 46 KiB

View File

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 73 KiB

View File

Before

Width:  |  Height:  |  Size: 279 KiB

After

Width:  |  Height:  |  Size: 279 KiB

View File

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

View File

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 66 KiB

View File

@@ -1,16 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Logo" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 248 204" style="enable-background:new 0 0 248 204;" xml:space="preserve">
<style type="text/css">
.st0{fill:#1D9BF0;}
</style>
<g id="Logo_1_">
<path id="white_background" class="st0" d="M221.95,51.29c0.15,2.17,0.15,4.34,0.15,6.53c0,66.73-50.8,143.69-143.69,143.69v-0.04
C50.97,201.51,24.1,193.65,1,178.83c3.99,0.48,8,0.72,12.02,0.73c22.74,0.02,44.83-7.61,62.72-21.66
c-21.61-0.41-40.56-14.5-47.18-35.07c7.57,1.46,15.37,1.16,22.8-0.87C27.8,117.2,10.85,96.5,10.85,72.46c0-0.22,0-0.43,0-0.64
c7.02,3.91,14.88,6.08,22.92,6.32C11.58,63.31,4.74,33.79,18.14,10.71c25.64,31.55,63.47,50.73,104.08,52.76
c-4.07-17.54,1.49-35.92,14.61-48.25c20.34-19.12,52.33-18.14,71.45,2.19c11.31-2.23,22.15-6.38,32.07-12.26
c-3.77,11.69-11.66,21.62-22.2,27.93c10.01-1.18,19.79-3.86,29-7.95C240.37,35.29,231.83,44.14,221.95,51.29z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

BIN
src/img/share/x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

56
src/ru/bibliography.json Normal file
View File

@@ -0,0 +1,56 @@
{
"birrel-nelson-implementing-rpc": {
"authors": "Birrell, A. D., Nelson, B. J.",
"publicationDate": "1984",
"title": "Implementing Remote Procedure Calls",
"subtitle": [
"ACM Transactions on Computer Systems (TOCS), Volume 2, Issue 1",
"Pages 39 - 59"
],
"hrefs": ["https://dl.acm.org/doi/10.1145/2080.357392"]
},
"fielding-architectural-styles": {
"authors": "Fielding, R. T.",
"publicationDate": "2001",
"title": "Architectural Styles and the Design of Network-based Software Architectures",
"hrefs": ["https://ics.uci.edu/~fielding/pubs/dissertation/top.htm"]
},
"fowler-gui-architectures": {
"authors": "Fowler, M.",
"publicationDate": "2006",
"title": "GUI Architectures",
"hrefs": ["https://www.martinfowler.com/eaaDev/uiArchs.html"]
},
"gang-of-four-patterns": {
"authors": "Gamma, E., Helm, R., Johnson, R., Vlissides, J.",
"publicationDate": "1994",
"title": "Design Patterns",
"subtitle": ["Elements of Reusable Object-Oriented Software"],
"hrefs": ["isbn:9780321700698"]
},
"grigorik-high-performance-browser-networking": {
"authors": "Grigorik, I.",
"publicationDate": "2013",
"title": "High Performance Browser Networking",
"hrefs": ["isbn:9781449344764", "https://hpbn.co"]
},
"hoffman-web-application-security": {
"authors": "Hoffman, A.",
"publicationDate": "2024",
"title": "Web Application Security",
"subtitle": ["Second Edition"],
"hrefs": ["isbn:9781098143930"]
},
"martin-functional-design": {
"authors": "Martin, R. C.",
"publicationDate": "2023",
"title": "Functional Design: Principles, Patterns, and Practices",
"hrefs": ["isbn:9780138176518"]
},
"nelson-rpc": {
"authors": "Nelson, B. J.",
"publicationDate": "1981",
"title": "Remote Procedure Call",
"hrefs": ["https://dl.acm.org/doi/10.5555/910306"]
}
}

View File

@@ -1,4 +1,4 @@
### [О структуре этой книги][intro-structure]
### О структуре этой книги
Книга, которую вы держите в руках, посвящена разработке API как отдельной инженерной задаче. Хотя многое из того, о чём мы будем говорить, применимо к написанию любых программ, наша цель состояла прежде всего в описании тех проблем и подходов к их решению, которые характерны именно для предметной области API.

View File

@@ -1,4 +1,4 @@
### [Определение API][intro-api-definition]
### Определение API
Прежде чем говорить о разработке API, необходимо для начала договориться о том, что же такое API. Энциклопедия скажет нам, что API — это программный интерфейс приложений. Это точное определение, но бессмысленное. Примерно как определение человека по Платону: «двуногое без перьев» — определение точное, но никоим образом не дающее нам представление о том, чем на самом деле человек примечателен. (Да и не очень-то и точное: Диоген Синопский как-то ощипал петуха и заявил, что это человек Платона; пришлось дополнить определение уточнением «с плоскими ногтями».)

View File

@@ -1,4 +1,4 @@
### [Критерии качества API][intro-api-quality]
### Критерии качества API
Прежде чем переходить к изложению рекомендаций по проектированию архитектуры API, нам следует определиться с тем, что мы считаем качественным API, и какую пользу мы получаем от того, что наш API «качественный». Достаточно очевидно, что качество API определяется в первую очередь тем, насколько хорошо он помогает разработчикам решать стоящие перед ними задачи. (Оставим за скобками ситуации, когда вендор API преследует какие-то свои неявные цели, отличные от предоставления полезного продукта.)

View File

@@ -1,4 +1,4 @@
### [Выбор подхода к разработке API][intro-api-choosing-solutions]
### Выбор подхода к разработке API
Вернёмся к нашей аналогии API как акведука, соединяющего два различных контекста. Пытаясь сделать подключение к нашему сооружению удобным для потребителей, мы также сталкиваемся и с другой стороной вопроса: а как им (потребителям) было бы удобно? Как они привыкли? Нет ли в нашей предметной области каких-то распространённых стандартов подключения к водопроводу?

View File

@@ -1,4 +1,4 @@
### [API-first подход][intro-api-first-approach]
### API-first подход
На сегодняшний день всё больше и больше IT-компаний понимают и принимают важность концепции «API-first», т.е. парадигмы разработки ПО, в которой главной составляющей является разработка API.

View File

@@ -1,4 +1,4 @@
### [Обратная совместимость][intro-back-compat]
### Обратная совместимость
Обратная совместимость — это некоторая *временна́я* характеристика качества вашего API. Именно необходимость поддержания обратной совместимости отличает разработку API от разработки программного обеспечения вообще.

Some files were not shown because too many files have changed in this diff Show More