10 минут до кода
137 subscribers
83 photos
74 links
Твой ежедневный контекст в мире веб-разработки.

Без скучных уроков и академической нагрузки.
Читаешь канал 10 минут в день — убираешь кашу в голове и становишься программистом.

Просто. Понятно. Каждый день.
Download Telegram
С чего начинается разработка?

Начинающие разработчики часто думают, что старт проекта — это выбор стека и установка фреймворка. Пока вы учитесь, это ок, потому что за вас «тяжелую» работу по архитектуре уже сделали другие.

Но когда вы начинаете что-то свое, все начинается с одного вопроса: ЗАЧЕМ?

Зачем мы это делаем? Кто пользователь? Какую проблему решаем? Какая главная функция?

Без ответов на эти вопросы любой проект обречен. Вы будете бесконечно модифицировать код, потеряете смысл и просто забросите всё на полпути. Это работает везде: и в серьезных продуктах и в пет-проектах для «набивания руки». Нет цели — нет финала, нет прогресса.

Но что делать когда ответить на этот вопрос сложно?

Используйте нейронки. Не просите их придумать идею, а переключите в режим интервьюера. Пусть они «пытают» вас вопросами и вытаскивают из вас всю нужную информацию.

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

Ровно эту философию я внедрил в своем клубе «ВЕБМастер». Мы каждый месяц берем одну идею и проходим путь от ТЗ и декомпозиции до деплоя на сервер.

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

Проект текущего месяца я описывал у себя в паблике а войти в ВЕБМастер можно чрез бота клуба 👇

https://t.me/webmaster_club_bot

🎁 Самое приятное: попробовать участие можно всего за 1 рубль.

Буду ждать новых инженеров!

10МДК | ВЕБМастер
🔥3
Каскадное удаление: Целостность данных против логики приложения

Когда впервые натыкаешься на внешние ключи (Foreign Keys) и ON DELETE CASCADE в MySQL, возникает иллюзия полного контроля. Кажется, что ты наконец-то переложил скучную работу по очистке базы на плечи самой СУБД. Но на практике, особенно на этапе активной разработки, эта «магия» быстро превращается в проблему: попытка удалить одну тестовую сущность оборачивается ошибкой целостности, и ты сидишь, вручную отключаешь FOREIGN_KEY_CHECKS, чтобы просто поправить структуру данных.

Механизм «Слепого» удаления

Суть каскада проста: есть родительская таблица (например, projects) и дочерние (tasks, subtasks). Если мы удаляем проект, база автоматически вычищает всё, что к нему привязано. Это путь к идеальной целостности — в базе не остается «сирот» или мусорных записей, которые никуда не ведут. Но здесь кроется ловушка для архитектора.

Когда база удаляет записи каскадом, бэкенд об этом ничего не знает. Для приложения это «событийный разрыв». Если в коде прописана логика «при удалении заказа отправить письмо пользователю или инициировать возврат через API Stripe», то каскад в БД эту логику просто проигнорирует. Код удалил одну строку в users, а миллион связанных orders исчезли в подкапотке СУБД, не вызвав ни одного хука или события в вашем приложении.

Блокировки и глубокая задумчивость

В продакшене каскад может стать причиной отказа в обслуживании. Представьте пользователя-гиганта, у которого в системе миллион заказов. Когда он решает удалить аккаунт, один простой запрос на удаление инициирует лавину. СУБД уходит в глубокую задумчивость, пытаясь за одну транзакцию вычистить миллионы строк и обновить индексы. В этот момент база вешает блокировки, запросы в очереди растут, и ваш сервис ложится просто потому, что вы решили автоматизировать «уборку».

В инженерной практике для таких случаев используется Batch Delete. Вместо каскада мы пишем контролируемые запросы, которые удаляют данные пачками (например, по 5000 записей за раз) в цикле. Это позволяет базе «дышать» между запросами и не блокирует критически важные таблицы намертво.

Компромисс через SET NULL

Иногда полное выжигание данных — это не то, что нужно бизнесу. Если автор удаляет свой профиль, его статьи в блоге или комментарии не обязательно должны исчезать. Для этого существует ON DELETE SET NULL. Внешний ключ обнуляется, данные остаются, но привязка к сущности пропадает. Пост остается, но автор теперь — «Аноним». Это сохраняет историю и аналитику, избавляя базу от «битых» ссылок без потери полезного контента.

