Road to FAANG

Road to FAANG

Аудитория: 18 000 подписчиков
Категория: Блоги
Java Буткемп — https://clck.ru/39NSHf
Курс Java Magics — https://clck.ru/38dLDY
Задать вопросы по обучению → @Fastwwway Тихон

YouTube — https://clck.ru/3B5SaA

Статистика канала

18 000 подписчиков

Последние посты

Road to FAANG
Обновил статус и потерял все данные? POST vs PATCHСитуация: пилишь фичу для профиля пользователя. Юзер может поменять свой статус, например, с «В сети» на «Пью кофе». Ты делаешь для этого метод в своем API. Тестируешь — работает. А через день прибегает менеджер с криком: «У нас пользователи после смены статуса теряют свои аватарки!». Как так-то? Все дело в выборе правильного HTTP-метода.Метод грубой силыСкорее всего, для обновления ты интуитивно выбрал POST. Ведь мы им постоянно пользуемся, чтобы что-то создавать, верно? Когда новый пользователь регистрируется, мы отправляем POST-запрос с его данными. Сервер берет эти данные и создает в базе новую запись. Все логично. Но тебе же надо было обновить!В результате происходит вот что: фронтенд, чтобы обновить только статус, отправляет на сервер объект, в котором есть только одно поле — status: "Пью кофе". А твой бэкенд, получив такой запрос, воспринимает его как команду «возьми вот ЭТИ данные и полностью замени ими ВСЕ, что было раньше у этого пользователя». Он так и делает: обновляет статус, а все остальные поля, которые не пришли в запросе, типа биографии и ссылки на аватар, просто затирает. Бац! И профиль пользователя становится пустым, за исключением нового статуса. Хирургическая точностьА как надо было? Для таких вот частичных, точечных обновлений в REST-архитектуре существует специальный метод PATCH. Ты как бы говоришь серверу: «Слушай, вот тебе ID пользователя. У него там много всяких данных, но ты их не трогай. Поменяй, пожалуйста, *только вот это конкретное поле* на новое значение, а остальное оставь как было».И сервер послушно выполняет твою просьбу. Он находит пользователя и меняет ему только статус. Биография, аватарка, имя — все остается на своих местах. Никаких потерянных данных и разгневанных пользователей. Почему же тогда для обновлений иногда используют POST? Потому что иногда метод на сервере, который отвечает за обновление статуса, вообще не ждет всю информацию о пользователе. Он заточен только под эту одну задачу. Ты передаешь ему ID пользователя и новый статус, а дальше этот метод сам найдет нужного пользователя в базе по ID, достанет его данные и поменяет только статус. Он не будет затирать все остальное. Это прописано прям в логике метода сервиса.В таких случаях POST используется как способ выполнить конкретную операцию. Это нормально для многих систем.Так что в итоге?PATCH точный, безопасный и предназначенный для одной задачи — частичного обновления ресурса.POST чаще всего отвечает за создание новых данных, но также может выполнять и любые другие операции, если сервер на них настроен.Понимание этих нюансов — это еще один шажок от новичка, который следует правилам, к разработчику, который понимает, почему эти правила существуют и когда их можно грамотно обойти.Ставь 🔥 и делись в комментах, что еще в REST кажется непонятным — разберем!Работаемс!
4 390
Road to FAANG
Идемпотентность в APIТы из своего приложения отправляешь запрос к внешнему сервису, а он завершается по таймауту. Как узнать, что там произошло? Сервер обработал запрос, но упал прямо перед отправкой ответа? Или получил запрос, но еще не успел обработать?Когда по сети передается большой объем данных, могут происходить проблемы с маршрутизацией, перебои и прочие ошибки. Именно поэтому важно разрабатывать API так, чтобы они были устойчивы к сбоям.Ответ-то ты все равно не получил, поэтому остается только повторить запрос несколько раз, пока не сработает. И, разумеется, это может привести к проблемам, если запрос не идемпотентный.Что такое идемпотентностьВ контексте API идемпотентность означает, что повторение одного и того же запроса несколько раз дает тот же результат, что и выполнение его один раз. В HTTP некоторые методы по своей природе идемпотентны — это означает, что их повторное выполнение не изменяет состояние сервера.Методы GET и DELETE — идемпотентны, так как повторное получение или удаление ресурса не должно менять его состояние. Ты удаляешь запись из базы по ID = 1, в базе пропадает такая запись. Если ты повторно удалишь запись по ID = 1, несуществующая теперь строка… ничего не произойдет, короче. Состояние твоей базы не изменится после этого, сколько раз ты бы не вызывал DELETE с ID = 1. Метод PUT также считается идемпотентным, потому что в REST он означает создание или полную замену ресурса на основании тела запроса. А так как в теле ты передаешь одно и то же, то и состояние в базе может поменяться только на это тело.Но POST, используемый для добавления новой записи в базу, не идемпотентен: если сервер успешно обрабатывает запрос, но по какой-то причине клиент не получает ответа и повторяет запрос — может создаться вторая запись. Но клиент этого не хотел! Он повторил запрос только потому, что не получил обещанного ответа! И вот чей-то заказ на PS5 был оплачен дважды.Поэтому надо сделать так, чтобы сервер обеспечивал идемпотентность POST-запросов: сколько бы раз клиент ни отправил один и тот же запрос — результат будет один и тот же, как будто запрос был выполнен один раз!Как сделать POST идемпотентным: Идемпотентные ключиНо как понять, что запрос один и тот же? Для этого используется идемпотентный ключ.Это уникальный идентификатор, который клиент генерирует и отправляет с запросом. Он работает как отпечаток пальца: позволяет серверу распознать и обработать повторный запрос корректно.На стороне клиента:1. Клиент генерирует уникальный ключ (например, UUID) для каждого действия.2. Ключ добавляется в заголовки запроса.3. Клиент сохраняет ключ локально и, в случае таймаута, повторяет запрос с тем же ключом.На стороне сервера:1. Сервер хранит идемпотентные ключи и соответствующие результаты в базе данных или кэше. Чтобы не переполнить хранилище, ключи хранятся со временем жизни (TTL) — от 10 минут до 48 часов.2. Сервер проверяет, встречался ли ключ раньше:• если нет — обрабатывает запрос и сохраняет результат с ключом;• если да — берет результат по этому ключу и возвращает клиенту.Важно, что обработка запроса и сохранение ключа должны быть атомарными. То есть либо и запрос выполнен, и ключ сохранен, либо ничего не выполнено.Что ты сказал, повториии — RetryПри неудачной попытке имеет смысл попробовать еще раз — возможно, это временный сбой. Но если сервер переживает аварию, повторные запросы могут только усугубить ситуацию.Даже с идемпотентностью безопаснее использовать стратегию экспоненциальной задержки: после первой ошибки клиент делает короткую паузу перед повторной отправкой, а если снова таймаут — увеличивает время ожидания перед каждым новым повтором по экспоненте. Сначала ждал 1 секунду, потом 2, 4, 8…Ответ клиентуЕсли пришел повторный запрос с тем же идемпотентным ключом, сервер возвращает тот же самый ответ, что и в прошлый раз. Это удобно для клиента: он воспринимает ответ как результат выполнения запроса, не зная, был ли это оригинальный или повторный отклик.Ставь лайки, если слово идемпотентность стало понятным!
4 730
Road to FAANG
За 15 минут рассказываю, что такое API простыми словами!Будешь великолепно знать, для чего это и как работает📺 СМОТРЕТЬ ВИДЕО
5 060
Road to FAANG
ТОП рекомендаций по код-ревьюСидишь ты, значит, пилишь фичу для нашего интернет-магазина. Добавляешь хитрую логику для расчета скидок или обновления статусов заказов. Локально все работает, тесты зеленые. Собираешь это дело, отправляешь в ветку и создаешь Pull Request – типа, "готовенько, народ, забирайте в прод!". И ждешь, что вот-вот твоя гениальность окажется у пользователя.Но вместо этого тебе прилетают комментарии. Стрелочки указывают на твой код, рядом какие-то вопросы, предложения, иногда даже восклицательные знаки. Ух ты, елки-палки! Сразу мысли: "Почему они придираются? Это же работает!". Это и есть код-ревью, и многим новичкам (да и не только) оно кажется пыткой или экзаменом.Давай разберемся, как делать ревью, чтобы коллеги сами хотели учитывать твои комментарии и ждали твоей проверки как праздника.Зачем вообще это надо?Ты написал кусок кода, а другие ребята из команды смотрят на него свежим взглядом. И это важно, потому что когда ты погружен в задачу, глаз замыливается. Ты можешь не заметить банальную опечатку, неочевидный баг, который вылезет только при определенных условиях, или просто не очень оптимальное решение. Ревьюеры помогают найти и устранить такие штуки.А еще ревью – это обмен знаниями. Ты видишь, как пишут другие, учишься новым приемам, узнаешь о фишках языка или фреймворка, о которых даже не подозревал. А когда ревьюишь ты, то глубже погружаешься в чужой код, видишь разные подходы к решению задач. Это одна из самых эффективных инвестиций в собственное развитие и качество кода.Что искать в коде?Сначала просто прочитай код, как книгу. В хорошем коде тебе должна быть понятна логика, и ты должен сразу видеть, что делает каждый метод. Если приходится ломать голову, значит, код можно сделать более читаемым, например, переименовать переменные и разбить длинный метод на несколько маленьких.Дальше включай режим детектива и ищи потенциальные проблемы. Попробуй обнаружить места, где может вылететь null; проверь циклы: нет ли там лишних операций, которые замедлят работу? Проверь, не тянет ли кто-то все данные из базы, когда нужна только пара строчек?И смотри на общую структуру. Соответствует ли код тем принципам, которые приняты в вашей команде? Не добавили ли в проект избыточные зависимости?Комментируй как босс!Главное правило: будь конкретным и вежливым. Вместо "Тут плохая логика" напиши: "Смотри, вот в этой строке мы считаем скидку до проверки на минимальную сумму заказа. А что, если сумма меньше? Получится, что скидка посчитается, но потом не применится. Может, сначала проверять сумму, а потом уже считать скидку?". Видишь разницу? Ты указываешь на проблему, объясняешь почему это проблема (на примере их же кода!), и предлагаешь вариант решения, но не настаиваешь.Используй вопросы: "А что будет, если...?", "Не думал над вариантом сделать...?", "Почему сделано именно так?". Это не звучит как обвинение, а скорее как приглашение к дискуссии. И всегда начинай ревью с чего-то позитивного, если есть за что зацепиться. "Круто, что добавил тесты на этот кейс!" или "Хорошо структурировано!".Тебе пишут?Если непонятно – спрашивай! "Не совсем понял, почему этот подход лучше в данном случае? Можешь привести пример?". Не бойся показаться глупым. Вопросы показывают, что ты хочешь разобраться. Иногда в процессе обсуждения оказывается, что и ревьюер что-то упустил, или твой вариант тоже хорош, и твой коллега только рад будет, если ты отстоишь свою правоту. Это нормальный рабочий процесс.Не спорь ради спора. Твоя цель – сделать код лучше, а не доказать, что ты знаешь все лучше всех. Принимай конструктивную критику, исправляй, учись. А если с чем-то категорически не согласен, аргументируй спокойно.Когда вся команда активно участвует в ревью, баги вылавливаются быстрее, знания распространяются, а новички растут. Ревью – это один из самых мощных инструментов для обучения и развития в команде. Используй его как возможность стать сильнее как разработчик. Это реально работает!Рассказывай в комментах, какой самый полезный совет ты получил на ревью!
4 980
Road to FAANG
Что будет, если парсить гигантский jsonНужен обмен данными? Кидаем JSON. Отправил строку, получил строку, распарсил и готово.Но вот на нагруженных проектах, когда данных становится много, эта обычная строка может превратиться в узкое горлышко. Твой сервис вдруг начинает отвечать медленнее, проц грузится под 100% и память заканчивается. Почему же JSON такой дорогой?JSON — это текст. Чтобы понять, где в нем число, строка, объект, массив — парсеру приходится читать его символ за символом. Ведь парсер не знает заранее, что поле "price" будет числом, а "name" — строкой. Ему приходится либо полагаться на схему, либо строить универсальное дерево из Map и List. А когда ты потом пытаешься это дерево запихнуть в свои красивые Java-классы (десериализовать), происходит приведение типов. И тут, бац! Пришла строка "null" вместо числа, а ты пихаешь в int, ошЫбка.Вот представь, что у тебя есть список из тысячи объектов, например, товаров в интернет-магазине. Каждый товар — это JSON-объект с ключами типа "id", "name", "price","currency". Эти названия ключей повторяются тысячу раз в твоем JSON! Это занимает место в памяти, при передаче по сети, и заставляет парсер тысячу раз читать почти одинаковые строчки.JSON часто выглядит, как матрешка из объектов: вот массив, а внутри него объект, внутри которого опять массив, внутри которого… короче, ты понял. Чем глубже эта матрешка, тем сложнее парсеру отслеживать, где он находится, какой уровень он обрабатывает, куда возвращаться после закрывающей скобки. Ты получаешь JSON, парсер идет по этой строке и видит {, понимает: "Ага, начался объект!". Видит [: "Начался массив!". Видит ": "Сейчас будет строка!".Последствия для приложенияВсе эти операции требуют процессорного времени. Особенно если JSON большой или если ты парсишь его постоянно, например, при каждом входящем запросе. Твой сервер тратит драгоценные циклы CPU не на бизнес-логику, а на разбор текста.Кроме того, если тебе нужно принять большой JSON от клиента или, наоборот, собрать и отдать клиенту JSON с кучей данных, сериализация и десериализация могут занимать десятки или сотни миллисекунд. Для высоконагруженных систем это может быть критично. А если ты работаешь с большими JSON-документами или держишь много десериализованных объектов в памяти, будь готов к повышенному потреблению RAM. Короче, минусов много.Так что же делать, если отказаться от JSON нельзя?Если проектируешь JSON, делай структуру максимально плоской, насколько это возможно и логично. Иногда лучше разделить один сложный, глубоко вложенный документ на несколько более простых. И используй полезные фичи из библиотек! Например, в Java есть Jackson и Gson, которые позволяют гибко управлять процессом сериализации и десериализации. Вешаешь аннотации @JsonIgnore, @JsonProperty, чтобы включать в JSON только те поля Java-объектов, которые действительно нужны клиенту или другому сервису, и твой джейсон уже не такой уж и гигантский.А если у тебя есть данные, которые редко меняются, но часто отдаются в формате JSON, кешируй! То есть, один раз преврати Java-объекты в JSON и храни эту готовую строку в кэше. Отдавать клиенту строчку из кэша в разы быстрее, чем каждый раз собирать объекты и сериализовать их!Ставь 🔥, если узнал что-то новое!Работаемс!
5 690

Оставить комментарий/отзыв

Рекомендации

мурмадол

мурмадол

@murmadol
18.3K подписчиков

№ 5827049526 Polina Реклама/бартер/вп: @PRMURMADOL other: @murmadollk TWITCH: twitch.tv/murmadoll INST:...

KARAVALIEV

KARAVALIEV

@Karavaliev_Zagid
17.2K подписчиков

А Када не Када 🌚 📲 По рекламе - @bylipton

Арсений Петров

Арсений Петров

@arrrsenypetrov
17.4K подписчиков

Блоггер. Путешествия, гаджеты, секс хороший и душные напутствия — благостно и по уму!⚜️ Менеджер: @potatoalek...

Sanya Bortich

Sanya Bortich

@sanyabortichsanya
17.5K подписчиков

№ 5733928436

sheydov

sheydov

@sheydov
17.6K подписчиков

networks

kiririlll

kiririlll

@kiririlllme
17.4K подписчиков

несказанное — https://neskazannoe.com/ - «песнидля» искать по хэштегу #песнядля - по вопросам рекламы @kiriri...

ТКАЧЁВА. ЛИЧНОЕ❤️

ТКАЧЁВА. ЛИЧНОЕ❤️

@tkacheva_lichnoe
20.2K подписчиков

Валерия Ткачёва. Тут без Владиславовна. Связь в direct: https://www.instagram.com/iam_tkacheva?igsh=MXQwZHF1a...

Palladiy

Palladiy

@palundy
17.6K подписчиков

ТАТУИРУЮ В САНКТ ПЕТЕРБУРГЕ .

🏆 Data Feeling | AI

🏆 Data Feeling | AI

@datafeeling
18.8K подписчиков

IT предприниматель и препод 🧑‍🏫 ex-ML лидер в Dodo Brands 🦤🍕 Прокачиваю людей в Data Science 🚀 Победитель Ste...

INFABOSS

INFABOSS

@infabosspro
16K подписчиков

Заявление в РКН № 5038469366 Единственный официальный канал INFABOSS. Реклама: @venre_pr @ssempaai @pr_dari...