По пунктам: что нужно знать о бэкенде новичку в веб-разработке

бэкенд

Рассказывает Эмит Ирэндол, full-stack разработчик


В этой статье перечислены ключевые аспекты, которые нужно учитывать при создании бэкенда в контексте full-stack веб-разработки. Новичков она познакомит с основами, а более продвинутым программистам может быть полезна в качестве чек-листа.

1. Аутентификация

Большинство приложений стремится обрести новых пользователей, поэтому необходимо разработать механизм, позволяющий пользователям регистрироваться, аутентифицироваться и менять свои учётные данные.

Можно выделить два основных типа аутентификации:

  1. Запоминающая предыдущее состояние — реализуется с помощью сессий. Пользователь авторизуется один раз, а затем получает возможность свободно передвигаться по приложению и доступ к защищенным ресурсам (таким, как банковские транзакции или селфи в Snapchat), не отправляя данные, которые подтверждают его вход повторно.
  2. Не запоминающая предыдущее состояние — реализуется с помощью токенов. Пользователи делают все то же самое, но при выполнении каждого HTTP-запроса пользователю нужно отправлять идентификационные данные. Так обычно поступают с REST API. Сейчас золотой стандарт, не запоминающей состояние аутентификации с токенами, — JWT.

Есть и более продвинутый сценарий — многофакторная аутентификация. Она повышает безопасность приложения, добавляя дополнительные уровни защиты к логину и паролю. Хорошие примеры реализации есть у Google и Amazon.

Прим. перев. А у нас есть разъясняющая статья про двухфакторную аутентификацию и протокол FIDO U2F.

OAuth — другой широко распространенный сценарий. Он дает пользователям вашего приложения возможность зарегистрироваться и войти в него одним кликом, используя аккаунт одной из социальных сетей. Аутентификация происходит за счет того, что пользователи предоставляют вашему приложению некоторые свои данные из социальной сети, но при этом не вводят их вручную.

2. Роли, разрешения и контроль доступа

Многие путают авторизацию с аутентификацией, не понимая, что это разные понятия. Аутентификация определяет то, как пользователь входит в приложение. Авторизация же определяет то, что пользователь имеет право делать после входа.

Запутались? Объясню подробнее. Смысл слоя, отвечающего за авторизацию, — это выдача разрешений, поддержание безопасности личной информации, отказ в доступе к конкретным действиям и, где требуется, аннулирование привилегий, чтобы одни пользователи не пробирались в аккаунты других и не смотрели их личные фотографии. Логика разрешений проста:

Пользователь x может сделать действие y с объектом z.

Применим это в конкретной ситуации: Шэрон — редактор и может редактировать посты. Тогда надо определить:

  • роль Шэрон — редактор;
  • ее действие — редактирование;
  • объекты, с которыми она может это делать, — посты.

Как это работает? Просто: булевы переменные. Вы возвращаете True/False в зависимости от того, что и кому разрешено делать с конкретным объектом. Итак, может ли Шэрон редактировать какой-то конкретный пост? Вернуть True, если она редактор, вернуть False и закрыть доступ к посту, если нет.

3. CRUD — Create, Read, Update, Delete

Вы не можете создавать пользователей или выдавать разрешения, не зная, как работать с ресурсами: создавать, читать, редактировать и удалять их. Это значит, что надо научиться управлять ресурсами приложения, и чаще всего для этого используют базы данных.

Но что такое ресурс? Если вы создаете книжный магазин, то книги — это ресурсы. Если вы создаете группу, она сама и есть ресурс и ее участники тоже ресурсы. А также каждая запись или аккаунт, который они используют. Например, это может быть официальное письмо к правительству, открытка или фильм, который они пытаются купить.

Здесь и появляется модель структуры ваших данных. Вам нужно будет понимать, как решить следующие задачи:

  • как создавать новые данные;
  • как их редактировать;
  • как я их обновлять и удалять.

Так выглядит CRUD при работе с фреймворком Ruby on Rail, который предоставляет слой объектно-реляционного сопоставления (Object Relational Mapping — ORM):

Также ваши ресурсы редко существуют в изоляции. Чаще всего они связаны какими-то отношениями или ассоциациями с другими ресурсами. Давайте взглянем на сценарий, где вы хотите сохранить информацию о парах, которые есть у студента. Вы можете создать дочерний ресурс в student и сохранить его:

Не правда ли, это выглядит и читается, как обычный английский? Но учиться все равно придется, ведь в реальности задачи очень быстро обрастают трудностями! Поэтому вам нужно научиться работать с базами данных, выбрав для себя подходящую модель: реляционную или NoSQL.