Инженерный взгляд на целостность

Каскад — это инструмент технической чистоты, а не бизнес-логики. Если вам нужно гарантировать, что в базе не останется ошметков данных после технических манипуляций — используйте каскад. Но если процессом должен управлять бизнес (логирование, уведомления, сторонние API), удаление должно быть явным и контролируемым на уровне приложения.

Чистая база данных — это круто, но работающий и предсказуемый продакшн — важнее.

Ставь 🔥, если тоже хоть раз отключал проверку ключей, чтобы просто почистить тестовые данные. А если остались вопросы или что-то звучит слишком абстрактно — пиши в комменты, обязательно разберем!

10МДК | ВЕБМастер
2🔥2
Ретрай-политики: Как не превратить обработку ошибок в DDoS-атаку на самого себя

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

Внешние API и распределенные системы — это агрессивная среда. Если вы работаете с LLM вроде ChatGPT или Claude, вы не можете гарантировать 100% аптайм или стабильный ответ. Единственное, что вы можете гарантировать — это факт вашей попытки достучаться до эндпоинта.

Ловушка вложенных try-catch

Первое инстинктивное решение — обернуть запрос в try-catch. Если упало — вызываем запрос еще раз внутри блока catch. Но это путь к бесконечной вложенности и «гонке вооружений» с неопределенностью. Вы не знаете, сколько раз упадет сервер: два, три или десять. Дублирование логики обработки ошибок делает код хрупким и невыносимым в дебаге.

Инженерный подход требует выноса логики повторов в отдельный управляемый механизм. Базовый вариант — отложенный повтор. Вместо того чтобы стучать в закрытую дверь каждые 100 миллисекунд, мы должны дать удаленной системе «продышаться» пару секунд. За это время на сервере может инвалидироваться кэш или завершиться процесс очистки памяти, который мешал обработке вашего запроса.

Экспоненциальное ожидание и фактор хаоса

Но простой линейный ретрай (повтор каждые 2 секунды) — это риск само-DDoS’а. Представьте, что у 1000 пользователей одновременно отвалился бэкенд. Если у всех зашит жесткий интервал, то через 2 секунды сервер получит волну из 1000 новых запросов, потом еще одну через 2 секунды. Вместо восстановления вы добьете систему ритмичными ударами.

Решение — Exponential Backoff. Мы увеличиваем паузу после каждой неудачи: 1, 2, 4, 8, 16 секунд. Это разгружает сеть, но оставляет проблему «волн», когда тысячи клиентов синхронно ждут и синхронно бьют в одну и ту же дверь.

Чтобы размазать нагрузку, в формулу добавляется Jitter (джиттер) — контролируемый хаос. Мы берем наше экспоненциальное время и умножаем на случайный коэффициент. В итоге один клиент повторит запрос через 4.1 секунды, второй — через 3.8, а третий — через 4.5. Нагрузка на сервер становится размазанной и плавной, что дает системе реальный шанс вернуться в строй.

Идемпотентность: Главный предохранитель

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

Если вы ретраите запрос на получение данных (GET) — это безопасно. Но если вы ретраите списание средств или создание заказа без ключа идемпотентности, вы рискуете списать деньги дважды или создать дублирующие записи в базе. Бэкенд должен уметь определять: «Так, этот запрос с ID #555 я уже видел и успешно обработал, просто верну старый результат», вместо того чтобы запускать логику транзакции заново.

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

🔥 — если пост был понятен. А если остались вопросы или что-то звучит слишком абстрактно — пиши в комменты, обязательно разберем!

10МДК | ВЕБМастер
🔥4
Хирургия кода: Почему швейцарский нож убивает архитектуру

Single Responsibility Principle (SRP) — это база, которую цитируют все, но на практике часто превращают в абсурд. Многие воспринимают SRP как требование дробить код до атомарного состояния, когда описание функции занимает больше строк, чем само тело с единственным вызовом сторонней библиотеки. Это перегиб. Истинный смысл SRP не в минимизации строк, а в четкой функциональной деятельности.

Штопор в операционной: Опасность универсальных инструментов

