1
0
mirror of https://github.com/twirl/The-API-Book.git synced 2025-08-10 21:51:42 +02:00

fresh build

This commit is contained in:
Sergey Konstantinov
2023-05-01 14:49:19 +03:00
parent 072609e660
commit 74e88f7e86
7 changed files with 30 additions and 28 deletions

Binary file not shown.

View File

@@ -641,14 +641,14 @@ ul.references li p a.back-anchor {
<p>The APIs that belong to the first category are usually denoted as “REST” or “RESTful” APIs. The second category comprises different RPC formats and some service protocols, for example, SSH.</p>
<p><strong>Second</strong>, different HTTP APIs rely on different data formats:</p>
<ul>
<li>REST APIs and some RPCs (JSON-RPC, GraphQL, etc.) use the JSON format (sometimes with some additional endpoints to transfer binary data)</li>
<li>GRPC and some specialized RPC protocols like Apache Avro utilize binary formats (such as Protocol Buffers, FlatBuffers, or Apache Avro's own format)</li>
<li>finally, some RPC protocols (notably SOAP and XML-RPC) employ the XML data format (which is considered a rather outdated practice by many developers).</li>
<li>REST APIs and some RPCs (<a href="https://www.jsonrpc.org/">JSON-RPC</a>, <a href="https://graphql.org/">GraphQL</a>, etc.) use the <a href="https://www.ecma-international.org/publications-and-standards/standards/ecma-404/">JSON</a> format (sometimes with some additional endpoints to transfer binary data)</li>
<li><a href="https://grpc.io/">gRPC</a> and some specialized RPC protocols like <a href="https://avro.apache.org/docs/">Apache Avro</a> utilize binary formats (such as <a href="https://protobuf.dev/">Protocol Buffers</a>, <a href="https://flatbuffers.dev/">FlatBuffers</a>, or Apache Avro's own format)</li>
<li>finally, some RPC protocols (notably <a href="https://www.w3.org/TR/soap12/">SOAP</a> and <a href="http://xmlrpc.com/">XML-RPC</a>) employ the <a href="https://www.w3.org/TR/xml/">XML</a> data format (which is considered a rather outdated practice by many developers).</li>
</ul>
<p>All the above-mentioned technologies operate in significantly dissimilar paradigms, which give rise to rather hot “holy war” debates among software engineers. However, at the moment this book is being written we observe the choice for general-purpose APIs is reduced to the “REST API (in fact, JSON-over-HTTP) vs. GRPC vs. GraphQL” triad.</p>
<p>All the above-mentioned technologies operate in significantly dissimilar paradigms, which give rise to rather hot “holy war” debates among software engineers. However, at the moment this book is being written we observe the choice for general-purpose APIs is reduced to the “REST API (in fact, JSON-over-HTTP) vs. gRPC vs. GraphQL” triad.</p>
<h4>SDKs</h4>
<p>The term “SDK” is not, strictly speaking, related to APIs: this is a generic term for a software toolkit. As with “REST,” however, it got some popular reading as a client framework to work with some underlying API. This might be, for example, a wrapper to a client-server API or a UI to some OS API. The major difference from the APIs we discussed in the previous paragraph is that an “SDK” is implemented for a specific programming language and platform, and its purpose is translating the abstract language-agnostic set methods (comprising a client-server or an OS API) into concrete structures specific for the programming language and the platform.</p>
<p>Unlike client-server APIs, such SDKs can hardly be generalized as each of them is developed for a specific language-platform pair. There are some interoperable SDKs, notably cross-platform mobile (React Native, Flutter, Xamarin) and desktop (JavaFX, QT) frameworks and some highly-specialized solutions (Unity).</p>
<p>The term “SDK” (stands for “Software Development Kit”) is not, strictly speaking, related to APIs: this is a generic term for a software toolkit. As with “REST,” however, it got some popular reading as a client framework to work with some underlying API. This might be, for example, a wrapper to a client-server API or a UI to some OS API. The major difference from the APIs we discussed in the previous paragraph is that an “SDK” is implemented for a specific programming language and platform, and its purpose is translating the abstract language-agnostic set methods (comprising a client-server or an OS API) into concrete structures specific for the programming language and the platform.</p>
<p>Unlike client-server APIs, such SDKs can hardly be generalized as each of them is developed for a specific language-platform pair. Interoperable SDKs exist, notably cross-platform mobile (<a href="https://reactnative.dev/">React Native</a>, <a href="https://flutter.dev/">Flutter</a>, <a href="https://dotnet.microsoft.com/en-us/apps/xamarin">Xamarin</a>, etc.) and desktop (<a href="https://openjfx.io/">JavaFX</a>, <a href="https://www.qt.io/">QT</a>, etc.) frameworks and some highly-specialized solutions (<a href="https://docs.unity3d.com/Manual/index.html">Unity</a>). However, they are still narrowly focused on concrete technologies.</p>
<p>Still, SDKs feature some generality in terms of <em>the problems they solve</em>, and Section V of this book will be dedicated to solving these problems of translating contexts and making UI components.</p><div class="page-break"></div><h3><a href="#intro-api-quality" class="anchor" id="intro-api-quality">Chapter 4. API Quality Criteria</a><a href="#chapter-4" class="secondary-anchor" id="chapter-4"> </a></h3>
<p>Before we start laying out the recommendations, we ought to specify what API we consider “fine,” and what the benefits of having a “fine” API are.</p>
<p>Let's discuss the second question first. Obviously, API “finesse” is primarily defined through its capability to solve developers' and users' problems. (One could reasonably argue that solving problems might not be the main purpose of offering an API to developers. However, manipulating public opinion is not of interest to the author of this book. Here we assume that APIs exist primarily to help people, not for some other covertly declared purposes.)</p>
@@ -761,8 +761,8 @@ Cache-Control: no-cache
</ul>
<p>This four-step algorithm actually builds an API from top to bottom, from common requirements and use case scenarios down to a refined nomenclature of entities. In fact, moving this way will eventually conclude with a ready-to-use API, and that's why we value this approach highly.</p>
<p>It might seem that the most useful pieces of advice are given in the last chapter, but that's not true. The cost of a mistake made at certain levels differs. Fixing the naming is simple; revising the wrong understanding of what the API stands for is practically impossible.</p>
<p><strong>NB</strong>. Here and throughout we will illustrate the API design concepts using a hypothetical example of an API allowing for ordering a cup of coffee in city cafes. Just in case: this example is totally synthetic. If we were to design such an API in the real world, it would probably have very little in common with our fictional example.</p><div class="page-break"></div><h3><a href="#api-design-defining-field" class="anchor" id="api-design-defining-field">Chapter 10. Defining an Application Field</a><a href="#chapter-10" class="secondary-anchor" id="chapter-10"> </a></h3>
<p>The key question you should ask yourself before we start developing any software product, including an API, is: what problem do we solve? It should be asked four times, each time putting an emphasis on another word.</p>
<p><strong>NB</strong>. Here and throughout we will illustrate the API design concepts using a hypothetical example of an API that allows ordering a cup of coffee in city cafes. Just in case: this example is totally synthetic. If we were to design such an API in the real world, it would probably have very little in common with our fictional example.</p><div class="page-break"></div><h3><a href="#api-design-defining-field" class="anchor" id="api-design-defining-field">Chapter 10. Defining an Application Field</a><a href="#chapter-10" class="secondary-anchor" id="chapter-10"> </a></h3>
<p>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.</p>
<ol>
<li>
<p><em>What</em> problem do we solve? Could we clearly outline the situation in which our hypothetical API is needed by developers?</p>
@@ -780,7 +780,7 @@ Cache-Control: no-cache
<p>So, let's imagine that we are going to develop an API for automated coffee ordering in city cafes, and let's apply the key question to it.</p>
<ol>
<li>
<p>Why would someone need an API to make a coffee? Why ordering a coffee via “human-to-human” or “human-to-machine” interfaces is inconvenient, why have a “machine-to-machine” interface?</p>
<p>Why would someone need an API to make coffee? Why is ordering coffee via “human-to-human” or “human-to-machine” interfaces inconvenient? Why have a “machine-to-machine” interface?</p>
<ul>
<li>Possibly, we're solving awareness and selection problems? To provide humans with full knowledge of what options they have right now and right here.</li>
<li>Possibly, we're optimizing waiting times? To save the time people waste while waiting for their beverages.</li>
@@ -790,31 +790,31 @@ Cache-Control: no-cache
<p>Here and throughout we assume, to make our example more complex and bizarre, that we are optimizing all three factors.</p>
</li>
<li>
<p>Do the problems we outlined really exist? Do we really observe unequal coffee-machines utilization in the mornings? Do people really suffer from the inability to find nearby a toffee nut latte they long for? Do they really care about the minutes they spend in lines?</p>
<p>Do the problems we outlined really exist? Do we really observe unequal coffee-machine utilization in the mornings? Do people really suffer from the inability to find nearby a toffee nut latte they long for? Do they really care about the minutes they spend in lines?</p>
</li>
<li>
<p>Do we actually have resources to solve the problem? Do we have access to a sufficient number of coffee machines and users to ensure the system's efficiency?</p>
</li>
<li>
<p>Finally, will we really solve a problem? How we're going to quantify the impact our API makes?</p>
<p>Finally, will we really solve a problem? How are we going to quantify the impact our API makes?</p>
</li>
</ol>
<p>In general, there are no simple answers to those questions. Ideally, you should start the work having all the relevant metrics measured: how much time is wasted exactly, and what numbers we're going to achieve providing we have such coffee machines density. Let us also stress that in the real world obtaining these numbers is only possible if you're entering a stable market. If you try to create something new, your only option is to rely on your intuition.</p>
<p>In general, there are no simple answers to those questions. Ideally, you should start the work with all the relevant metrics measured: how much time is wasted exactly, and what numbers will we achieve providing we have such a coffee machine density. Let us also stress that in the real world obtaining these numbers is only possible if you're entering a stable market. If you try to create something new, your only option is to rely on your intuition.</p>
<h4>Why an API?</h4>
<p>Since our book is dedicated not to software development per se, but to developing APIs, we should look at all those questions from a different angle: why does solving those problems specifically require an API, not simply a specialized software application? In terms of our fictional example, we should ask ourselves: why provide a service to developers, allowing for brewing coffee to end users, instead of just making an app?</p>
<p>Since our book is dedicated not to software development per se, but to developing APIs, we should look at all those questions from a different angle: why does solving those problems specifically require an API, not simply a specialized software application? In terms of our fictional example, we should ask ourselves: why provide a service to developers that allows for brewing coffee for end users instead of just making an app?</p>
<p>In other words, there must be a solid reason to split two software development domains: there are vendors that provide APIs, and there are vendors that develop services for end users. Their interests are somehow different to such an extent that coupling these two roles in one entity is undesirable. We will talk about the motivation to specifically provide APIs instead of apps (or as an addition to an app) in more detail in Section III.</p>
<p>We should also note that you should try making an API when, and only when, your answer to question (3) is "because that's our area of expertise". Developing APIs is a sort of meta-engineering: you're writing some software to allow other vendors to develop software to solve users' problems. You must possess expertise in both domains (APIs and user products) to design your API well.</p>
<p>As for our speculative example, let us imagine that in the nearby future, some tectonic shift happened within the coffee brewing market. Two distinct player groups took shape: some companies provide “hardware,” i.e., coffee machines; other companies have access to customer auditory. Something like the modern-day flights market looks like: there are air companies, which actually transport passengers; and there are trip planning services where users are choosing between trip variants the system generates for them. We're aggregating hardware access to allow app vendors for ordering freshly brewed coffee.</p>
<p>We should also note that you should try making an API when, and only when, your answer to question (3) is because that's our area of expertise. Developing APIs is a sort of meta-engineering: you're writing some software to allow other vendors to develop software to solve users' problems. You must possess expertise in both domains (APIs and user products) to design your API well.</p>
<p>As for our speculative example, let us imagine that in the nearby future, some tectonic shift happened within the coffee brewing market. Two distinct player groups took shape: some companies provide “hardware,” i.e., coffee machines; other companies have access to customer audiences. Something like the modern-day flights market looks like: there are air companies that actually transport passengers, and there are trip planning services where users choose between trip options the system generates for them. We're aggregating hardware access to allow app vendors to order freshly brewed coffee.</p>
<h4>What and How</h4>
<p>After finishing all these theoretical exercises, we should proceed right to designing and developing the API, having a decent understanding of two things:</p>
<p>After finishing all these theoretical exercises, we should proceed directly to designing and developing the API, having a decent understanding of two things:</p>
<ul>
<li><em>what</em> we're doing, exactly;</li>
<li><em>how</em> we're doing it, exactly.</li>
<li><em>what</em> we're doing exactly</li>
<li><em>how</em> we're doing it exactly.</li>
</ul>
<p>In our coffee case, we are:</p>
<ul>
<li>providing an API to services with a larger audience, so their users may order a cup of coffee in the most efficient and convenient manner;</li>
<li>abstracting access to coffee machines' “hardware” and developing generalized software methods to select a beverage kind and some location to make an order.</li>
<li>providing an API to services with a larger audience so that their users may order a cup of coffee in the most efficient and convenient manner</li>
<li>abstracting access to coffee machines' “hardware” and developing generalized software methods to select a beverage kind and a location to make an order.</li>
</ul><div class="page-break"></div><h3><a href="#api-design-separating-abstractions" class="anchor" id="api-design-separating-abstractions">Chapter 11. Separating Abstraction Levels</a><a href="#chapter-11" class="secondary-anchor" id="chapter-11"> </a></h3>
<p>“Separate abstraction levels in your code” is possibly the most general advice to software developers. However, we don't think it would be a grave exaggeration to say that abstraction level separation is also the most difficult task for API developers.</p>
<p>Before proceeding to the theory, we should formulate clearly <em>why</em> abstraction levels are so important, and what goals we're trying to achieve by separating them.</p>
@@ -2744,6 +2744,7 @@ const pendingOrders = await api.
<p>Employing task queues might lead to some problems specific to the queue technology itself, i.e., not related to the business logic of the request handler:</p>
<ul>
<li>tasks might be “lost” and never processed</li>
<li>events might be received in the wrong order or processed twice, which might affect public interfaces</li>
<li>under the task identifier, wrong data might be published (corresponding to some other task) or the data might be corrupted.</li>
</ul>
<p>These issues will be totally unexpected by developers and will lead to bugs in applications that are very hard to reproduce.</p>

Binary file not shown.

Binary file not shown.

View File

@@ -641,15 +641,15 @@ ul.references li p a.back-anchor {
<p>К первой категории относятся API, которые принято обозначать словом «REST» или «RESTful». а ко второй — все виды RPC, а также прикладные протоколы типа SSH.</p>
<p><strong>Во-вторых</strong>, реализации HTTP API опираются на разные форматы передаваемых данных:</p>
<ul>
<li>REST API и некоторые RPC (JSON-RPC, GraphQL) полагаются в основном на формат JSON (опционально дополненный передачей бинарных файлов);</li>
<li>GRPC, а также Apache Avro и другие специализированные RPC-протоколы полагаются на бинарные форматы (такие как Protocol Buffers, FlatBuffers и собственный формат Apache Avro);</li>
<li>наконец, некоторые RPC-протоколы (SOAP, XML-RPC) используют для передачи данных формат XML (что многими разработчиками сегодня воспринимается скорее как устаревшая практика).</li>
<li>REST API и некоторые RPC (<a href="https://www.jsonrpc.org/">JSON-RPC</a>, <a href="https://graphql.org/">GraphQL</a>) полагаются в основном на формат <a href="https://www.ecma-international.org/publications-and-standards/standards/ecma-404/">JSON</a> (опционально дополненный передачей бинарных файлов);</li>
<li><a href="https://grpc.io/">gRPC</a>, а также <a href="https://avro.apache.org/docs/">Apache Avro</a> и другие специализированные RPC-протоколы полагаются на бинарные форматы (такие как <a href="https://protobuf.dev/">Protocol Buffers</a>, <a href="https://flatbuffers.dev/">FlatBuffers</a> и собственный формат Apache Avro);</li>
<li>наконец, некоторые RPC-протоколы (<a href="https://www.w3.org/TR/soap12/">SOAP</a>, <a href="http://xmlrpc.com/">XML-RPC</a>) используют для передачи данных формат <a href="https://www.w3.org/TR/xml/">XML</a> (что многими разработчиками сегодня воспринимается скорее как устаревшая практика).</li>
</ul>
<p>Все перечисленные технологии оперируют существенно разными парадигмами — и вызывают естественным образом большое количество холиваров — хотя на момент написания этой книги можно констатировать, что для API общего назначения выбор практически сводится к триаде «REST API (фактически, JSON over HTTP) против GRPC против GraphQL».</p>
<p>Все перечисленные технологии оперируют существенно разными парадигмами — и вызывают естественным образом большое количество холиваров — хотя на момент написания этой книги можно констатировать, что для API общего назначения выбор практически сводится к триаде «REST API (фактически, JSON over HTTP) против gRPC против GraphQL».</p>
<p>HTTP API будет посвящён раздел IV; мы также отдельно и подробно рассмотрим концепцию «REST API», поскольку, в отличие от GRPC и GraphQL, она является более гибкой и низкоуровневой — но и приводит к большему непониманию по той же причине.</p>
<h4>SDK</h4>
<p>Понятие SDK, вообще говоря, вовсе не относится к API: это просто термин для некоторого набора программных инструментов. Однако, как и за «REST», за ним закрепилось некоторое определённое толкование — как клиентского фреймворка для работы с некоторым API. Это может быть как обёртка над клиент-серверным API, так и UI-библиотека в рамках какой-то платформы. Существенным отличием от вышеперечисленных API является то, что «SDK» реализован для какого-то конкретного языка программирования, и его целью является как раз превращение абстрактного набора методов (клиент-серверного API или API операционной системы) в конкретные структуры, разработанные для конкретного языка программирования и конкретной платформы.</p>
<p>В отличие от клиент-серверных API, обобщить такие SDK не представляется возможным, т.к. каждый из них написан под конкретное сочетание язык программирования-платформа. Из интероперабельных технологий в мире SDK можно привести в пример разве что кросс-платформенные мобильные (React Native, Flutter, Xamarin) и десктопные фреймворки (JavaFX, QT) и некоторые узкоспециализированные решения (Unity).</p>
<p>Понятие SDK (Software Development Kit, «набор для разработки программного обеспечения»), вообще говоря, вовсе не относится к API: это просто термин для некоторого набора программных инструментов. Однако, как и за «REST», за ним закрепилось некоторое определённое толкование — как клиентского фреймворка для работы с некоторым API. Это может быть как обёртка над клиент-серверным API, так и UI-библиотека в рамках какой-то платформы. Существенным отличием от вышеперечисленных API является то, что «SDK» реализован для какого-то конкретного языка программирования, и его целью является как раз превращение абстрактного набора методов (клиент-серверного API или API операционной системы) в конкретные структуры, разработанные для конкретного языка программирования и конкретной платформы.</p>
<p>В отличие от клиент-серверных API, обобщить такие SDK не представляется возможным, т.к. каждый из них написан под конкретное сочетание язык программирования-платформа. Из интероперабельных технологий в мире SDK можно привести в пример кросс-платформенные мобильные (<a href="https://reactnative.dev/">React Native</a>, <a href="https://flutter.dev/">Flutter</a>, <a href="https://dotnet.microsoft.com/en-us/apps/xamarin">Xamarin</a>) и десктопные фреймворки (<a href="https://openjfx.io/">JavaFX</a>, QT) и некоторые узкоспециализированные решения (<a href="https://docs.unity3d.com/Manual/index.html">Unity</a>), однако все они направлены на работу с конкретными технологиями и весьма специфичны.</p>
<p>Тем не менее, SDK обладают общностью <em>на уровне задач</em>, которые они решают, и именно этому (решению проблем трансляции и предоставления UI-компонент) будет посвящён раздел V настоящей книги.</p><div class="page-break"></div><h3><a href="#intro-api-quality" class="anchor" id="intro-api-quality">Глава 4. Критерии качества API</a><a href="#chapter-4" class="secondary-anchor" id="chapter-4"> </a></h3>
<p>Прежде чем излагать рекомендации, нам следует определиться с тем, что мы считаем «хорошим» API, и какую пользу мы получаем от того, что наш API «хороший».</p>
<p>Начнём со второго вопроса. Очевидно, «хорошесть» API определяется в первую очередь тем, насколько он помогает разработчикам решать стоящие перед ними задачи. (Можно резонно возразить, что решение задач, стоящих перед разработчиками, не обязательно влечёт за собой выполнение целей, которые мы ставим перед собой, предлагая разработчикам API. Однако манипуляция общественным мнением не входит в область интересов автора этой книги: здесь и далее предполагается, что API существует в первую очередь для того, чтобы разработчики решали с его помощью свои задачи, а не ради каких-то завуалированных целей).</p>
@@ -700,7 +700,7 @@ ul.references li p a.back-anchor {
<p>Более подробно о смысле и политиках такого версионирования читайте в главе <a href="#back-compat-statement">«Постановка проблемы обратной совместимости»</a>.</p><div class="page-break"></div><h3><a href="#intro-terms-notation" class="anchor" id="intro-terms-notation">Глава 8. Условные обозначения и терминология</a><a href="#chapter-8" class="secondary-anchor" id="chapter-8"> </a></h3>
<p>В мире разработки программного обеспечения существует множество различных парадигм разработки, адепты которых зачастую настроены весьма воинственно по отношению к адептам других парадигм. Поэтому при написании этой книги мы намеренно избегали слов «метод», «объект», «функция» и так далее, используя нейтральный термин «сущность», под которым понимается некоторая атомарная единица функциональности: класс, метод, объект, монада, прототип (нужное подчеркнуть).</p>
<p>Для составных частей сущности, к сожалению, достаточно нейтрального термина нам придумать не удалось, поэтому мы используем слова «поля» и «методы».</p>
<p>Большинство примеров API в общих разделах будут даны в виде JSON-over-HTTP-эндпойтов. Это некоторая условность, которая помогает описать концепции, как нам кажется, максимально понятно. Вместо <code>GET /v1/orders</code> вполне может быть вызов метода <code>orders.get()</code>, локальный или удалённый; вместо JSON может быть любой другой формат данных. Смысл утверждений от этого не меняется.</p>
<p>Большинство примеров API в общих разделах будут даны в виде абстрактных обращений по HTTP-протоколу к некоторой специфической именованной функции API («эндпойнту») с передачей данных в формате JSON. Это некоторая условность, которая помогает описать концепции, как нам кажется, максимально понятно. Вместо <code>GET /v1/orders</code> вполне может быть вызов метода <code>orders.get()</code>, локальный или удалённый; вместо JSON может быть любой другой формат данных. Смысл утверждений от этого не меняется.</p>
<p>Рассмотрим следующую запись:</p>
<pre><code>// Описание метода
POST /v1/bucket/{id}/some-resource⮠
@@ -2745,6 +2745,7 @@ const pendingOrders = await api.
<p>Использование очередей заданий может повлечь за собой свои собственные проблемы, не связанные с собственно обработкой запроса:</p>
<ul>
<li>задание может быть «потеряно», т.е. никогда не быть обработанным;</li>
<li>события смены статусов могут приходить в неверном порядке и/или повторяться, что может повлиять на публичные интерфейсы;</li>
<li>под идентификатором задания могут быть по ошибке размещены неправильные данные (соответствующие другому заданию) или же данные могут быть повреждены.</li>
</ul>
<p>Эти ситуации могут оказаться совершенно неожиданными для разработчиков и приводить к крайне сложным в воспроизведении ошибкам в приложениях.</p>

Binary file not shown.

View File

@@ -51,7 +51,7 @@
<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>Вы можете скачать книгу «API» в формате <a href="API.ru.pdf">PDF</a> / <a href="API.ru.epub">EPUB</a> или <a href="API.ru.html">прочитать её онлайе</a>.
<p>Вы можете скачать книгу «API» в формате <a href="API.ru.pdf">PDF</a> / <a href="API.ru.epub">EPUB</a> или <a href="API.ru.html">прочитать её онлайн</a>.
</p>
<h3>Содержание</h3>
<ul><li>