Заметьте, что для задач CRUD вам также нужно будет научиться проверять входящие данные и сверяться с разрешениями, прежде чем вы сделаете что-то с этими данными.

4. REST

Чтобы обеспечить управление ресурсами в вашем приложении (такими, как книги или аккаунты), нужно реализовать программный слой, принимающий запросы и формирующий ответы. Здесь вам доведется поработать с маршрутами (routes) и контроллерами (controllers). Они обеспечивают соблюдение ограничений, накладываемых REST — стилем архитектуры программного обеспечения для распределенных систем.

В типичном приложении на Ruby маршрут выглядит так:

Что в это время происходит в системе:

  1. Приходит запрос на фото с этим маршрутом и передается контроллеру с помощью метода show.
  2. Этот метод, обращаясь к ресурсу из базы данных или к другому API, формирует и передает ответ в формате HTML или JSON.
  3. Клиент (в данном случае браузер компьютера) получает ответ и выводит фото на экран.

Запросы могут приходить из многих источников (их называют клиентами). Чаще всего запросы для веб-приложения формируются в форме ввода браузера. Но, если вы пишете бэкенд для мобильного приложения, то клиент — это API приложения, и он посылает запросы GET, POST, PUT, DELETE из приложения.

Вы можете разработать отвечающую на запросы систему, создав API с учетом REST. Такой API называется RESTful, читайте подробнее о нем в подробной статье.

Прим. перев. Также предлагаем ознакомиться с нашим материалом по этой теме.

5. Формы и состояния

Формы — это самый распространенный способ общения пользователей с приложением. В основном через них пользователи и вводят все данные.

Вам надо создать формы для взаимодействия с бэкендом: если пользователь заказывает билет на концерт, то форма должна выглядеть, как сетка мест:

Когда пользователь начинает взаимодействовать с формой, вам надо сделать следующее:

  1. Основываясь на правилах приложения, проверить введенную пользователем информацию и показать ошибки или сообщение об успешной проверке.
  2. Изменить название состояния или формы в зависимости от того, кто и что пытается сделать.
  3. Разрешить передачу данных, введенных проверенным пользователем с достаточными правами, в бэкенд для обработки.

6. API

Чтобы ваше приложение стало по-настоящему популярным, вам надо начать делиться данными с другими приложениями. Например, вы — музыкальная компания, и вы хотите, чтобы стриминговые сервисы типа SoundCloud поставляли ваш контент, а пользователи могли покупать вашу музыку напрямую из их приложения. Здесь и нужен API.

Термин API — аббревиатура от Application Programming Interface (интерфейс программирования приложений) — применяется к инфраструктуре, которая позволяет другим приложениям взаимодействовать с вашим. На картинке выше вы видите пример применения API для обслуживания сети из многих мобильных и настольных клиентов.

Основные этапы написания API:

  1. Создать API-сервер. Этап подразумевает обеспечение защищенного доступа к ресурсам, которые вы хотите передавать клиентам. Если у вас книжный магазин, то ваш API будет предоставлять названия книг, цены и информацию об издателе другим сайтам и перекупщикам.
  2. Защитить сервер, используя идентификаторы приложений и секретные ключи.
  3. Сделать понятную интерактивную документацию, которая позволит другим разработчикам просматривать ее и взаимодействовать между собой и с вами.

7. Уведомления по Email, SMS и Webhooks

Когда пользователь совершает в вашем приложении важное действие, например, подписывается на обновления, создает новый аккаунт или проект, он должен знать, удалось это действие или нет.

Уведомления — это способ сообщить вашему пользователю о статусе выполнения действия и помочь ему организовать рабочий процесс в вашем приложении.

Для разных случаев вы можете использовать разные уведомления:

  • оповещения на экране приложения;
  • электронные письма (верификация почты или подтверждение покупки);
  • SMS (авторизация или завершение транзакции);
  • webhook-уведомления в реальном времени для обратившихся к вашему приложению чат-ботов на разных платформах, например, Facebook, Telegram или Slack;
  • регулярные письма со счетами за покупки и информацией об оплате подписки.

8. Подписка и тарифные планы

Продумывание тарифов только кажется маловажным, но на деле часто является необходимым. Вам придется научиться создавать многоуровневые тарифные планы и присваивать определенные роли, разрешения и привилегии пользователям, подписавшимся на конкретный план. Также хорошая идея научиться предоставлять динамическое ценообразование, основанное на свойствах, формирующих каждый тарифный план. Например, покупка нового сервера на AWS или DigitalOcean дает пользователям право выбирать память, процессор и т.д.