Представьте хирурга, который оперирует пациента швейцарским ножом. В теории — это нож, он может резать. Но на практике, пока врач делает надрез, он рискует зацепить пациента открытым штопором. В коде это выглядит так: вы меняете логику расчета скидки, а у вас внезапно «отваливается» генерация PDF-отчетов.

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

Лингвистический тест на чистоту реализации

Самый быстрый способ продиагностировать код на нарушение SRP — это проговорить вслух, что делает конкретный метод. Если в описании появляется союз «и», вы нарушили принцип.

- «Эта функция проверяет права доступа И достает данные из базы И форматирует их в JSON».

Здесь как минимум три разных зоны ответственности. Каждое «и» — это вектор для выделения логики в отдельную сущность. Разделение этих действий упрощает не только дебаг, но и переиспользование. Вам может понадобиться достать те же данные для другого эндпоинта, но уже без проверки прав в этом конкретном месте или с другим форматированием. Если всё зашито в одну «швейцарскую» функцию, вам придется либо дублировать код, либо городить костыли.

Экономика инженерных решений

Соблюдение Single Responsibility напрямую влияет на стоимость поддержки и регрессионного тестирования. В большой системе даже минорная правка может потребовать перепроверки всех связностей. И вот фикс “на 5 минут” растягивается на пару часов.

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

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

🔥 — если теперь понимаешь SRP. А если остались вопросы или что-то звучит слишком абстрактно — пиши в комменты, обязательно разберем!

10МДК | ВЕБМастер
🔥5
🥳 Квиз день!

Если хотите дополнительный 4-ый вопрос, ставьте 🔥 этому посту.

Наберем 20 — опубликую бонусный квиз 😉

10МДК | ВЕБМастер
🔥6
Сервис обработки заказов должен вызвать API логистической службы. API временно недоступно (503). Как реализовать логику повторов, чтобы минимизировать нагрузку на шлюз и сохранить целостность данных?
Anonymous Quiz
7%
Цикл while(true) с немедленным повтором запроса до получения кода 200
33%
Рекурсивный вызов в блоке catch с фиксированным интервалом в 1 секунду
60%
Exponential Backoff с добавлением Jitter и передача ключа идемпотентности
0%
Использование каскадного удаления (ON DELETE CASCADE) для очистки транзакции
Лифт против микроволновки: Как проектировать предсказуемые системы

Слово «идемпотентность» звучит как заклинание, которое сложно выговорить с первого раза без запинки. Но за этим тяжеловесным термином скрывается максимально примитивная логика. Инженер должен гарантировать: сколько бы раз мы ни дергали один и тот же ендпоинт с одинаковыми данными, состояние системы изменится только один раз.

Представьте кнопку вызова 10-го этажа в лифте. Вы можете нажать её один раз, а можете в приступе нетерпения ударить по ней сотню раз. Лифт всё равно приедет на 10-й этаж и откроет двери один раз. Он не будет кататься вверх-вниз или хлопать дверьми пропорционально количеству нажатий. Эта кнопка — идемпотентна.

А теперь возьмём кнопку «+30 секунд» на микроволновке. Каждое нажатие меняет состояние системы: было 30 секунд, стало 60, потом 90. Нажмете 100 раз — и вместо разогретого обеда получите угли. Это пример неидемпотентного поведения.

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

Сценарий боли: Сбой связи в метро

В идеальном мире индемпотентность вообще не нужна. Но мы, увы, работаем в неидеальном мире, и наш код крутится в такой же среде.

Классический кейс: пользователь в метро покупает кроссовки. Он жмет «Оплатить», пакеты улетают на сервер, бэкэнд успешно проводит транзакцию, но в этот момент связь обрывается. Ответный пакет до клиента не доходит.

Что видит пользователь? Бесконечный лодер.
Что он делает? Обновляет страницу и жмет «Оплатить» еще раз.

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

Механика: Идемпотентный ключ

Чтобы бэкэнд понимал, что запрос пришел повторно, нам нужен «якорь» — Idempotency Key. Это уникальный идентификатор операции, который мы генерируем, чтобы отличать запросы и транзакции.

Как это работает под капотом:

1. Клиент отправляет запрос с заголовком Idempotency-Key: uuid-123-456.
2. Бэкэнд проверяет: «Я уже видел этот ключ?».
3. Если нет — обрабатывает запрос, сохраняет результат в базу или кеш и отдает ответ.
4. Если ключ уже есть в системе — бэкэнд просто достает из базы старый успешный ответ и отдает его клиенту, даже не пытаясь заново проводить оплату или менять данные.

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

Стандарты и «костыли»

В вебе есть базовый этикет. По стандарту HTTP-методы GET, PUT и DELETE должны быть идемпотентными. Сколько ни удаляй один и тот же пост по его ID (DELETE), он останется удаленным. Сколько ни запрашивай профиль юзера (GET), данные не должны мутировать.

Проблема всегда в POST. По своей природе он не идемпотентен, так как обычно создает новую сущность. Именно поэтому для всех критичных POST-запросов (платежи, заказы, переводы) нам нужны свои инженерные «костыли» в виде ключей идемпотентности.

Инженерный чеклист:
Если операция меняет баланс, создает заказ или отправляет письмо — она обязана быть идемпотентной. Иначе вы просто ждете момента, когда кто-то в метро нажмет кнопку дважды. 😉

🔥 — если теперь можешь объяснить идемпотентность бабушке. А если остались вопросы или что-то звучит слишком абстрактно — пиши в комменты, обязательно разберем!

10МДК | ВЕБМастер
🔥4
GraphQL: Свобода фронтенда и ловушка производительности

В REST архитектура диктует правила: один эндпоинт — один ресурс. Если тебе нужно собрать данные для профиля пользователя, где висят его последние заказы, ты идешь в /users/{id}, забираешь данные, а потом отдельным запросом стучишься в /orders?user_id={id}. Два запроса, два ожидания, лишний оверхед на сетевые задержки.

GraphQL меняет парадигму. Вместо того чтобы бегать по разным «ручкам», клиент обращается к единому порталу.

Если REST — это классический магазин, где ты точно знаешь, на какой полке лежат яблоки, а на какой хлеб, то GraphQL — это окно выдачи. Ты просто диктуешь список покупок в одно окно, и тебе выезжает собранный пакет. Один запрос — и в ответе сразу и юзер, и его заказы, и даже статус программы лояльности.

Схема как жесткий контракт

Вся магия держится на схеме(Schema). Бэкенд жестко описывает типы данных и связи между ними. Для фронтенд-инженеров это превращается в идеальный рабочий процесс: Тебе не нужно выпрашивать документацию у бэкэндера или гадать, какое поле придет в ответе. Ты открываешь специальный софт (Apollo Studio) идешь там в песочницу, где работает автодополнение, и сам как из кубиков лего собираешь запрос.

Схема — это живая документация.

Иллюзия скорости и проблема N+1

Главное заблуждение — считать, что GraphQL быстрее просто потому, что запрос один или потому что мы грузим только необходимые данные. На практике гибкость клиента часто оборачивается кошмаром для базы данных.

Когда фронтенд запрашивает дерево связанных объектов, бэкенд может свалиться в проблему N+1. Если ваш бэкэнд написан не оптимально, сервер на один запрос клиента сделает один запрос в БД за пользователем и еще сто запросов за каждым его заказом по отдельности. В итоге один «красивый» запрос в GraphQL может выполняться дольше, чем пять параллельных запросов в REST.

Инженерные компромиссы: Кэширование и Трафик

GraphQL так же ломает привычные инструменты оптимизации и работы с вебом.

1. Смерть HTTP-кэширования: В REST каждый URL уникален, его легко закэшировать на уровне браузера или CDN. В GraphQL у тебя всегда один эндпоинт (обычно /graphql) и всегда метод POST. Стандартные механизмы кэширования тут бесполезны — инженерам приходится внедрять сложные решения на уровне объектов внутри приложения.
2. Операции: Вместо стандартных методов (GET, POST, PUT) мы используем query для получения данных, mutation для их изменения и subscriptions, когда нужно подписаться на события через вебсокеты.

Когда это оправдано?

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

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

🔥 — если работали с GraphQL и ловили N+1
🤔 — если REST кажется надежнее

А если остались вопросы или что-то звучит слишком абстрактно — пиши в комменты, обязательно разберем!

