mirror of
https://github.com/twirl/The-API-Book.git
synced 2025-01-05 10:20:22 +02:00
Переписано введение
This commit is contained in:
parent
2ca9beac0b
commit
aa43e042d9
104
API.ru.html
104
API.ru.html
@ -17,44 +17,69 @@
|
||||
<h2>Введение</h2>
|
||||
<p>Если мы посмотрим на определение из энциклопедии, то узнаем, что программирование — это что-то вроде преобразования формально проставленной задачи в исполняемый код, как правило, путём имплементации какого-то алгоритма на определённом языке программирования. И действительно, курсы обучения соответствующим дисциплинам большей частью и состоят из инструкций, как перевести словесно поставленную задачу в код и запрограммировать тот или иной алгоритм.</p>
|
||||
<p>Этот алгоритмический подход — пожалуй, худшее, что могло случиться с программистами. Определять программирование через имплементацию алгоритмов — это как определять работу композитора как написание специальных значков на нотном стане, математика — как написание формул, астронома — как смотрение в телескоп.</p>
|
||||
<p>Разумеется, написание кода — неотъемлемая часть процесса программирования. Но позвольте мне высказаться резко: это наименее важная и наиболее простая часть работы программиста. К сожалению, реальность такова, что множество людей, так или иначе связанных с программированием — включая самих программистов и их непосредственное руководство, — этого не понимают. Результат — огромное количество откровенно плохих, неудобных, небезопасных и дырявых как решето приложений, которые окружают человека в XXI веке.</p>
|
||||
<h3>Об уровнях восприятия</h3>
|
||||
<p>Программирование как трансляция формальной задачи с человеческого языка на машинный — это лишь первый (скорее даже, нулевой) уровень восприятия процесса разработки. Нет алгоритма, который был бы как остров, сам по себе; каждый алгоритм откуда-то берётся и для чего-то предназначен. Иными словами, существует некоторый контекст, в котором будет работать этот небольшой фрагмент программного кода. В первую очередь таким контекстом является программный продукт целиком, в составе которого имплементируется алгоритм.</p>
|
||||
<p>Чем больше, масштабнее и сложнее программный продукт, тем менее важна собственно алгоритмизация конкретной подзадачи и тем более важна архитектура продукта в целом. Правильно ли произведена декомпозиция? Будет ли этот код понятен другому разработчику через несколько лет? Можно ли потом эффективно расширять и поддерживать этот код?</p>
|
||||
<p>Это следующий уровень восприятия проекта: понимание <em>контекста</em> существования конкретного фрагмента кода. На этом уровне появляется понимание того, что интерфейс должен быть сначала спроектирован, и что с ним надо «переспать», т.е. всесторонне обдумать; что «переключение контекстов» — дорогая операция, и что браться за другую задачу в другом проекте, на самом деле, очень сложно, даже если требуется написать всего 10 строчек кода.</p>
|
||||
<p>Но и этот уровень не последний. Помимо контекст продукта существует также и ещё более широкий контекст — внешний, в котором живёт сам продукт. Связи внешнего мира с внутренним миром разработки широки и разнообразны: внешний мир определяет функциональность продукта, внешний мир диктует свои правила. Помимо прямой связи существует и обратная: кто-то во внешнем мире будет пользоваться вашим продуктом и, возможно, вашим программным кодом — т.е. вы сами привносите нечто во внешний контекст, и это «нечто» какое-то время будет там жить.</p>
|
||||
<p><em>Существуют ли иные, более масштабные уровни восприятия — наверняка хочет поинтересоваться пытливый читатель. Мне, во всяком случае, о них неизвестно; если что, я напишу о них в следующем, исправленном и дополненном, издании.</em></p>
|
||||
<p>Свою задачу как автора этой книги я вижу в том, чтобы помочь вам мыслить на более высоких уровнях понимания. «При чём же здесь тогда API?» — наверняка удивится пытливый читатель.</p>
|
||||
<p>При том, что API это ничто иное, как средство связи контекстов. Например, когда вы реализуете какой-то алгоритм — вы используете API языка программирования. Компилятор языка программирования, в свою очередь, использует API команд процессора. Это API, в случае CISC-процессоров, в свою очередь построено поверх ещё более низкоуровнего API микрокоманд; и так далее. Только представьте себе, какое огромное количество API разных уровней должно отработать — и отработать правильно! — для того, чтобы вы смогли, скажем, увидеть страничку в браузере: тут и весь сетевой стек с его 6-7 уровнями абстракции; и серверное ПО — веб-сервер, генерация страницы, база данных, кэш; и клиентское ПО — браузер — имплементирующее буквально десятки разных API.</p>
|
||||
<p>В современном мире роль API трудно преувеличить, и она продолжает расти. Всё новые и новые устройства — от часов и розеток до кораблей и ветряных турбин — включаются в «игру контекстов» и обзаводятся своим API. При этом, к сожалению, качество этих API всё больше оставляет желать лучшего.</p>
|
||||
<p>Именно эти соображения и побудили меня написать эту книгу. Разработка хорошего API требует, во-первых, определённого системного мышления; а, во-вторых, понимания того, что API — это не просто какой-то командный код, но и большая ответственность. Я надеюсь, что с помощью этой книги окружающие меня API станут чуть лучше.</p>
|
||||
<h3>Об относительности критериев качества</h3>
|
||||
<p>Несмотря на всё написанное выше, я вовсе не призываю вас подходить к каждой задаче глобально; чрезмерное переусложнение ничуть не лучше чрезмерного упрощения.</p>
|
||||
<p>У каждого инструмента, включая и API, есть своя область применимости, и это важно понимать. Допустим, вы пишете, скажем, скрипт импорта данных из Википедии для того, чтобы залить в базу данных вашего продукта какие-то тестовые данные, и вы собираетесь воспользоваться им один раз. В этом случае, очевидно, совершенно неважно, правильная ли у него архитектура и понятен ли его API. Нет, разумеется, вы можете спроектировать и реализовать этот скрипт «правильно», гибко и универсально, чтобы вы могли им гордиться. Но зачем?</p>
|
||||
<p>Любая красота сложна. Правильная архитектура требует больших затрат времени и сил, часто — неоднократного полного переписывания базовых модулей. Правильное API требует времени и сил ещё больше.</p>
|
||||
<p>Понимать, где ваши усилия полезнее и нужнее — пожалуй, не менее важно, чем их (усилий) приложение.</p>
|
||||
<p>Этот принцип, в общем и целом, относится не только к архитектуре и красоте кода, но и ко многим другим вещам. Применение любого паттерна, любого принципа разработки имеет свою стоимость — и, к сожалению, мало кто всерьёз берётся анализировать эту стоимость до начала разработки.</p>
|
||||
<p>Например, бессмысленно примернять MVC-подход к вашему скрипту. Нет, конечно, можно, но зачем? Накладные расходы на описание моделей и представлений, будут разменены на что?</p>
|
||||
<p>Бессмысленно пытаться внедрять и agile или waterfall практики. Зачем и для чего нужны переоценки и анализы требований для скрипта, который один раз отработает и будет забыт?</p>
|
||||
<p>Более того, применение даже таких базовых принципов, как, скажем, ООП для этой задачи вовсе не выглядит обоснованным.</p>
|
||||
<p>Эти вещи кажутся очевидными на простых примерах; со сложными же проектами, поверьте, то же самое. Достоинства и недостатки любой методологии, как правило, отлично известны, однако редко когда выбор конкретного фреймворка, паттерна или подхода опирается на анализ соответствия их достоинств и недостатков проекту.</p>
|
||||
<p>Есть ещё один момент, который хочется подчеркнуть: инструменты должны соответствовать конкретным обстоятельствам — предметной области, планируемому жизненному циклу продукта и, что немаловажно, компетенциям команды. Во многих случаях неидеальный инструмент, с которым команда привыкла работать, предпочтительнее неидеального, который придётся осваивать по ходу.</p>
|
||||
<h3>API как универсальный паттерн</h3>
|
||||
<p>На фоне сказанного выше этот заголовок должен вызывать некоторые сомнения. Универсального паттерна не существует, разве нет?</p>
|
||||
<p>Тем не менее, API таковым паттерном является. Чтобы пояснить этот парадокс, давайте для начала поймём, что такое API.</p>
|
||||
<p>В первом разделе мы говорили о том, что API — это связь, интерфейс взаимодействия двух программируемых контекстов. Вспомним, что мы живём в мире, очень сильно завязанном на правильное взаимодействие целых иерархий таких контекстов. Что же тогда самое важное, что такое API по смыслу?</p>
|
||||
<p>API — это обязательство. Обязательство поддерживать связь контекстов. Всё остальное вторично.</p>
|
||||
<p>Поэтому любой сложный проект требует как минимум внутреннего API. Невозможно разработать что-то сложнее скрипта импорта данных, исполняемого один раз, без предоставления некоторых обязательств.</p>
|
||||
<p>Надо понимать, что ничего бесплатного не существует. Написание продукта как API требует существенно больших затрат, и, разумеется, для многих проектов эти затраты никогда не окупятся. С другой стороны, и преуменьшать ценность API не стоит: поддержание взятых на себя обязательств — гигантское конкурентное преимущество в современном мире.</p>
|
||||
<p>Решение «API-зации» того или иного функционала — также всецело вопрос баланса; это всегда размен времени и сил сейчас на стабильный и поддерживаемый код в будущем.</p>
|
||||
<p>При этом, надо сразу оговорить, что наличие API вовсе не гарантирует отсутствие ошибок в коде (или хотя бы меньшее их количество); код, написанный как API, при прочих равных будет скорее содержать больше ошибок вследствие избыточности интерфейсов. Основная цель написания API — добиться стабильной, поддерживаемой и расширяемой архитектуры, которая способна покрыть все потребности пользователя.</p>
|
||||
<h3>Более чем код</h3>
|
||||
<p>Итак, API — это механизм связывания программируемых контекстов и обязательство поддерживать эту связь. Из чего же состоит это связывание и эта поддержка?</p>
|
||||
<p>Понятно, что API имеет некоторую программную составляющую, иначе зачем бы оно было кому-то нужно. Но, исходя из вышесказанного, очевидно, что сам программный интерфейс — это далеко не всё.</p>
|
||||
<p>Прежде всего, API обязано обладать некоторой гарантированной стабильностью. Это — ключевое свойство, без него API лишено смысла.</p>
|
||||
<p>Во-вторых, API должно быть понятно пользователям. Это касается как архитектуры интерфейсов, т.е. номенклатуры программных сущностей, так и публичной документации. API без документации не существует так же, как и без программного кода.</p>
|
||||
<p>В-третьих, помимо документации, должна осуществляться поддержка пользователей: решение их проблем и обратная связь. Идеальных API не существует, всегда есть какой-то поток вопросов и проблем.</p>
|
||||
<p>И то, и другое, и третье кажется, на первый взгляд, понятным. Однако, когда теория сталкивается с практикой, часто оказывается, что разработчики API уделяют непростительно мало внимания этим проблемам.</p>
|
||||
<p>Чем плохи эти определения? Тем, что они описывают лишь формальную сторону процесса, оставляя за кадром главный вопрос: зачем? Зачем программисты пишут код, математики - формулы, композиторы - ноты? Математики увеличивают сумму человеческих знаний, композиторы высекают своей музыкой искры из людских сердец, а вот зачем программисты пишут свои алгоритмы?</p>
|
||||
|
||||
<p>Почему я придаю этому вопросу столь большое значение? Потому что методы решения задачи и использованные инструменты в первую очередь должны быть адекватны используемой задаче, а всё остальное вторично. Именно цель написания кода должна определять такие первичные вещи, как архитектура приложения, используемый язык разработки и выбор инструментария. Я прочитал немалое количество книг по профессиональной разработке программного обеспечения - и не нашел качественного освещения этого вопроса ни в одной из них. Все они рассказывают, как писать "хороший" код - поддерживаемый, расширяемый, безошибочный; но опускают при этом вопрос о том, насколько написание "хорошего" кода адекватно стоящим перед разработчиками целям. Между тем, мировая практика такова, что ставит под большое сомнение предположение, что хороший код означает качественный или хотя бы поддерживаемый и расширяемый продукт. Легко привести множество примеров удачных продуктов, написанных откровенно плохо и с нарушением всех мыслимых заповедей разработки.</p>
|
||||
|
||||
<p>Хочу ли я тем самым сказать, будто бы нужно писать плохой код? Нет, что вы - на протяжении всей этой книги я буду призывать вас писать хороший код. Я хочу сказать, что, если мы посмотрим на разработку программных продуктов через призму вопроса "зачем" (они разрабатываются), то поймём, что качество решения задач пользователей само по себе не проистекает из следования советам по написанию хорошего кода - это совершенно отдельное качество продукта, и думать о нём также необходимо отдельно.</p>
|
||||
|
||||
<h3>Об API и уровнях восприятия</h3>
|
||||
|
||||
<p>У любопытного читателя может возникнуть вопрос: хорошо, мы поняли интенцию относительно соответствия принципов разработки программного обеспечения её целям. При чем же здесь API? Позвольте объяснить.</p>
|
||||
|
||||
<p>Программирование как трансляция формальной задачи с человеческого языка на машинный — это первый (скорее даже, нулевой) уровень восприятия процесса разработки. Нет алгоритма, который был бы как остров, сам по себе; каждый алгоритм откуда-то берётся и для чего-то предназначен. Иными словами, существует некоторый контекст, в котором будет работать этот небольшой фрагмент программного кода. В первую очередь таким контекстом является программный продукт целиком, в составе которого имплементируется алгоритм.</p>
|
||||
|
||||
<p>Чем больше, масштабнее и сложнее программный продукт, тем менее важна собственно алгоритмизация конкретной подзадачи и тем более важна архитектура продукта в целом. Правильно ли произведена декомпозиция? Будет ли этот код понятен другому разработчику через несколько лет? Можно ли потом эффективно расширять и поддерживать этот код?</p>
|
||||
|
||||
<p>Это следующий уровень восприятия проекта: понимание <em>контекста</em> существования конкретного фрагмента кода. На этом уровне появляется понимание того, что интерфейс должен быть сначала спроектирован, и что с ним надо «переспать», т.е. всесторонне обдумать; что «переключение контекстов» — дорогая операция, и что браться за другую задачу в другом проекте, на самом деле, очень сложно, даже если требуется написать всего 10 строчек кода.</p>
|
||||
|
||||
<p>Но и этот уровень не последний. Помимо контекста внутри программного продукта существует также и ещё более широкий контекст — внешний, в котором живёт сам продукт. Связи внешнего мира с внутренним миром разработки широки и разнообразны: внешний мир определяет функциональность продукта, внешний мир диктует свои правила. Помимо прямой связи существует и обратная: кто-то во внешнем мире будет пользоваться вашим продуктом и, возможно, вашим программным кодом — т.е. вы сами привносите нечто во внешний контекст, и это «нечто» какое-то время будет там жить.</p>
|
||||
|
||||
<p>API - это ничто иное, как средство связи контекстов. Например, когда вы реализуете какой-то алгоритм — вы используете API языка программирования. Компилятор языка программирования, в свою очередь, использует API команд процессора. Это API, в случае CISC-процессоров, в свою очередь построено поверх ещё более низкоуровнего API микрокоманд; и так далее. Только представьте себе, какое огромное количество API разных уровней должно отработать — и отработать правильно! — для того, чтобы вы смогли, скажем, увидеть страничку в браузере: тут и весь сетевой стек с его 6-7 уровнями абстракции; и серверное ПО — веб-сервер, генерация страницы, база данных, кэш; и клиентское ПО — браузер — имплементирующее буквально десятки разных API.</p>
|
||||
|
||||
<p>В современном мире роль API трудно преувеличить, и она продолжает расти. Всё новые и новые устройства — от часов и розеток до кораблей и ветряных турбин — включаются в «игру контекстов» и обзаводятся своим API. При этом, к сожалению, качество этих API всё больше оставляет желать лучшего.</p>
|
||||
<p>В отличие от прикладного кода, которым будут пользоваться только ваши коллеги, разработка api подразумевает, что вашими программными интерфейсами будут пользоваться другие разработчики. Именно поэтому в разработке api проблемы, описанные в предыдущем разделе, стоят особенно остро. Хорошее api должно одновременно быть и качественно реализовано, и качественно спроектировано с точки зрения предоставляемых интерфейсов.</p>
|
||||
|
||||
<p>Цель написания этой книги - посмотреть на разработку программного обеспечения под другим углом, дополнить известные принципы разработки программных продуктов принципами разработки api.</p>
|
||||
|
||||
<h3>Об относительности критериев качества</h3>
|
||||
<p>Несмотря на всё написанное выше, я вовсе не призываю вас подходить к каждой задаче с дополнительными наборами требований. Вовсе даже наоборот: я скорее призываю эти требования сокращать.</p>
|
||||
|
||||
<p>У каждого инструмента, включая и API, есть своя область применимости, и это важно понимать. Допустим, вы пишете, скажем, скрипт импорта данных из Википедии для того, чтобы залить в базу данных вашего продукта какие-то тестовые данные, и вы собираетесь воспользоваться им один раз. В этом случае, очевидно, совершенно неважно, правильная ли у него архитектура и понятен ли его API. Нет, разумеется, вы можете спроектировать и реализовать этот скрипт «правильно», гибко и универсально, чтобы вы могли им гордиться. Но зачем?</p>
|
||||
|
||||
<p>Любая красота сложна. Правильная архитектура требует больших затрат времени и сил, часто — неоднократного полного переписывания базовых модулей. Правильное API требует времени и сил ещё больше.</p>
|
||||
|
||||
<p>Понимать, где ваши усилия полезнее и нужнее — пожалуй, не менее важно, чем их (усилий) приложение.</p>
|
||||
|
||||
<p>Эти вещи кажутся очевидными на простых примерах; со сложными же проектами, поверьте, то же самое. Достоинства и недостатки любой методологии, как правило, отлично известны, однако редко когда выбор конкретного фреймворка, паттерна или подхода опирается на анализ соответствия их достоинств и недостатков проекту.</p>
|
||||
|
||||
<p>Есть ещё один момент, который хочется подчеркнуть: инструменты должны соответствовать конкретным обстоятельствам — предметной области, планируемому жизненному циклу продукта и, что немаловажно, компетенциям команды. Во многих случаях неидеальный инструмент, с которым команда привыкла работать, предпочтительнее неидеального, который придётся осваивать по ходу.</p>
|
||||
|
||||
<h3>API как универсальный паттерн</h3>
|
||||
|
||||
<p>На фоне сказанного выше этот заголовок должен вызывать некоторые сомнения. Универсального паттерна не существует, разве нет?</p>
|
||||
|
||||
<p>Тем не менее, API таковым паттерном является. Чтобы пояснить этот парадокс, давайте для начала поймём, что такое API.</p>
|
||||
|
||||
<p>В первом разделе мы говорили о том, что API — это связь, интерфейс взаимодействия двух программируемых контекстов. Вспомним, что мы живём в мире, очень сильно завязанном на правильное взаимодействие целых иерархий таких контекстов. Что же тогда самое важное, что такое API по смыслу?</p>
|
||||
|
||||
<p>API — это обязательство. Обязательство поддерживать связь контекстов. Всё остальное вторично.</p>
|
||||
|
||||
<h3>О структуре этой книги</h3>
|
||||
|
||||
<p>Книга, которую вы держите в руках, состоит из трех больших разделов, назовем их условно "статическим", "динамическим" и "маркетинговым".</p>
|
||||
|
||||
<p>В первом разделе мы поговорим о проектировании api на стадии разработки концепции - как грамотно выстроить архитектуру, от крупноблочного планирования до конечных интерфейсов.</p>
|
||||
|
||||
<p>Второй раздел будет посвящён жизненному циклу api - как интерфейсы эволюционируют со временем и как развивать продукт так, чтобы отвечать потребностям пользователей.</p>
|
||||
|
||||
<p>Наконец, третий раздел будет касаться больше не-разработческих сторон жизни api - поддержки, маркетинга, достижения контакта с аудиторией.</p>
|
||||
|
||||
<p>Первые два будут интересны скорее разработчикам, третий - и разработчикам, и менеджерам. При этом я настаиваю, что как раз третий раздел - самый важный для разработчика api. Ввиду того, что api - продукт для разработчиков, перекладывать ответственность за его маркетинг и поддержку на не-разработчиков неправильно: никто кроме вас самих не понимает так хорошо продуктовые свойства вашего api.</p>
|
||||
|
||||
<h2>Проектирование API</h2>
|
||||
|
||||
<!--
|
||||
<h2>О проектировании API</h2>
|
||||
<h3>Архитектура против реализации</h3>
|
||||
<p>Поскольку API — обязательство, то к качеству его реализации предъявляются, как правило, повышенные требования — во-первых, в силу важности API как инструмента для бизнес-логики потребителей; во-вторых, в силу того, что ошибка в API может привести к гораздо более разрушительным последствиям, чем ошибка в end-user интерфейсе.</p>
|
||||
@ -70,7 +95,7 @@
|
||||
<h3>О неважности кода</h3>
|
||||
- в правильном апи любой код заменяем и он неважен
|
||||
<h3>Уровни абстракции</h3>
|
||||
<p>Концепция уровней абстракции довольно широко известна. Классическим примером разделения уровней является, скажем, модель OSI, описывающая 7 уровней сетевых взаимодействий.</p>
|
||||
< p>Концепция уровней абстракции довольно широко известна. Классическим примером разделения уровней является, скажем, модель OSI, описывающая 7 уровней сетевых взаимодействий.</p>
|
||||
<p>К сожалению, в реальных системах выделить уровни абстракции гораздо сложнее, нежели в таких чистых случаях; множество успешных и существующих API и вовсе не оперируют такими терминами. Классический случай — веб-платформа, в которой правильное разделение абстракций фактически никогда не существовало, и лишь Extensible Web Manifesto впервые постулировал необходимость не экстенсивно наращивать номенклатуру методов, а строить иерархию абстракций.</p>
|
||||
<p>Связано это, по-видимому, со сложностью подобного разделения в абсолютном большинстве предметных областей. Классический алгоритм «берём все объекты и разбиваем их на слои» в реальном мире работает очень слабо: всегда есть сущности, которые не ложатся в иерархию, будучи либо чересчур глобальными, либо, напротив, чересчур утилитарными.</p>
|
||||
<p>Тем не менее, говорить об иерархии абстракций можно и нужно.</p>
|
||||
@ -124,4 +149,5 @@
|
||||
<p>В реальности же 90%, если не больше, обращающихся за поддержкой пользователей будут решать совершенно тривиальные задачи и у них в принципе нет никакой мотивации разбираться с внутренним устройством API. Пользователь хочет решить свою задачу с наименьшим напряжением сил, и было бы странным его за это упрекать.</p>
|
||||
<p>Люди не читают документацию. Не ищут ответов на свои вопросы на StackOverflow. Не являются гуру разработки. Даже напротив, абсолютное большинство ваших клиентов — начинающие и просто малоквалифицированные специалисты. Даже если вашим API пользуются ребята из соседнего отдела, квалификация которых не уступает вашей, — вряд ли даже у них есть желание глубоко разбираться в вашей архитектуре.</p>
|
||||
<p>Поэтому любой поток обращений, как правило, делится на две неравные категории: вопросы от начинающих (часто глупые или тривиальные) и очень редкие запросы от профессионалов. Запросов первого типа абсолютное большинство, и, при том, найти проблему в коде пользователя частенько бывает весьма нетривиальной задачей.</p>
|
||||
-->
|
||||
</body></html>
|
||||
|
Loading…
Reference in New Issue
Block a user