how-to-develop-perfect-crud

Translations: EN, RU(you are here)

🤔 Что это?

Данная статья - попытка объединить в одном месте хорошие практики, которые полезно знать и применять при разработке бэкэнд приложения.

Её можно использовать как полноценный чеклист, который будет полезен, если Вы:

🤔 Здесь только про Backend?

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

🤔 Слишком много всего, это точно нужно?

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

🤔 “Здесь не хватает информации о технологии X”

Если у вас есть предложения по наполнению репозитория, не стесняйтесь:

📖 Table of Contents

Repository

Code Style

Перед разработкой приложения:

✔️Tests

Старайтесь покрывать ваш код по пирамиде тестирования. Обратите внимание, что для тестов разного уровня могут использоваться разные инструменты. Для end to end тестирования можно использовать Selenium или Cypress. Для интеграционных удобно использовать testcontainers

⚙️Configuration & Infrastructure around Code

При описании конфигурации приложения используйте принципы 12factor. Изображение взято из статьи: 12 Factor App Revisited

Deployment

В данном разделе будет приведены варианты того как можно задеплоить своё приложение, от простого и топорного до production ready практик.

Level 0: Use free hostings

Многие сервисы предоставляют бесплатный хостинг для небольших проектов, например:

Больше вариантов здесь: https://free-for.dev/#/?id=web-hosting

Изучите их перед тем как переходить к следующим уровням, возможно вам будет достаточно тех фич что они предлагают :)

Level 1: SSH, Git, VPS / Cloud (EC2) (without Docker)

Что требуется:

Что делать с базой данных? Есть несколько вариантов.

Дополнительные пункты:

Задача со звездочкой: научиться писать Ansible playbooks, чтобы настройка сервера выполнялась в одну команду для программиста.

Level 2: Containers and VPS (Docker required)

Данный способ также подойдет для небольших проектов и для тех кто уверенно чувствует себя с Docker.

Что нужно:

Деплой будет происходить через запуск контейнера на удаленной машине:

DOCKER_HOST=“ssh://user@your_vps_domain_or_ip” docker-compose up -d

Таким образом мы мы можем описать приложение и все его зависимости в docker-compose.yml и развернуть в одну команду.

Подробнее

Level 3: Containers and clouds (Docker required)

Если от вас требуется задеплоить приложение в облако и вы уже знакомы с Docker, то всё будет гораздо проще и стандартизовано

Level 4: Containers and Orchestrators (Docker required)

Bonus #1: Learn deployment strategies

Существует несколько способов доставки новых версий приложения. Каждая из них имеет свои плюсы и минусы. Изучите их и выберите наиболее подходящую. Отличный практический репозиторий с объяснениями на примере k8s

Bonus #2: Shutdown app gracefully with zero downtime

Деплой приложения подразумевает что текущие инстансы приложения будут постепенно удаляться и их место займут новые. Чтобы клиент в момент релиза не получил негативный опыт взаимодействия важно перед тем как удалять инстансы терпеливо дожидаться завершения всех клиентских запросов (если речь о HTTP) и не допускать ситуации что в момент деплоя инстанс который завершает свою работу продолжает принимать HTTP запросы.

Как безопасно завершить работу пода в Kubernetes: разбираемся с graceful shutdown и zero downtime деплоймент

API Design

Полезные ссылки:

Если считаешь что связка REST+JSON не подходит под задачу, или по заданию требуется другой формат, то стоит изучить альтернативы:

Authorization & Authentication

Аутентификация – процедура проверки подлинности, например, проверка подлинности пользователя путем сравнения введенного им пароля с паролем, сохраненным в базе данных.

В качестве аутентификации по API можно использовать:

Полезные ссылки

Авторизация – предоставление определенному лицу прав на выполнение определенных действий. Например: пользователь которого забанил администратор не может публиковать комментарии к постам (хотя он прошел аутентификацию на сайте).

Примеры библиотек:

Дополнительные ссылки:

MVC Explanation

Цель: разделить обязанности в коде между компонентами. MVC это один из вариантов достижения цели и не требует от разработчика сильной когнитивной нагрузки (по сравнению с другими подходами)

Controller

Model

Service

View

📐✏️👷‍♀️Architecture, Design Patterns, Refactoring, etc

После того как MVC стал открытой книгой стоит углубиться и изучить:

Бесплатные ресурсы, которые рекомендую для старта:

🔒CRUD: Validations

Перед тем как сохранять данные в БД обязательно:

CRUD: Database

P.S. При описании миграций полезно подсматривать сюда, чтобы не написать миграцию которая может заблокировать БД.

CRUD: Operations

LIST (HTTP GET)

API не должно возвращать все поля модели. Пример: если наше API возвращает список постов то оно должно возвращать:

Полный текст поста для этого эндпоинта не нужен.

READ (HTTP GET)

CREATE (HTTP POST)

Задачи со звездочкой:

DESTROY (HTTP DELETE)

Дополнительно может быть полезно: реализовать soft удаление (скрываем от пользователя, оставляем в БД)

External API Calls, Long-running tasks (And why we need message queue)

Если в рамках API требуется:

Для этого может понадобиться очередь (Queue) в которую можно будет добавлять задачу (Task).

Примеры высокоуровневых библиотек которых решают задачу с постановкой, чтением и обработкой задач:

Стоит отметить, что Redis это не единственный вариант для хранения очереди + не для всех задач он подходит. Поэтому полезно изучить как минимум 2 более продвинутых варианта для хранения и обработки очередей: RabbitMQ и Kafka.

Доп.ссылки:

Metrics

Logs

🛡️Security

CORS Headers (Cross-Origin Resource Sharing)

Если запросы к твоему API будут делать из браузерных скриптов, например Single Page Application, построенных на современных Javascript фреймворках (React, Angular, Vue.js) и домен API будет отличаться от домена клиентского приложения, то нужно в API добавить CORS заголовки, чтобы браузер не блокировал ответы от API.

Обычно, модуль для настройки CORS заголовков есть в http фреймворке и можно использовать его как по дефолту, так и с более тонкими настройками по необходимости. Например:

Подробнее про CORS заголовки можно прочитать здесь.

🚄Cache

Первым делом нужно задать себе вопросы:

Если твердо решили что нужен кеш то:

Remote Config / Feature Toggles / Feature Flags

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

Полезные ссылки:

Full Text Search

Transactions, Locks, Isolation Levels, ACID

Классические веб приложения подразумевают что в единицу времени может быть несколько пользователей (сотни / тысячи / миллионы). И дополнительно к этому пользователи могут взаимодействовать с одним общим ресурсом одновременно (классический сценарий - покупка билетов на мероприятие). Для того чтобы избежать состояний гонки, ошибок и нарушений бизнес-логики важно правильно организовать работу с базой данных как минимум:

Отличная статья которая даст начальное представление о проблемах конкурентности и согласованности в API