10МДК | ВЕБМастер
🔥3
Ловушка зависимостей: Почему чужой код — это арендное жилье

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

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

В разработке «прорыв трубы» — это критическая уязвимость или легаси, которое блокирует развитие системы. Если мейнтейнер ушел в закат и забросил репозиторий, вы остаетесь один на один с кодом, который вам не принадлежит, но от которого зависит работоспособность вашего продакшна.

Инфраструктурный тупик и цена «бесплатного» кода

Прямо сейчас я наблюдаю этот сценарий в реальном проекте. Система критически зависит от библиотеки, на которой построен весь админ-интерфейс. Пока стек был актуальным, всё работало идеально. Но пришло время обновлять версию PHP и фреймворка, чтобы соответствовать современным стандартам безопасности и производительности.

Результат — инфраструктурный ад. Библиотека заброшена, версии конфликтуют, обновиться невозможно. У бизнеса теперь три плохих варианта:

1. Искать замену и переписывать огромный пласт UI.
2. Форкать чужой код, фиксить его самостоятельно и поддерживать вечно.
3. Копировать логику к себе и превращать её в собственное легаси.

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

Архитектурный щит: Anti-Corruption Layer

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

Решение — Anti-Corruption Layer (ACL). Это защитный слой, состоящий из ваших собственных интерфейсов, оберток и адаптеров.

- Ваше приложение никогда не вызывает сторонний пакет напрямую.
- Оно общается с вашим интерфейсом (Wrapper/Adapter).
- Ваш код внутри адаптера уже дергает методы библиотеки.

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

Ставь 🔥 если не думал что от сторонних библиотек может быть столько проблем.

А если остались вопросы или что-то звучит слишком абстрактно — пиши в комменты, обязательно разберем!

10МДК | ВЕБМастер
🔥4
Pull Request: Таможня на границе продакшна

Pull request — это не просто кнопка в GitHub, а единственный способ не превратить репозиторий в помойку, особенно когда в команде больше одного разработчика. Даже если ваш единственный напарник — это LLM-агент, работа через PR остается критически важной.

Суть процесса заложена в названии: вы просите (request) основную ветку (main или master) «вытянуть» (pull) ваши изменения. Это фильтр, который отделяет сырой код в вашей ветке от стабильного состояния системы в продакшне.

Механика таможенного контроля

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

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

Проблема когнитивной нагрузки

Существует золотое правило индустрии: если в Pull Request 10 строк кода, в нем найдут 3 ошибки. Если в PR 1000 строк, ревьюер напишет «looks good to me» и нажмет мердж.

Огромные PR на 2000+ строк — это кошмар. Мозг человека не способен удерживать контекст при такой когнитивной нагрузке. Когда изменений слишком много, ревьюер перестает читать код и начинает просто тестировать функционал. Это опасно: то, что фича работает сейчас, не гарантирует отсутствие технического долга под капотом.

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

Контекст как страховка

Код-ревью нужно не только для поиска багов, но и для синхронизации. Когда 10 разработчиков одновременно пилят разные фичи, кодовая база меняется быстрее, чем вы успеваете это осознать. Читая чужие PR, вы остаетесь в контексте: где теперь лежат ендпоинты API, как изменилась структура данных и какие архитектурные паттерны внедряются.

Хороший ревьюер не скажет «ты ошибся». Он скажет: «Здесь может возникнуть гонка состояний, давай попробуем реализовать это иначе». Это процесс взаимной страховки, а не трибунал. Работаете вы в соло или в огромном энтерпрайзе — PR защищает проект от хаоса, а вас — от потери управления над собственной системой.

🔥 — если делишь задачи на мелкие PR
🤔 — если считаешь, что в соло PR не нужны

А если остались вопросы или что-то звучит слишком абстрактно — пиши в комменты, обязательно разберем!

10МДК | ВЕБМастер
🥳 Квиз день!

Если хотите дополнительный 4-ый вопрос, ставьте 🔥 этому посту.

Наберем 20 — опубликую бонусный квиз 😉

10МДК | ВЕБМастер
🔥5
gRPC: Когда вызов метода важнее, чем манипуляция ресурсом