Полезные советы по проектированию тарифных планов:

  • выделяйте рекомендуемый вариант;
  • разрешите пользователям выбирать валюту (€/$/₽) и период оплаты (месяц/год);
  • предоставьте первый месяц бесплатно для успешного вовлечения пользователей;
  • особо выделите отзывы;
  • продавайте преимущества вместо характеристик;
  • дайте пользователям понять, что они могут отказаться в любой момент;
  • разрешите пользователям выбирать интересующие характеристики и конфигурировать тарифные планы.

9. Взаимодействие с платежным шлюзом

Вам понадобится обрабатывать информацию о кредитных картах с помощью форм, которые обычно выглядят, как интерфейс интернет-магазина.

Во время транзакции нужно:

  • убедиться, что информация о кредитной карте не сохраняется, не передается в другие части приложения и безопасно отправляется на платежный шлюз для обработки;
  • принять оплату, если транзакция прошла успешно, и отправить уведомление о том, что оплата удалась; иначе — отправить уведомление о неудаче и предложить пользователю попробовать оплатить в другой раз.

Вы также можете использовать сторонние сервисы, такие, как Paypal, которые позволяют интегрировать их интерфейс в виде формы (или кнопки) в ваше приложение, и тогда транзакции будут частично управляться этим сервисом.

Не забывайте про счета — людям нужны документы о транзакциях для уплаты налогов и т. д.:

  • создайте раздел со счетами, который является частью профиля пользователя;
  • сделайте удобную сортировку и экспорт данных по транзакциям в виде счет-фактур в формате PDF;
  • убедитесь, что пользователи могут отправлять эти счета себе на электронную почту.

Как работает платежный шлюз:

  1. Ваши кассовые формы отправляют детали покупки на платежный шлюз для обработки.
  2. Платежный шлюз передает данные транзакции банку продавца.
  3. Банк продавца передает эту информацию о транзакции банку, который выпустил карту покупателя, для авторизации транзакции.
  4. Банк, который выпустил карту покупателя, либо одобряет, либо отклоняет транзакцию и отправляет информацию банку продавца.
  5. Если транзакция одобрена, то банк переводит средства на ваш счет.
  6. После одобрения сторонний платежный шлюз отправляет детали транзакции и ответ вашему приложению.
  7. И, наконец, вы отправляете уведомление покупателю, сообщая, одобрена ли транзакция.

Если остались вопросы, посмотрите это видео:

10. Загрузка файлов

Очень вероятно, что когда пользователи начнут работать в вашем приложении, они будут хранить в нем свои данные, которые представляют из себя не только информацию в вашей базе, но и картинки, видео и PDF. Так что вам надо будет:

  1. Разрешить загружать только файлы определенных форматов.
  2. Проверять файлы на превышение разрешенного размера и отклонять загрузку слишком больших.
  3. Показывать пользователю процесс загрузки.
  4. Убедиться, что загрузка происходит асинхронно и не нарушает работу фронтенда.
  5. Разрешить пользователю помечать файлы как личные/общедоступные.
  6. Разрешить пользователю экспортировать загруженные данные.
  7. Создать медиа-библиотеку, чтобы фильтровать файлы и управлять ими (опционально).

11. Сторонние API, фреймворки и пакеты

Ruby, Elixir, PHP и JavaScript уже имеют тысячи пакетов, которые могут быть настроены и применены к вашему приложению. Их легко встроить с помощью команды в одну строку в терминале:

Если вы не будете включать сторонний код в вашу экосистему, то вам придется разбираться с такими низкоуровневыми проблемами, как создание сессий, хэширование и защита от атак CSRF и тому подобное вместо того, чтобы фокусироваться на высокоуровневых задачах, которые делают ваше приложение уникальным.

Чаще всего фреймворки составлены из отдельных пакетов, которые при желании можно заменять на более подходящие под ваши задачи. Вы можете оценить качество исходного кода пакета по следующим пунктам:

  • бейджи репозитория;
  • дата последнего обновления;
  • пройденные тесты;
  • популярность, например, по оценке пользователей в звездах;
  • количество решенных проблем и открытых пулл реквестов.

12. Работа с Open Source

Вы столкнетесь с тем, что уже существующие пакеты не выполняют необходимые задачи или делают это некорректно. Тем не менее, всегда есть возможность подстроить под себя их функционал, поэтому учитесь работать с чужим исходным кодом. Полезные советы:

  • читайте документацию и ищите ответы в ней, прежде чем задавать вопросы;
  • посетите официальную страницу пакета на GitHub или Bitbucket, просмотрите открытые и решенные проблемы, и, возможно, вы найдете пулл реквест, в котором будет необходимая функциональность;
  • также вы можете сами реализовать необходимую функциональность и отправить ее авторам, внеся свой вклад в развитие Open Source. Если ваш код не приняли, просто используйте свою версию вместо исходного пакета;
  • если вы все-таки вынуждены писать свои функции с нуля, то убедитесь, что вы создаете их для универсального применения, чтобы другие тоже могли их использовать.

