1
0
mirror of https://github.com/twirl/The-API-Book.git synced 2024-11-30 08:06:47 +02:00

typos & style fix

This commit is contained in:
Sergey Konstantinov 2023-04-25 10:35:00 +03:00
parent 22cc6692b5
commit 4ec0e03e1c
17 changed files with 1272 additions and 1433 deletions

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@ -44,9 +44,9 @@
</nav>
<p>API-first development is one of the hottest technical topics nowadays since many companies started to realize that API serves as a multiplicator to their opportunities—but it also amplifies the design mistakes as well.</p>
<p>This book is written to share the expertise and describe the best practices in designing and developing APIs. It comprises six sections dedicated to:</p>
<ul><li>the API design</li>
<ul><li>The API design</li>
<li>— API patterns</li>
<li>backwards compatibility</li>
<li>Backwards compatibility</li>
<li>— HTTP API & REST</li>
<li>— SDK and UI libraries</li>
<li>— API product management.</ul>
@ -59,95 +59,97 @@
<ul>
<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-back-compat">Chapter 4. On Backwards Compatibility</a></li>
<li><a href="API.en.html#intro-versioning">Chapter 5. On Versioning</a></li>
<li><a href="API.en.html#intro-terms-notation">Chapter 6. Terms and Notation Keys</a></li>
<li><a href="API.en.html#intro-api-solutions-overview">Chapter 3. Overview of Existing API Development Solutions</a></li>
<li><a href="API.en.html#intro-api-quality">Chapter 4. API Quality Criteria</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 Backwards 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>
<ul>
<li><a href="API.en.html#api-design-context-pyramid">Chapter 7. The API Contexts Pyramid</a></li>
<li><a href="API.en.html#api-design-defining-field">Chapter 8. Defining an Application Field</a></li>
<li><a href="API.en.html#api-design-separating-abstractions">Chapter 9. Separating Abstraction Levels</a></li>
<li><a href="API.en.html#api-design-isolating-responsibility">Chapter 10. Isolating Responsibility Areas</a></li>
<li><a href="API.en.html#api-design-describing-interfaces">Chapter 11. Describing Final Interfaces</a></li>
<li><a href="API.en.html#api-design-annex">Chapter 12. 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">[Work in Progress] Section II. The API Patterns</a></h4>
<ul>
<li><a href="API.en.html#chapter-13">Chapter 13. On Design Patterns in the API Context</a></li>
<li><a href="API.en.html#chapter-14">Chapter 14. Authenticating Partners and Authorizing API Calls</a></li>
<li><a href="API.en.html#chapter-15">Chapter 15. Synchronization Strategies</a></li>
<li><a href="API.en.html#chapter-16">Chapter 16. Eventual Consistency</a></li>
<li><a href="API.en.html#chapter-17">Chapter 17. Asynchronicity and Time Management</a></li>
<li><a href="API.en.html#chapter-18">Chapter 18. Lists and Accessing Them</a></li>
<li><a href="API.en.html#chapter-19">Chapter 19. Bidirectional Data Flows. Push and Poll Models</a></li>
<li><a href="API.en.html#chapter-20">Chapter 20. Organization of Notification Systems</a></li>
<li><a href="API.en.html#chapter-21">Chapter 21. Atomicity</a></li>
<li><a href="API.en.html#chapter-22">Chapter 22. Partial Updates</a></li>
<li><a href="API.en.html#chapter-23">Chapter 23. 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#chapter-18">Chapter 18. Eventual Consistency</a></li>
<li><a href="API.en.html#chapter-19">Chapter 19. Asynchronicity and Time Management</a></li>
<li><a href="API.en.html#chapter-20">Chapter 20. Lists and Accessing Them</a></li>
<li><a href="API.en.html#chapter-21">Chapter 21. Bidirectional Data Flows. Push and Poll Models</a></li>
<li><a href="API.en.html#chapter-22">Chapter 22. Organization of Notification Systems</a></li>
<li><a href="API.en.html#chapter-23">Chapter 23. Atomicity</a></li>
<li><a href="API.en.html#chapter-24">Chapter 24. Partial Updates</a></li>
<li><a href="API.en.html#chapter-25">Chapter 25. Degradation and Predictability</a></li>
</ul>
</li>
<li>
<h4><a href="API.en.html#section-4">Section III. The Backwards Compatibility</a></h4>
<ul>
<li><a href="API.en.html#back-compat-statement">Chapter 24. The Backwards Compatibility Problem Statement</a></li>
<li><a href="API.en.html#back-compat-iceberg-waterline">Chapter 25. On the Waterline of the Iceberg</a></li>
<li><a href="API.en.html#back-compat-abstracting-extending">Chapter 26. Extending through Abstracting</a></li>
<li><a href="API.en.html#back-compat-strong-coupling">Chapter 27. Strong Coupling and Related Problems</a></li>
<li><a href="API.en.html#back-compat-weak-coupling">Chapter 28. Weak Coupling</a></li>
<li><a href="API.en.html#back-compat-universal-interfaces">Chapter 29. Interfaces as a Universal Pattern</a></li>
<li><a href="API.en.html#back-compat-serenity-notepad">Chapter 30. The Serenity Notepad</a></li>
<li><a href="API.en.html#back-compat-statement">Chapter 26. The Backwards 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">[Work in Progress] Section IV. The HTTP API & REST</a></h4>
<ul>
<li><a href="API.en.html#chapter-31">Chapter 31. On HTTP API Concept and Terminology</a></li>
<li><a href="API.en.html#chapter-32">Chapter 32. The REST Myth</a></li>
<li><a href="API.en.html#chapter-33">Chapter 33. The Semantics of the HTTP Request Components</a></li>
<li><a href="API.en.html#chapter-34">Chapter 34. The HTTP API Advantages and Disadvantages</a></li>
<li><a href="API.en.html#chapter-35">Chapter 35. HTTP API Organization Principles</a></li>
<li><a href="API.en.html#chapter-36">Chapter 36. Working with HTTP API Errors</a></li>
<li><a href="API.en.html#chapter-37">Chapter 37. Organizing the HTTP API Resources and Operations</a></li>
<li><a href="API.en.html#chapter-38">Chapter 38. Final Provisions and General Recommendations</a></li>
<li><a href="API.en.html#chapter-33">Chapter 33. On HTTP API Concept and Terminology</a></li>
<li><a href="API.en.html#chapter-34">Chapter 34. The REST Myth</a></li>
<li><a href="API.en.html#chapter-35">Chapter 35. The Semantics of the HTTP Request Components</a></li>
<li><a href="API.en.html#chapter-36">Chapter 36. The HTTP API Advantages and Disadvantages</a></li>
<li><a href="API.en.html#chapter-37">Chapter 37. HTTP API Organization Principles</a></li>
<li><a href="API.en.html#chapter-38">Chapter 38. Working with HTTP API Errors</a></li>
<li><a href="API.en.html#chapter-39">Chapter 39. Organizing the HTTP API Resources and Operations</a></li>
<li><a href="API.en.html#chapter-40">Chapter 40. Final Provisions and General Recommendations</a></li>
</ul>
</li>
<li>
<h4><a href="API.en.html#section-6">[Work in Progress] Section V. The SDK & UI Libraries</a></h4>
<ul>
<li><a href="API.en.html#chapter-39">Chapter 39. On the Content of This Section</a></li>
<li><a href="API.en.html#chapter-40">Chapter 40. The SDK: Problems and Solutions</a></li>
<li><a href="API.en.html#chapter-41">Chapter 41. The Code Generation Pattern</a></li>
<li><a href="API.en.html#chapter-42">Chapter 42. The UI Components</a></li>
<li><a href="API.en.html#chapter-43">Chapter 43. Decomposing UI Components</a></li>
<li><a href="API.en.html#chapter-44">Chapter 44. The MV* Frameworks</a></li>
<li><a href="API.en.html#chapter-45">Chapter 45. The Backend-Driven UI</a></li>
<li><a href="API.en.html#chapter-46">Chapter 46. Shared Resources and Asynchronous Locks</a></li>
<li><a href="API.en.html#chapter-47">Chapter 47. Computed Properties</a></li>
<li><a href="API.en.html#chapter-48">Chapter 48. Conclusion</a></li>
<li><a href="API.en.html#chapter-41">Chapter 41. On the Content of This Section</a></li>
<li><a href="API.en.html#chapter-42">Chapter 42. The SDK: Problems and Solutions</a></li>
<li><a href="API.en.html#chapter-43">Chapter 43. The Code Generation Pattern</a></li>
<li><a href="API.en.html#chapter-44">Chapter 44. The UI Components</a></li>
<li><a href="API.en.html#chapter-45">Chapter 45. Decomposing UI Components</a></li>
<li><a href="API.en.html#chapter-46">Chapter 46. The MV* Frameworks</a></li>
<li><a href="API.en.html#chapter-47">Chapter 47. The Backend-Driven UI</a></li>
<li><a href="API.en.html#chapter-48">Chapter 48. Shared Resources and Asynchronous Locks</a></li>
<li><a href="API.en.html#chapter-49">Chapter 49. Computed Properties</a></li>
<li><a href="API.en.html#chapter-50">Chapter 50. Conclusion</a></li>
</ul>
</li>
<li>
<h4><a href="API.en.html#section-7">Section VI. The API Product</a></h4>
<ul>
<li><a href="API.en.html#api-product">Chapter 49. API as a Product</a></li>
<li><a href="API.en.html#api-product-business-models">Chapter 50. The API Business Models</a></li>
<li><a href="API.en.html#api-product-vision">Chapter 51. Developing a Product Vision</a></li>
<li><a href="API.en.html#api-product-devrel">Chapter 52. Communicating with Developers</a></li>
<li><a href="API.en.html#api-product-business-comms">Chapter 53. Communicating with Business Owners</a></li>
<li><a href="API.en.html#api-product-range">Chapter 54. The API Services Range</a></li>
<li><a href="API.en.html#api-product-kpi">Chapter 55. The API Key Performance Indicators</a></li>
<li><a href="API.en.html#api-product-antifraud">Chapter 56. Identifying Users and Preventing Fraud</a></li>
<li><a href="API.en.html#api-product-tos-violations">Chapter 57. The Technical Means of Preventing ToS Violations</a></li>
<li><a href="API.en.html#api-product-customer-support">Chapter 58. Supporting customers</a></li>
<li><a href="API.en.html#api-product-documentation">Chapter 59. The Documentation</a></li>
<li><a href="API.en.html#api-product-testing">Chapter 60. The Testing Environment</a></li>
<li><a href="API.en.html#api-product-expectations">Chapter 61. Managing Expectations</a></li>
<li><a href="API.en.html#api-product">Chapter 51. API as a Product</a></li>
<li><a href="API.en.html#api-product-business-models">Chapter 52. The API Business Models</a></li>
<li><a href="API.en.html#api-product-vision">Chapter 53. Developing a Product Vision</a></li>
<li><a href="API.en.html#api-product-devrel">Chapter 54. Communicating with Developers</a></li>
<li><a href="API.en.html#api-product-business-comms">Chapter 55. Communicating with Business Owners</a></li>
<li><a href="API.en.html#api-product-range">Chapter 56. The API Services Range</a></li>
<li><a href="API.en.html#api-product-kpi">Chapter 57. The API Key Performance Indicators</a></li>
<li><a href="API.en.html#api-product-antifraud">Chapter 58. Identifying Users and Preventing Fraud</a></li>
<li><a href="API.en.html#api-product-tos-violations">Chapter 59. The Technical Means of Preventing ToS Violations</a></li>
<li><a href="API.en.html#api-product-customer-support">Chapter 60. Supporting customers</a></li>
<li><a href="API.en.html#api-product-documentation">Chapter 61. The Documentation</a></li>
<li><a href="API.en.html#api-product-testing">Chapter 62. The Testing Environment</a></li>
<li><a href="API.en.html#api-product-expectations">Chapter 63. Managing Expectations</a></li>
</ul>
</li>
</ul>