В архитектуре API принято считать REST стандартом, но когда мы говорим о взаимодействии микросервисов внутри системы, REST начинает буксовать. Основная проблема в том, что REST заставляет нас мыслить сущностями: User, Order, Payment. Мы манипулируем этими ресурсами.

gRPC (Remote Procedure Call) возвращает нас к логике прямого действия. Вам не нужно думать, какой HTTP-метод прикрутить к ендпоинту — вы просто вызываете удаленный метод CreateUser() так же естественно, как если бы он лежал в соседнем файле вашего проекта.

Подкапотка HTTP/2 и бинарный стриминг

gRPC — это не просто другой формат запросов, это другой фундамент. В отличие от классического REST, gRPC по дефолту работает на HTTP/2. Это дает нам две критические для продакшена вещи:

1. Мультиплексирование. Мы не открываем новое соединение на каждый чих. Множество запросов летят по одному каналу, что избавляет сеть от лишней нагрузки и оверхеда на установку соединений.
2. Стриминг. В REST передача потока данных без костылей вроде WebSockets практически невозможна. В gRPC клиент может стримить данные серверу, сервер — клиенту, или они могут делать это одновременно (бидирекциональный стриминг). Для распределенных систем, где нужно прокидывать тяжелые логи или real-time данные, это прям спасение.

Схема как закон: Протофайлы против документации

В REST описание схемы API через Swagger — это часто жест вежливости со стороны бэкенд-разработчика. В gRPC схема (proto-файлы) — это обязательный контракт. Вы описываете методы и типы данных в файлах .proto, а затем gRPC сам генерирует клиентский код и типизированные шаблоны для сервера.

Вам же остается только вписать бизнес-логику и походы в базу. Такой подход исключает ситуацию, когда фронт ожидает string, а бэк внезапно прислал null или int. Если данных нет в схеме — считай их нет и вовсе.

Почему байты быстрее текста

Самое наглядное различие между REST и gRPC — это способ упаковки данных. REST гоняет JSON. Это текстовый формат: куча кавычек, скобочек и повторяющихся имен полей. Это как перевозить мебель в полностью собранном виде. Красиво, понятно, но занимает чертовски много места в грузовике.

gRPC использует Protobuf — бинарный формат. Это плоские коробки из IKEA. Мы передаем только голые значения в строгом порядке, зашифрованные в байты. Чтобы «собрать» эту мебель на другом конце, у принимающей стороны должна быть инструкция — тот самый proto-файл. Без него эти байты — просто мусор, но с ним скорость парсинга и передачи данных возрастает в разы.

Где gRPC бесполезен, а где незаменим

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

Когда у вас сотни микросервисов, которые должны общаться друг с другом с минимальными задержками, gRPC становится идеальным клеем. Он создает иллюзию бесшовности: вы вызываете функции другого сервиса, находящегося на другом конце дата-центра, с той же легкостью, что и локальные методы. В высоконагруженных системах, где борьба идет за миллисекунды, экономия на парсинге JSON и эффективное использование соединений HTTP/2 — это единственный способ не положить сеть.

🔥 — если пост был понятен и полезен.

А если остались вопросы или что-то звучит слишком абстрактно — пиши в комменты, обязательно разберем!

10МДК | ВЕБМастер
🔥1
Скорость света как ограничение: зачем на самом деле нужна CDN

Физику обмануть не получится: если твой сервер находится в Огайо, а юзер открывает сайт в Бангкоке, пакеты данных будут идти долго просто по законам мироздания. Сигналу нужно время, чтобы преодолеть расстояние между континентами.

И для маленького локального магазина в США, куда случайно забрел турист из Таиланда, это не проблема. Но если ты строишь глобальный продукт, задержки в несколько секунд на загрузку интерфейса — это прямой путь к потере конверсии.

Когда клиенты разбросаны по всему миру, инженерная задача меняется: нам нужно сделать так, чтобы контент находился максимально близко к конечному устройству. Здесь в игру вступает CDN — Content Delivery Network.

Инфраструктура «пунктов выдачи»

По сути, CDN — это географически распределенная сеть серверов, которая работает в связке с твоим основным бэкендом. Мы не переносим туда бизнес-логику, мы делегируем CDN хранение и отдачу «тяжелой» статики: картинок, стилей, скомпилированных JS-бандлов и других ассетов.