13. Интерфейс для управления

Как только вы выпустите приложение, пользователи захотят управлять им, настраивать и персонализировать его. Чтобы они ничего не сломали, стоит ограничить им доступ, предоставив приятную и простую в использовании панель управления. Создать её не так сложно, как кажется, да и большинство написанных для нее функций вы сможете использовать где-то еще.

Хорошая панель управления должна обладать следующими свойствами:

  • защищенность от внешних атак;
  • корректное отображение для пользователей с разными уровнями доступа;
  • приятный дизайн и простота в использовании;
  • фокус на самых частых задачах;
  • возможность добавления внешних компонентов;
  • возможность заменить неиспользуемые функции новыми.

14. Кэширование

Красивый и удобный фронтенд часто состоит из сложные многоуровневых данных, отображение которых может быть медленным и ресурсозатратным. Без кэширования ваша база данных будет вынуждена многократно выполнять почти одинаковые запросы, что приведет к ее перегрузкам.

Представьте промежуточный слой в стэке вашего приложения, который хранит статические данные и предоставляет их по запросу, не обращаясь к базе данных. Это и есть кэш.

Как работает кэширование в веб-приложениях? Можно выделить следующие типы механизмов:

  • кэширование контента. Если контент веб-страницы не изменяется постоянно, то нет нужды каждый раз заново его генерировать. Целая HTML-страница может быть сохранена в кэше;
  • кэширование фрагментов. Иногда целая страница не может быть закэширована, потому что на ней есть контент, который постоянно изменяется, но есть и части, которые изменяются медленно. HTML для этих статичных частей генерируется только при первом запросе, а при повторных извлекается из кэша;
  • кэширование данных. Часто в основе веб-приложения лежит база данных, но каждый раз извлекать из нее информацию достаточно накладно, поэтому часто используемые данные кэшируются в памяти приложения или в других хранилищах, например, Redis, Varnish и Memcached.

15. Компоненты

Это больше относится к фронтенду, но так как вы full-stack разработчик, вам нужно разделить ваш код — и шаблоны страниц, и службы бэкенда — на модульные компоненты, если вы не хотите запутаться. В моем любимом проекте фронтенд организован следующим образом:

Приведенный выше код взят из шаблона Twig, который можно легко менять. Кроме того, при выходе из строя одного из компонентов работа всей страницы не нарушается. Например, если ваш код для аутентификации находится в слое управления, будет гораздо лучше убрать его оттуда и сформировать в виде отдельного компонента.

16. Системы управления версиями

Речь, конечно, идет об использовании Git и GitHub. Новичкам использование Git кажется излишним, а его преимущества — неочевидными, поэтому предлагаю подумать о ситуациях, с которыми вы можете столкнуться в процессе написания кода:

  1. Если вы собираетесь работать с другими разработчиками над одним и тем же проектом, то вы будете пользоваться общим набором файлов. Как именно вы планируете избежать противоречий при изменениях в коде?
  2. Что, если вы захотите вернуть старую версию и посмотреть, как вы реализовали ту или иную задачу перед тем, как продолжите разработку?
  3. Что, если вы захотите откатить проект к последней версии, в которой еще не было сбоя?
  4. Что, если вы захотите поделиться своим исходным кодом? Вы будете его архивировать и рассылать по e-mail при добавлении каждой новой фичи?
  5. Как вы будете следить за тем, какие файлы были изменены, а какие — нет?

Научиться пользоваться GitHub поможет эта статья.

Прим. перев. А чтобы разобраться в основах Git, читайте наше руководство.

17. Командная строка

В интерфейсе, доступном пользователю, есть ограниченное количество кнопок, которых недостаточно для полноценного управления приложением на всех уровнях. Но для этого есть командная строка, которая поможет вам добавлять модули в инфраструктуру вашего приложения, тестировать его и выкладывать на удаленный сервер.

Для освоения командной строки советую эту книгу.

Прим. перев. Знакомство с командной строкой также можно начать с нашей шпаргалки по Bash.

18. Вопросы на Stack Overflow

Если вы не можете разобраться сами, то спросите на Stack Overflow. А чтобы не показаться смешным в глазах опытных пользователей и получить исчерпывающий ответ, задавайте вопросы по инструкции.

Перевод статьи «Part uh: what does it take to be a full stack developer?»