View File

@ -40,7 +40,7 @@
<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="medium" href="https://twirl.medium.com/">Medium</a>
<br />Поддержите эту работу на <a class="patreon" href="https://www.patreon.com/yatwirl">Patreon</a>
<br />Поделиться: <a class="share share-vk" href="https://vk.com/share.php?url=https%3A%2F%2Ftwirl.github.io%2FThe-API-Book%2Findex.ru.html" target="_blank"></a> · <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="http://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/>⚙️⚙️⚙️
<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="http://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>
@ -59,95 +59,97 @@
<ul>
<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-back-compat">Глава 4. Обратная совместимость</a></li>
<li><a href="API.ru.html#intro-versioning">Глава 5. О версионировании</a></li>
<li><a href="API.ru.html#intro-terms-notation">Глава 6. Условные обозначения и терминология</a></li>
<li><a href="API.ru.html#intro-api-solutions-overview">Глава 3. Обзор существующих решений в области разработки API</a></li>
<li><a href="API.ru.html#intro-api-quality">Глава 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>
<ul>
<li><a href="API.ru.html#api-design-context-pyramid">Глава 7. Пирамида контекстов API</a></li>
<li><a href="API.ru.html#api-design-defining-field">Глава 8. Определение области применения</a></li>
<li><a href="API.ru.html#api-design-separating-abstractions">Глава 9. Разделение уровней абстракции</a></li>
<li><a href="API.ru.html#api-design-isolating-responsibility">Глава 10. Разграничение областей ответственности</a></li>
<li><a href="API.ru.html#api-design-describing-interfaces">Глава 11. Описание конечных интерфейсов</a></li>
<li><a href="API.ru.html#api-design-annex">Глава 12. Приложение к разделу 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>
<ul>
<li><a href="API.ru.html#chapter-13">Глава 13. О паттернах проектирования в контексте API</a></li>
<li><a href="API.ru.html#chapter-14">Глава 14. Аутентификация партнёров и авторизация вызовов API</a></li>
<li><a href="API.ru.html#chapter-15">Глава 15. Стратегии синхронизации</a></li>
<li><a href="API.ru.html#chapter-16">Глава 16. Слабая консистентность</a></li>
<li><a href="API.ru.html#chapter-17">Глава 17. Асинхронность и управление временем</a></li>
<li><a href="API.ru.html#chapter-18">Глава 18. Списки и организация доступа к ним</a></li>
<li><a href="API.ru.html#chapter-19">Глава 19. Двунаправленные потоки данных. Push и poll-модели</a></li>
<li><a href="API.ru.html#chapter-20">Глава 20. Варианты организации системы нотификаций</a></li>
<li><a href="API.ru.html#chapter-21">Глава 21. Атомарность</a></li>
<li><a href="API.ru.html#chapter-22">Глава 22. Частичные обновления</a></li>
<li><a href="API.ru.html#chapter-23">Глава 23. Деградация и предсказуемость</a></li>
<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#chapter-18">Глава 18. Слабая консистентность</a></li>
<li><a href="API.ru.html#chapter-19">Глава 19. Асинхронность и управление временем</a></li>
<li><a href="API.ru.html#chapter-20">Глава 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#chapter-22">Глава 22. Варианты организации системы нотификаций</a></li>
<li><a href="API.ru.html#chapter-23">Глава 23. Атомарность</a></li>
<li><a href="API.ru.html#chapter-24">Глава 24. Частичные обновления</a></li>
<li><a href="API.ru.html#chapter-25">Глава 25. Деградация и предсказуемость</a></li>
</ul>
</li>
<li>
<h4><a href="API.ru.html#section-4">Раздел III. Обратная совместимость</a></h4>
<ul>
<li><a href="API.ru.html#back-compat-statement">Глава 24. Постановка проблемы обратной совместимости</a></li>
<li><a href="API.ru.html#back-compat-iceberg-waterline">Глава 25. О ватерлинии айсберга</a></li>
<li><a href="API.ru.html#back-compat-abstracting-extending">Глава 26. Расширение через абстрагирование</a></li>
<li><a href="API.ru.html#back-compat-strong-coupling">Глава 27. Сильная связность и сопутствующие проблемы</a></li>
<li><a href="API.ru.html#back-compat-weak-coupling">Глава 28. Слабая связность</a></li>
<li><a href="API.ru.html#back-compat-universal-interfaces">Глава 29. Интерфейсы как универсальный паттерн</a></li>
<li><a href="API.ru.html#back-compat-serenity-notepad">Глава 30. Блокнот душевного покоя</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>
<ul>
<li><a href="API.ru.html#chapter-31">Глава 31. О концепции HTTP API и терминологии</a></li>
<li><a href="API.ru.html#chapter-32">Глава 32. Мифология REST</a></li>
<li><a href="API.ru.html#chapter-33">Глава 33. Составляющие HTTP запросов и их семантика</a></li>
<li><a href="API.ru.html#chapter-34">Глава 34. Преимущества и недостатки HTTP API</a></li>
<li><a href="API.ru.html#chapter-35">Глава 35. Принципы организации HTTP API</a></li>
<li><a href="API.ru.html#chapter-36">Глава 36. Работа с ошибками в HTTP API</a></li>
<li><a href="API.ru.html#chapter-37">Глава 37. Организация URL ресурсов и операций над ними в HTTP API</a></li>
<li><a href="API.ru.html#chapter-38">Глава 38. Заключительные положения и общие рекомендации</a></li>
<li><a href="API.ru.html#chapter-33">Глава 33. О концепции HTTP API и терминологии</a></li>
<li><a href="API.ru.html#chapter-34">Глава 34. Мифология REST</a></li>
<li><a href="API.ru.html#chapter-35">Глава 35. Составляющие HTTP запросов и их семантика</a></li>
<li><a href="API.ru.html#chapter-36">Глава 36. Преимущества и недостатки HTTP API</a></li>
<li><a href="API.ru.html#chapter-37">Глава 37. Принципы организации HTTP API</a></li>
<li><a href="API.ru.html#chapter-38">Глава 38. Работа с ошибками в HTTP API</a></li>
<li><a href="API.ru.html#chapter-39">Глава 39. Организация URL ресурсов и операций над ними в HTTP API</a></li>
<li><a href="API.ru.html#chapter-40">Глава 40. Заключительные положения и общие рекомендации</a></li>
</ul>
</li>
<li>
<h4><a href="API.ru.html#section-6">[В разработке] Раздел V. SDK и UI</a></h4>
<ul>
<li><a href="API.ru.html#chapter-39">Глава 39. О содержании раздела</a></li>
<li><a href="API.ru.html#chapter-40">Глава 40. SDK: проблемы и решения</a></li>
<li><a href="API.ru.html#chapter-41">Глава 41. Кодогенерация</a></li>
<li><a href="API.ru.html#chapter-42">Глава 42. UI-компоненты</a></li>
<li><a href="API.ru.html#chapter-43">Глава 43. Декомпозиция UI-компонентов. MV*-подходы</a></li>
<li><a href="API.ru.html#chapter-44">Глава 44. MV*-фреймворки</a></li>
<li><a href="API.ru.html#chapter-45">Глава 45. Backend-Driven UI</a></li>
<li><a href="API.ru.html#chapter-46">Глава 46. Разделяемые ресурсы и асинхронные блокировки</a></li>
<li><a href="API.ru.html#chapter-47">Глава 47. Вычисляемые свойства</a></li>
<li><a href="API.ru.html#chapter-48">Глава 48. В заключение</a></li>
<li><a href="API.ru.html#chapter-41">Глава 41. О содержании раздела</a></li>
<li><a href="API.ru.html#chapter-42">Глава 42. SDK: проблемы и решения</a></li>
<li><a href="API.ru.html#chapter-43">Глава 43. Кодогенерация</a></li>
<li><a href="API.ru.html#chapter-44">Глава 44. UI-компоненты</a></li>
<li><a href="API.ru.html#chapter-45">Глава 45. Декомпозиция UI-компонентов. MV*-подходы</a></li>
<li><a href="API.ru.html#chapter-46">Глава 46. MV*-фреймворки</a></li>
<li><a href="API.ru.html#chapter-47">Глава 47. Backend-Driven UI</a></li>
<li><a href="API.ru.html#chapter-48">Глава 48. Разделяемые ресурсы и асинхронные блокировки</a></li>
<li><a href="API.ru.html#chapter-49">Глава 49. Вычисляемые свойства</a></li>
<li><a href="API.ru.html#chapter-50">Глава 50. В заключение</a></li>
</ul>
</li>
<li>
<h4><a href="API.ru.html#section-7">Раздел VI. API как продукт</a></h4>
<ul>
<li><a href="API.ru.html#api-product">Глава 49. Продукт API</a></li>
<li><a href="API.ru.html#api-product-business-models">Глава 50. Бизнес-модели API</a></li>
<li><a href="API.ru.html#api-product-vision">Глава 51. Формирование продуктового видения</a></li>
<li><a href="API.ru.html#api-product-devrel">Глава 52. Взаимодействие с разработчиками</a></li>
<li><a href="API.ru.html#api-product-business-comms">Глава 53. Взаимодействие с бизнес-аудиторией</a></li>
<li><a href="API.ru.html#api-product-range">Глава 54. Линейка сервисов API</a></li>
<li><a href="API.ru.html#api-product-kpi">Глава 55. Ключевые показатели эффективности API</a></li>
<li><a href="API.ru.html#api-product-antifraud">Глава 56. Идентификация пользователей и борьба с фродом</a></li>
<li><a href="API.ru.html#api-product-tos-violations">Глава 57. Технические способы борьбы с несанкционированным доступом к API</a></li>
<li><a href="API.ru.html#api-product-customer-support">Глава 58. Поддержка пользователей API</a></li>
<li><a href="API.ru.html#api-product-documentation">Глава 59. Документация</a></li>
<li><a href="API.ru.html#api-product-testing">Глава 60. Тестовая среда</a></li>
<li><a href="API.ru.html#api-product-expectations">Глава 61. Управление ожиданиями</a></li>
<li><a href="API.ru.html#api-product">Глава 51. Продукт API</a></li>
<li><a href="API.ru.html#api-product-business-models">Глава 52. Бизнес-модели API</a></li>
<li><a href="API.ru.html#api-product-vision">Глава 53. Формирование продуктового видения</a></li>
<li><a href="API.ru.html#api-product-devrel">Глава 54. Взаимодействие с разработчиками</a></li>
<li><a href="API.ru.html#api-product-business-comms">Глава 55. Взаимодействие с бизнес-аудиторией</a></li>
<li><a href="API.ru.html#api-product-range">Глава 56. Линейка сервисов API</a></li>
<li><a href="API.ru.html#api-product-kpi">Глава 57. Ключевые показатели эффективности API</a></li>
<li><a href="API.ru.html#api-product-antifraud">Глава 58. Идентификация пользователей и борьба с фродом</a></li>
<li><a href="API.ru.html#api-product-tos-violations">Глава 59. Технические способы борьбы с несанкционированным доступом к API</a></li>
<li><a href="API.ru.html#api-product-customer-support">Глава 60. Поддержка пользователей API</a></li>
<li><a href="API.ru.html#api-product-documentation">Глава 61. Документация</a></li>
<li><a href="API.ru.html#api-product-testing">Глава 62. Тестовая среда</a></li>
<li><a href="API.ru.html#api-product-expectations">Глава 63. Управление ожиданиями</a></li>
</ul>
</li>
</ul>