Представь локальный оффлайн-магазин в Лиссабоне. Чтобы купить там товар, человеку из Сибири придется лететь через всю Европу. Это логистический ад.

CDN превращает эту схему в модель современного маркетплейса с сетью ПВЗ (пунктов выдачи заказов). Неважно, где находится твой главный склад; покупатель просто идет в ближайший к нему пункт и забирает товар мгновенно. В мире веба «пунктом выдачи» становится ближайший к юзеру сервер (например, в Катаре для пользователя из Таиланда), который отдает тяжелые файлы по кратчайшему пути.

Главный кошмар распределенных систем

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

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

В этот момент у тебя пропадает «единая точка правды». Ты видишь в логах, что билд прошел, но у тысячи юзеров в другом полушарии всё «развалилось», потому что стили обновились, а логика в старых скриптах их не понимает. Управление этим кэшем и синхронизация всех узлов сети — это цена, которую мы платим за высокую скорость доступа.

Прагматичный подход к внедрению

Стоит ли тащить CDN в каждый проект? Нет. Если ты пилишь внутренний сервис для сотрудников одного офиса или локальный портал для жителей конкретного города, CDN станет лишним звеном. Ты не только не получишь профита в скорости, но и добавишь себе геморроя с обновлением статики и лишними расходами на инфраструктуру.

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

🔥 — если пост был понятен и полезен.

А если остались вопросы или что-то звучит слишком абстрактно — пиши в комменты, обязательно разберем!

10МДК | ВЕБМастер
🔥1
Протоколы общения: Почему шкаф из IKEA не возят целиком

Когда наше приложение эволюционирует из простой функции в сложную систему, встает фундаментальный вопрос: как передать состояние между элементами системы?

Внутри кода мы оперируем ссылками на объекты в памяти, но как только данные должны покинуть пределы сервера и уйти в сеть по HTTP, ссылки превращаются в тыкву. В сетевом стеке не существует «объектов», там есть только поток байтов.

Инженерный подход здесь прост: раз всё в компьютерах в конечном счете сводится к файлам, а файлы — к тексту, значит, любой объект можно описать строкой. Так появилась сериализация.

Механика копирования, а не дегидрации

Существует опасное заблуждение, что сериализация — это своего рода «дегидратор»: засунули объект, высушили его до состояния сублимата, передали, а на другом конце «добавили водички» и получили тот же самый объект. Это не так.

На самом деле мы создаем Payload — детальное описание структуры и значений. Мы не перемещаем объект, мы отправляем инструкцию по его созданию на другой конец провода. В момент десериализации создается абсолютно новый инстанс. Да, он будет идентичен по данным, но в памяти это будет другой жилец. Сериализация — это всегда процесс создания слепка, а не телепортация оригинала.

Принцип плоской коробки

Чтобы визуализировать этот процесс, представьте огромный шкаф из IKEA. Пытаться перевезти его в собранном виде в другой город — это логистический кошмар и лишние траты.

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

Эволюция форматов: От XML к бинарному потоку

Раньше стандартом был XML. Он отлично справлялся с описанием сложных структур благодаря тегам, но подкапотка была тяжелой. Каждый «чих» сопровождался открывающим и закрывающим тегами. Когда у вас сотни полей, закрывающиеся теги превращаются в лишние килобайты данных, которые гоняются по сети впустую.

На смену пришел JSON (JavaScript Object Notation). Он выкинул визуальный шум XML, оставив лаконичную структуру «ключ-значение». Он читаем для человека, его легко парсить, и он весит значительно меньше. Для большинства публичных API это золотой стандарт.

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

Безопасность сборки

Как инженер, ты должен помнить: десериализация — это точка входа для атак. Если ты бездумно собираешь объект из строки, присланной извне, ты рискуешь исполнить вредоносный код, который злоумышленник зашил в эту «инструкцию». Никогда не доверяй входящему потоку данных без жесткой валидации, особенно если речь идет о сложных структурах данных.

🔥 — если пост был понятен и полезен.

А если остались вопросы или что-то звучит слишком абстрактно — пиши в комменты, обязательно разберем!

10МДК | ВЕБМастер