View File

@ -4,6 +4,7 @@
"license": "CC-BY-NC-4.0",
"author": "Sergey Konstantinov <twirl-team@yandex.ru>",
"repository": "github.com:twirl/The-API-Book",
"version": "2.0.0",
"devDependencies": {
"@twirl/book-builder": "0.0.22",
"html-docx-js": "^0.3.1",

View File

@ -147,10 +147,6 @@ article ul.share {
background-image: url(/img/share/twitter.svg);
}
.side-panel ul.share li a.share-vk {
background-image: url(/img/share/vk.svg);
}
.side-panel ul.share li a.share-linkedin {
background-image: url(/img/share/linkedin.png);
}

View File

@ -12,12 +12,12 @@ In this Section, we will specify those API design problems that we see as the mo
#### The Fundamentals of Solving Typical API Design Problems
Before we proceed to the patterns, we need to formulate first, how developing APIs differs from developing other kinds of software. Below, we will formulate three important concepts, which we will be referring to in the subsequent chapters.
Before we proceed to the patterns, we need to understand first, how developing APIs differs from developing other kinds of software. Below, we will formulate three important concepts, which we will be referring to in the subsequent chapters.
1. The more distributed and multi-faceted systems are and the more general-purpose channels of communication used, the more errors occur in the process of interaction. In the most interesting case of distributed many-layered client-server systems, raising an exception on the side of a client (like losing context as a result of app crash and restart), server (the pipeline of executing a query threw at some stage), communication channel (connection fully or partially lost), or any other interim agent (intermediate web-server hasn't got a response from backend and returned a gateway error) is a norm of life, and all systems must be designed in a manner that in a case of an exception of any kind, API clients must be able to restore their state and continue operating normally.
1. The more distributed and multi-faceted systems are built and the more general-purpose channels of communication are used, the more errors occur in the process of interaction. In the most interesting case of distributed many-layered client-server systems, raising an exception on the side of a client (like losing context as a result of app crash and restart), server (the pipeline of executing a query threw at some stage), communication channel (connection fully or partially lost), or any other interim agent (intermediate web-server hasn't got a response from backend and returned a gateway error) is a norm of life, and all systems must be designed in a manner that in a case of an exception of any kind, API clients must be able to restore their state and continue operating normally.
2. The more partners use the API, the more chance is that some of the mechanisms of the expected workflow are implemented wrongly. In other words, not only physical mistakes related to network or server overload should be expected, but also logical ones caused by improper API usage (and, in particular, there should be safeguards to avoid errors in one partner's code leading to a denial of service for other partners).
2. The more partners use the API, the more chance is that some of the mechanisms of the expected workflow are implemented wrongly. In other words, not only genuine errors related to network or server overload should be expected, but also logical ones caused by improper API usage (and, in particular, there should be safeguards to avoid errors in one partner's code leading to a denial of service for other partners).
3. Any part of the system might introduce unpredictable latencies when serving requests, and these latencies could be quite high, up to seconds and tens of seconds. Even if you have full control over the execution environment and network, client apps may hinder themselves due to suboptimal code or execution on low-performing or overloaded devices. As a result, it is important to ensure that proper API design does not rely on critical operations being executed quickly. This includes:
* If carrying out a task through the API requires making a sequence of calls, there should be a mechanism in place to resume the operation from the current step if needed, instead of restarting it from the beginning.
* Operations that affect shared resources should have locking mechanisms in place for the duration of the operation.
* If carrying out a task through the API requires making a sequence of calls, there should be a mechanism in place to resume the operation from the current step if needed, instead of restarting it from the beginning.
* Operations that affect shared resources should have locking mechanisms in place for the duration of the operation.

View File

@ -8,16 +8,16 @@ If we set aside implementation details (for which we strongly recommend not rein
The difference between the two approaches lies in the access granularity:
* If an API client is making requests as a regular user of the system, then it can only perform operations allowed for a specific user, which often means it might have access only to a partial dataset within the API endpoint.
* If the caller system is authorized, it implies that it has full access to the endpoint and can supply any parameters, i.e., has access to the full dataset exposed through the endpoint.
* If the caller system is authorized, it implies that it has full access to the endpoint and can supply any parameters, i.e., might operate the full dataset exposed through the endpoint.
Therefore, the first approach is more granular (the robot might be a “virtual employee” with access only to a limited dataset) and is a natural choice for APIs that are supplemental to an existing service for end users (and thus can reuse the existing AA solutions). However, this approach has some disadvantages:
* The need to develop a process for securely fetching authorization tokens for the robot user (e.g., via having a real user generate tokens in the web UI), as regular login-password authentication (especially multi-factored) is not well-suited for API clients.
* The need to make exceptions for robot users in almost every security protocol:
* Robots might make many more requests per second than real users and might perform several queries in parallel (possibly from different IP addresses located in different availability zones).
* Robots do not accept cookies and cannot solve captchas.
* Robots should not be logged out or have their token invalidated “just in case” (as it would impact the partner's business processes), so it is usually necessary to invent specific long-lived tokens for robots and/or token renewal procedures.
* Finally, you may encounter significant challenges if you need to allow robots to perform operations on behalf of other users (as you will have to either expose this functionality to all users or, conversely, hide its existence from them).
* Robots should not be logged out or have their token invalidated (as it would impact the partner's business processes), so it is usually necessary to invent specific long-lived tokens for robots and/or token renewal procedures.
* Finally, you may encounter significant challenges if you need to allow robots to perform operations on behalf of other users (as you will have to either expose this functionality to all users or, vice versa, hide its existence from them).
If the API is not about providing additional access to a service for end users, it is usually much easier to opt for the second approach and authorize clients with API keys. In this case, per-endpoint granularity can be achieved (i.e., allowing partners to regulate the set of permitted endpoints for a key), while developing more granular access can be much more complex and rarely implemented.
If the API is not about providing additional access to a service for end users, it is usually much easier to opt for the second approach and authorize clients with API keys. In this case, per-endpoint granularity can be achieved (i.e., allowing partners to regulate the set of permitted endpoints for a key), while developing more granular access can be much more complex and because of that rarely see implementations.
Both approaches can be morphed into each other (e.g., allowing robot users to perform operations on behalf of any other users effectively becomes API key-based authorization; allowing binding of a limited dataset to an API key effectively becomes a user account), and there are some hybrid systems in the wild (where the request requires being signed with both an API key and a user token).
Both approaches can be morphed into each other (e.g., allowing robot users to perform operations on behalf of any other users effectively becomes API key-based authorization; allowing binding of a limited dataset to an API key effectively becomes a user account), and there are some hybrid systems in the wild (where the request must be signed with both an API key and a user token).

View File

@ -4,7 +4,7 @@ Let's proceed to the technical problems that API developers face. We begin with
1. The client sends the order creation request
2. Because of network issues, the request propagates to the server very slowly, and the client gets a timeout;
* therefore, the client does not know whether the query was served or not.
* therefore, the client does not know whether the query was served or not.
3. The client requests the current state of the system and gets an empty response as the initial request still hasn't reached the server:
```
const pendingOrders = await
@ -27,7 +27,7 @@ The first approach is to literally implement standard synchronization primitives
let lock;
try {
// Capture the exclusive
// reight to create new orders
// right to create new orders
lock = await api.
acquireLock(ORDER_CREATION);
// Get the list of current orders
@ -51,7 +51,7 @@ try {
Rather unsurprisingly, this approach sees very rare use in distributed client-server APIs because of the plethora of related problems:
1. Waiting for acquiring a lock introduces new latencies to the interaction that are hardly predictable and might potentially be quite significant.
2. The lock itself is one more entity that constitutes a subsystem of its own, and quite a demanding one as strong consistency is required for implementing locks: the `getPendingOrders` function must return the up-to-date state of the system otherwise the duplicate order will be anyway created.
2. The lock itself is one more entity that constitutes a subsystem of its own, and quite a demanding one as [strong consistency](https://en.wikipedia.org/wiki/Strong_consistency) is required for implementing locks: the `getPendingOrders` function must return the up-to-date state of the system otherwise the duplicate order will be anyway created.
3. As it's partners who develop client code, we can't guarantee it works with locks always correctly. Inevitably, “lost” locks will occur in the system, and that means we need to provide some tools to partners so they can find the problem and debug it.
4. A certain granularity of locks is to be developed so that partners can't affect each other. We are lucky if there are natural boundaries for a lock — for example, if it's limited to a specific user in the specific partner's system. If we are not so lucky (let's say all partners share the same user profile), we will have to develop even more complex systems to deal with potential errors in the partners' code — for example, introduce locking quotas.
@ -87,6 +87,6 @@ try {
Instead of a version, the date of the last modification of the resource might be used (which is much less reliable as clocks are not ideally synchronized across different system nodes; at least save it with the maximum possible precision!) or entity identifiers (ETags).
The advantage of optimistic concurrency control is therefore the possibility to hide under the hood the complexity of implementing locking mechanisms. The disadvantage is that the versioning errors are no longer exceptions — it's now a regular behavior of the system. Furthermore, client developers *must* implement working with them otherwise the application might render inoperable as users will be infinitely creating an order with the wrong version.
The advantage of optimistic concurrency control is therefore the possibility to hide under the hood the complexity of implementing locking mechanisms. The disadvantage is that the versioning errors are no longer exceptional situations — it's now a regular behavior of the system. Furthermore, client developers *must* implement working with them otherwise the application might render inoperable as users will be infinitely creating an order with the wrong version.
**NB**: which resource to select for making versioning is extremely important. If in our example we create a global system version that is incremented after any order comes, users' chances to successfully create an order will be close to zero.

View File

@ -70,9 +70,9 @@
"contents": [
"<p>API-first development is one of the hottest technical topics nowadays since many companies started to realize that API serves as a multiplicator to their opportunities—but it also amplifies the design mistakes as well.</p>",
"<p>This book is written to share the expertise and describe the best practices in designing and developing APIs. It comprises six sections dedicated to:</p>",
"<ul><li>the API design</li>",
"<ul><li>The API design</li>",
"<li>API patterns</li>",
"<li>backwards compatibility</li>",
"<li>Backwards compatibility</li>",
"<li>HTTP API & REST</li>",
"<li>SDK and UI libraries</li>",
"<li>API product management.</ul>",
@ -92,9 +92,9 @@
"content": [
"<p>API-first development is one of the hottest technical topics nowadays since many companies started to realize that API serves as a multiplicator to their opportunities—but it also amplifies the design mistakes as well.</p>",
"<p>This book is written to share the expertise and describe the best practices in designing and developing APIs. It comprises six sections dedicated to:</p>",
"<ul><li>— the API design</li>",
"<ul><li>— The API design</li>",
"<li>— API patterns</li>",
"<li>— backwards compatibility</li>",
"<li>— Backwards compatibility</li>",
"<li>— HTTP API & REST</li>",
"<li>— SDK and UI libraries</li>",
"<li>— API product management.</ul>",

View File

@ -19,5 +19,5 @@
2. Чем больше различных партнёров подключено к API, тем больше вероятность того, что какие-то из предусмотренных вами механизмов обеспечения корректности взаимодействия будет имплементирован неправильно. Иными словами, **вы должны ожидать не только физических ошибок, связанных с состоянием сети или перегруженностью сервера, но и логических, связанных с неправильным использованием API** (и, в частности, предотвращать возможный отказ в обслуживании одних партнёров из-за ошибок в коде других партнёров).
3. Любая из частей системы может вносить непредсказуемые задержки исполнения запросов, причём достаточно высокого — секунды, десятки секунд — порядка. Даже если вы полностью контролируете среду исполнения и сеть, задержку может вносить само клиентское приложение, которое может быть просто написано неоптимальным образом или же работать на слабом или перегруженном устройстве. Поэтому **при проектировании API нельзя полагаться на то, что критические действия выполнятся быстро**. В частности:
* для операций, состоящих из нескольких шагов, необходимо предусматривать возможность при необходимости продолжить выполнение с текущего шага, а не с начала;
* для операций с разделяемыми ресурсами необходимо предусматривать механизмы блокировки ресурса.
* для операций, состоящих из нескольких шагов, необходимо предусматривать возможность при необходимости продолжить выполнение с текущего шага, а не с начала;
* для операций с разделяемыми ресурсами необходимо предусматривать механизмы блокировки ресурса.

View File

@ -84,7 +84,7 @@ try {
}
```
**NB**: Внимательный читатель может возразить нам, что необходимость имплементировать стратегии синхронизации и строгую консистентность никуда не пропала, т.к. где-то в системе должен существовать компонент, осуществляющий блокирующее чтение версии с её последующим изменением. Это не совсем так: стратегии синхронизации и строгая консистентность *пропали из публичного API*. Расстояние между клиентом, устанавливающим блокировку, и сервером, её обрабатывающим, стало намного меньше, и всё взаимодействие теперь происходит в контролируемой среде (это вообще может быть одна подсистема, если мы используем [ACID-совместимую базу данных](https://en.wikipedia.org/wiki/ACID) или вовсе держим состояние ресурса в оперативной памяти).
**NB**: внимательный читатель может возразить нам, что необходимость имплементировать стратегии синхронизации и строгую консистентность никуда не пропала, т.к. где-то в системе должен существовать компонент, осуществляющий блокирующее чтение версии с её последующим изменением. Это не совсем так: стратегии синхронизации и строгая консистентность *пропали из публичного API*. Расстояние между клиентом, устанавливающим блокировку, и сервером, её обрабатывающим, стало намного меньше, и всё взаимодействие теперь происходит в контролируемой среде (это вообще может быть одна подсистема, если мы используем [ACID-совместимую базу данных](https://en.wikipedia.org/wiki/ACID) или вовсе держим состояние ресурса в оперативной памяти).
Вместо версий можно использовать дату последней модификации ресурса (что в целом гораздо менее надёжно ввиду неидеальной синхронизации часов в разных узлах системы; не забывайте, как минимум, сохранять дату с максимально доступной точностью!) либо идентификаторы сущности (ETag).

View File

@ -147,10 +147,6 @@ article ul.share {
background-image: url(/img/share/twitter.svg);
}
.side-panel ul.share li a.share-vk {
background-image: url(/img/share/vk.svg);
}
.side-panel ul.share li a.share-linkedin {
background-image: url(/img/share/linkedin.png);
}