Стажировка в Т-банк одна из лучших возможностей для старта в разработке:
• специалисты высокого класса
• зарплаты в среднем выше рынка
• современный стек и проекты
• хорошо выстроены процессы
• корпоративная культура
Для участия нужно подать анкету заполнить анкету до 6 сентября и выполнить экзамен. Разбор программирования уже выложен на нашем курсе бэкенд про.
➡️ Записаться.
Как заполнять анкеты смотрим этот ролик. Вашу анкету оценивают рекрутеры, команды. Если вы им понравитесь, вас пригласят на финальное собеседование.
На собесе может быть все, что угодно на усмотрение интервьюера: могут быть даже математические задачи на логику в духе тюремных загадок. Обязателен лайвкодинг с задачами, которые часто подбирают под ваше направление (фронтендерам замыкания и event loop, Goшникам работа с рутинами и т.п.). Технические вопросы сильно зависят от команды: например, в команде T‑Мобайла гоняют по сетям, а в продуктовых в основном спрашивают синтаксис и основы. Иногда собеседование может пройти в формате "вайбчека" без технических вопросов, но это скорее исключение. Короче все, что есть в нашей программе курсов бэкенд старт и бэкенд про. Пример нашего выпускника здесь.
Обычно финальный собес один на полтора часа. Если прям очень хорошо о себя завили в анкете и хорошо показали на собесе - команда может дать хороший отзыв и тогда вам могут предложить еще одно собеседование, но такое бывает редко. Дополнительный финальный собес можно получить, если податься на донабор, который проходит обычно спустя месяц основного набора.
При идеальном мэтче, вы в Т-банке - поздравляю!
Подписаться: @codeof_art
• специалисты высокого класса
• зарплаты в среднем выше рынка
• современный стек и проекты
• хорошо выстроены процессы
• корпоративная культура
Для участия нужно подать анкету заполнить анкету до 6 сентября и выполнить экзамен. Разбор программирования уже выложен на нашем курсе бэкенд про.
Как заполнять анкеты смотрим этот ролик. Вашу анкету оценивают рекрутеры, команды. Если вы им понравитесь, вас пригласят на финальное собеседование.
На собесе может быть все, что угодно на усмотрение интервьюера: могут быть даже математические задачи на логику в духе тюремных загадок. Обязателен лайвкодинг с задачами, которые часто подбирают под ваше направление (фронтендерам замыкания и event loop, Goшникам работа с рутинами и т.п.). Технические вопросы сильно зависят от команды: например, в команде T‑Мобайла гоняют по сетям, а в продуктовых в основном спрашивают синтаксис и основы. Иногда собеседование может пройти в формате "вайбчека" без технических вопросов, но это скорее исключение. Короче все, что есть в нашей программе курсов бэкенд старт и бэкенд про. Пример нашего выпускника здесь.
Обычно финальный собес один на полтора часа. Если прям очень хорошо о себя завили в анкете и хорошо показали на собесе - команда может дать хороший отзыв и тогда вам могут предложить еще одно собеседование, но такое бывает редко. Дополнительный финальный собес можно получить, если податься на донабор, который проходит обычно спустя месяц основного набора.
При идеальном мэтче, вы в Т-банке - поздравляю!
Подписаться: @codeof_art
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3
Forwarded from Поступашки - ШАД, Стажировки и Магистратура
This media is not supported in your browser
VIEW IN TELEGRAM
Открылся отбор на стажировку в Т-Банк
Задачи уже выложены в нашем чате (тут).
Специально для участников курсов про уже мы уже выложили разбор соответствующих экзаменов. В разборе мы покажем подход к решению задач и как оформить ответ, чтобы получить высокий балл.
Также на курсах будет доступно:
📌 Вопросы и запись — менеджеру
Задачи уже выложены в нашем чате (тут).
Специально для участников курсов про уже мы уже выложили разбор соответствующих экзаменов. В разборе мы покажем подход к решению задач и как оформить ответ, чтобы получить высокий балл.
Также на курсах будет доступно:
🔽 Курс по выходу на доход в валюте🔽 Разбор текущей стажировки Яндекса🔽 Гарантия оффера🔽 Огромный банк технических вопросов🔽 Рефералка в бигтех после защиты пет-проекта🔽 mock-собеседования с обратной связью
Please open Telegram to view this post
VIEW IN TELEGRAM
Реальное собеседование на стажировку Go‑разработчика в Т‑Банк
Наш студент сделал расшифровку записи собеса, делимся с вами! Кстати, решение экзамена уже выложено на нашем курсе бэкенд про, ии агенты про и алгоритмы про.
➡️ Записаться.
1. «Расскажи, что такое Firewall?»
Собеседование было в команду, которая разрабатывает host‑based firewall на eBPF с Control Plane в Kubernetes. Интервьюер рассказал про свою команду и задал этот уточняющий вопрос + спросил понял ли я, чем занимается команда.
• Firewall – система, управляющая сетевыми доступами: пропускает или блокирует трафик на основе правил (IP, порты, протоколы).
• Команда пишет распределённый firewall, который работает на десятках тысяч хостов в банке, управляется централизованно через Kubernetes. Стек: Go, eBPF, gRPC, Linux.
2. «Какой у тебя опыт с Linux и сетями?»
Я сам особо не занимался бэкендом и го, знаю основы: модель OSI, TCP vs UDP (TCP надёжный с подтверждением, UDP быстрый без гарантий), маски подсетей, маршрутизацию. Линуксом владею на уровне пользователя, но готов быстро адаптироваться.
3. «Чем процесс отличается от потока? Зачем вообще нужны потоки?»
• Процесс – изолированный экземпляр программы со своей памятью, файловыми дескрипторами.
• Поток – легковесная единица внутри процесса, потоки разделяют память процесса. Потоки нужны для параллельного выполнения задач внутри одного процесса и эффективного обмена данными.
4. «Чем горутина отличается от треда в Go?»
• Горутина – легковесный поток, управляемый рантаймом Go, а не ОС. Она занимает меньше памяти (несколько КБ), переключение между горутинами дешевле. Планировщик Go мультиплексирует горутины на системные треды (модель M:N).
• В отличие от тредов, горутины не привязаны жёстко к одному системному треду.
5. «Что такое gRPC? На каких протоколах работает? В чём отличие HTTP/2 от HTTP/1.1?»
• gRPC – фреймворк для удалённого вызова процедур от Google. Использует HTTP/2 в качестве транспорта и Protobuf для сериализации.
• HTTP/2 поддерживает мультиплексирование запросов, сжатие заголовков, работу в дуплексном режиме.
• По сравнению с HTTP/1.1, это даёт меньшую задержку и более эффективное использование соединений.
6. Задача на ревью кода
Дан HTTP‑хендлер, который проксирует запросы во внешнее API и кеширует ответы, чтобы реже ходить в платное API. Найденные проблемы:
• Кеш не заполнялся – после успешного запроса результат не сохранялся. ➜ Добавлена запись в map.
• Проверка наличия ключа – использовалась
• Метод POST – хендлер принимает только POST, хотя логичнее GET (но это контракт, оставлено).
• Race condition – конкурентные запросы к map без синхронизации. ➜ Добавлен
• Утечка памяти – кеш бесконечно растёт, нет ограничений по размеру или TTL. ➜ Нужно добавить политику вытеснения (LRU) или время жизни записей.
7. «Как бы ты добавил тесты?»
Я предложил тест, который проверяет, что повторный запрос не идёт в API (счётчик вызовов), и что при параллельных запросах нет гонок – с помощью флага
8. «После деплоя сервис падает через несколько дней без паники. Что делать?»
Причина – кеш разрастается до заполнения памяти. Решения:
• добавить ограничение на размер кеша,
• внедрить TTL для записей,
• настроить мониторинг памяти и алерты.
Еще больше вопрос в нашем открытом банке собесов и тестовых заданий: смотрите на сайте.
Подписаться: @codeof_art
Наш студент сделал расшифровку записи собеса, делимся с вами! Кстати, решение экзамена уже выложено на нашем курсе бэкенд про, ии агенты про и алгоритмы про.
1. «Расскажи, что такое Firewall?»
Собеседование было в команду, которая разрабатывает host‑based firewall на eBPF с Control Plane в Kubernetes. Интервьюер рассказал про свою команду и задал этот уточняющий вопрос + спросил понял ли я, чем занимается команда.
• Firewall – система, управляющая сетевыми доступами: пропускает или блокирует трафик на основе правил (IP, порты, протоколы).
• Команда пишет распределённый firewall, который работает на десятках тысяч хостов в банке, управляется централизованно через Kubernetes. Стек: Go, eBPF, gRPC, Linux.
2. «Какой у тебя опыт с Linux и сетями?»
Я сам особо не занимался бэкендом и го, знаю основы: модель OSI, TCP vs UDP (TCP надёжный с подтверждением, UDP быстрый без гарантий), маски подсетей, маршрутизацию. Линуксом владею на уровне пользователя, но готов быстро адаптироваться.
3. «Чем процесс отличается от потока? Зачем вообще нужны потоки?»
• Процесс – изолированный экземпляр программы со своей памятью, файловыми дескрипторами.
• Поток – легковесная единица внутри процесса, потоки разделяют память процесса. Потоки нужны для параллельного выполнения задач внутри одного процесса и эффективного обмена данными.
4. «Чем горутина отличается от треда в Go?»
• Горутина – легковесный поток, управляемый рантаймом Go, а не ОС. Она занимает меньше памяти (несколько КБ), переключение между горутинами дешевле. Планировщик Go мультиплексирует горутины на системные треды (модель M:N).
• В отличие от тредов, горутины не привязаны жёстко к одному системному треду.
5. «Что такое gRPC? На каких протоколах работает? В чём отличие HTTP/2 от HTTP/1.1?»
• gRPC – фреймворк для удалённого вызова процедур от Google. Использует HTTP/2 в качестве транспорта и Protobuf для сериализации.
• HTTP/2 поддерживает мультиплексирование запросов, сжатие заголовков, работу в дуплексном режиме.
• По сравнению с HTTP/1.1, это даёт меньшую задержку и более эффективное использование соединений.
6. Задача на ревью кода
Дан HTTP‑хендлер, который проксирует запросы во внешнее API и кеширует ответы, чтобы реже ходить в платное API. Найденные проблемы:
• Кеш не заполнялся – после успешного запроса результат не сохранялся. ➜ Добавлена запись в map.
• Проверка наличия ключа – использовалась
if val != "", что ломается при пустом ответе. ➜ Использован второй параметр ok при чтении из map.• Метод POST – хендлер принимает только POST, хотя логичнее GET (но это контракт, оставлено).
• Race condition – конкурентные запросы к map без синхронизации. ➜ Добавлен
sync.Mutex с Lock/Unlock при каждом обращении.• Утечка памяти – кеш бесконечно растёт, нет ограничений по размеру или TTL. ➜ Нужно добавить политику вытеснения (LRU) или время жизни записей.
7. «Как бы ты добавил тесты?»
Я предложил тест, который проверяет, что повторный запрос не идёт в API (счётчик вызовов), и что при параллельных запросах нет гонок – с помощью флага
-race.8. «После деплоя сервис падает через несколько дней без паники. Что делать?»
Причина – кеш разрастается до заполнения памяти. Решения:
• добавить ограничение на размер кеша,
• внедрить TTL для записей,
• настроить мониторинг памяти и алерты.
Еще больше вопрос в нашем открытом банке собесов и тестовых заданий: смотрите на сайте.
Подписаться: @codeof_art
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3
Открываем новую серию постов. Смысл такой: берём известный проект, смотрим, как в нём решили какую-нибудь неочевидную проблему, и разбираемся, чем этот приём полезен лично тебе в твоём коде. Без душной теории — только то, что реально пригодится. И начать хочу с истории, которая случалась с каждым, кто хоть раз что-то куда-то сохранял.
Ты сохранил данные. Сервис ответил «готово». Ты выдохнул и пошёл дальше. Знакомо? А теперь неприятная новость: «сервис ответил готово» и «данные действительно на месте» — это два разных события. Между ними есть щель, и данные умеют в неё проваливаться. Причём случается это ровно в тот момент, когда что-то ломается, — то есть в самый неподходящий. Чтобы увидеть эту щель во всей красе, посмотрим, как с ней воюет Kafka. А потом вернёмся к твоему коду, потому что проблема там ровно та же.
Как Kafka бережёт данные. Она хранит каждую порцию сообщений сразу на нескольких серверах: один главный, он принимает записи, остальные — его копии, они за ним повторяют. Звучит надёжно. Но вот ловушка, в которую попадают почти все. Главный сервер принял сообщение, записал у себя, ответил «принято» — и в следующую секунду умер. А копии не успели повторить за ним. На его место встаёт одна из копий, но у неё этого сообщения нет. Всё, сообщение исчезло. А отправитель-то уверен, что всё хорошо, — ему же ответили «принято».
Как эту дыру закрывают. У отправителя есть настройка, которая решает, когда считать сообщение сохранённым. Можно сказать «мне хватит, что его принял главный» — быстро, но это ровно та история с исчезновением. А можно потребовать «считать сохранённым, только когда его повторили и живые копии тоже». Вот тогда появляется настоящая гарантия: даже если главный умрёт, сообщение уже есть на других.
Но и это не всё. Что, если копии отстали и по одной повыпадали, а живым остался только главный? Тогда правило «пусть подтвердят копии» тихо превращается в «пусть подтвердит главный» — и мы снова там же, откуда начали. Поэтому есть ещё одна настройка-предохранитель: «если живых копий осталось меньше, чем нужно, — вообще перестань принимать записи и честно скажи об этом». Лучше отказать сразу, чем сделать вид, что всё сохранилось, и потерять данные молча.
И вот тут главная мысль, ради которой всё затевалось. Это выбор, а не значение по умолчанию. Хочешь надёжность — требуй подтверждения от нескольких копий, но тогда при поломке части серверов запись может встать колом (некому подтверждать). Хочешь, чтобы запись шла всегда, — ослабляешь требования, но растёт шанс что-то потерять. Идеального варианта «для всех» нет. Для денег ты выберешь надёжность и переживёшь, что иногда нельзя записать. Для какой-нибудь статистики — наоборот, пусть пишется всегда, а пара потерянных точек погоды не сделает.
А теперь — зачем тебе это, даже если ты Kafka в глаза не видел. Принцип простой и универсальный: ответ «готово» стоит ровно столько, сколько мест реально успели сохранить твои данные. Так что каждый раз, когда твой код получает «ок» откуда-то извне, спроси себя — «ок» от кого и что за ним стоит.
Пара примеров из обычной жизни. Пишешь в базу, у которой есть копии для чтения. Запись прошла, но копии могли ещё не успеть её получить. Читаешь сразу после записи из копии — а там пусто. Та же щель, вид сбоку. Или дёргаешь чужой сервис по сети и получаешь 200. Это значит «я принял твой запрос», а вовсе не «я довёл дело до конца» — если тебе важен именно результат, надо его проверить, а не верить на слово. И везде, где надёжность важнее скорости, ты за неё платишь — тем, что иногда придётся подождать или получить отказ. Это нормально. Ненормально — надеяться, что «да обычно долетает».
Если совсем коротко: надёжность — это не галочка «включил копии и забыл», а осознанное решение, сколько подтверждений тебе достаточно и чем ты за это готов заплатить. Почти все истории про «данные загадочно пропали» — и в Kafka, и в обычном коде — на самом деле про неправильно понятое слово «готово».
Подписаться: @codeof_art
Вступить в чатик: @code_of_art
Ты сохранил данные. Сервис ответил «готово». Ты выдохнул и пошёл дальше. Знакомо? А теперь неприятная новость: «сервис ответил готово» и «данные действительно на месте» — это два разных события. Между ними есть щель, и данные умеют в неё проваливаться. Причём случается это ровно в тот момент, когда что-то ломается, — то есть в самый неподходящий. Чтобы увидеть эту щель во всей красе, посмотрим, как с ней воюет Kafka. А потом вернёмся к твоему коду, потому что проблема там ровно та же.
Как Kafka бережёт данные. Она хранит каждую порцию сообщений сразу на нескольких серверах: один главный, он принимает записи, остальные — его копии, они за ним повторяют. Звучит надёжно. Но вот ловушка, в которую попадают почти все. Главный сервер принял сообщение, записал у себя, ответил «принято» — и в следующую секунду умер. А копии не успели повторить за ним. На его место встаёт одна из копий, но у неё этого сообщения нет. Всё, сообщение исчезло. А отправитель-то уверен, что всё хорошо, — ему же ответили «принято».
Как эту дыру закрывают. У отправителя есть настройка, которая решает, когда считать сообщение сохранённым. Можно сказать «мне хватит, что его принял главный» — быстро, но это ровно та история с исчезновением. А можно потребовать «считать сохранённым, только когда его повторили и живые копии тоже». Вот тогда появляется настоящая гарантия: даже если главный умрёт, сообщение уже есть на других.
Но и это не всё. Что, если копии отстали и по одной повыпадали, а живым остался только главный? Тогда правило «пусть подтвердят копии» тихо превращается в «пусть подтвердит главный» — и мы снова там же, откуда начали. Поэтому есть ещё одна настройка-предохранитель: «если живых копий осталось меньше, чем нужно, — вообще перестань принимать записи и честно скажи об этом». Лучше отказать сразу, чем сделать вид, что всё сохранилось, и потерять данные молча.
И вот тут главная мысль, ради которой всё затевалось. Это выбор, а не значение по умолчанию. Хочешь надёжность — требуй подтверждения от нескольких копий, но тогда при поломке части серверов запись может встать колом (некому подтверждать). Хочешь, чтобы запись шла всегда, — ослабляешь требования, но растёт шанс что-то потерять. Идеального варианта «для всех» нет. Для денег ты выберешь надёжность и переживёшь, что иногда нельзя записать. Для какой-нибудь статистики — наоборот, пусть пишется всегда, а пара потерянных точек погоды не сделает.
А теперь — зачем тебе это, даже если ты Kafka в глаза не видел. Принцип простой и универсальный: ответ «готово» стоит ровно столько, сколько мест реально успели сохранить твои данные. Так что каждый раз, когда твой код получает «ок» откуда-то извне, спроси себя — «ок» от кого и что за ним стоит.
Пара примеров из обычной жизни. Пишешь в базу, у которой есть копии для чтения. Запись прошла, но копии могли ещё не успеть её получить. Читаешь сразу после записи из копии — а там пусто. Та же щель, вид сбоку. Или дёргаешь чужой сервис по сети и получаешь 200. Это значит «я принял твой запрос», а вовсе не «я довёл дело до конца» — если тебе важен именно результат, надо его проверить, а не верить на слово. И везде, где надёжность важнее скорости, ты за неё платишь — тем, что иногда придётся подождать или получить отказ. Это нормально. Ненормально — надеяться, что «да обычно долетает».
Если совсем коротко: надёжность — это не галочка «включил копии и забыл», а осознанное решение, сколько подтверждений тебе достаточно и чем ты за это готов заплатить. Почти все истории про «данные загадочно пропали» — и в Kafka, и в обычном коде — на самом деле про неправильно понятое слово «готово».
Подписаться: @codeof_art
Вступить в чатик: @code_of_art
🔥5👍1🎉1
Как стать миддлом
По стеку джуна и мидла сегодня спрашивают почти одно и то же. Открой любые вакансии - знание своего ЯП/фреймворка, SQL, Docker, Kafka/Redis, везде одно и то же. Так за что мидлу платят вдвое больше? Разбираемся на актуальных вакансиях Т-Банка и Ozon.
Джуну дают задачу. Мидлу — проблему
Джуну пишут конкретно, например, написать API под новый микросервис для техподдержки. Задача с границами: понятно, что на входе, что на выходе, когда готово. Бери и делай.
Мидлу пишут абстрактные вещи, для примера, рефакторить интеграционные решения и обеспечивать стабильность работы сервисов. Границ нет, не особо понятно, а какой конечный результат вообще и с чего начать-то. Тебе дают проблему, а задачу из неё ты достаёшь сам. И отвечаешь за результат, если твои микросервисы упадут в разгар рабочего дня и заказчик потеряет деньги, тут уже другой уровень отвественности по сравнению с джуном.
Вот и вся граница: джуна берут за умение закрывать задачи, мидла — за умение отвечать за систему. Всё остальное — следствие.
Стек тот же — уровень владения разный
В вакансиях джуна и мидла — одни и те же технологии. Разница в том, что от тебя с ними ждут.
Джуну: «знать Python», «понимать архитектуру ETL». Знать и понимать.
Мидлу: «проектировать микросервисы», «оптимизировать запросы», «самому работать с Docker». Не слышал про Kubernetes, а крутил руками.
Что конкретно учить, чтобы стать мидлом
«Бери больше ответственности и качай харды» - совет ни о чём. Ниже дам несколько конкертных советов, они не зависят от языка - работают хоть на Go, хоть на Python, хоть на Java.
System design. Главный навык мидла. Спроектировать сервис с нуля: где узкое место, что реплицировать, где кэш, что будет под нагрузкой в 10 раз больше. Это спрашивают почти на каждом собесе на мидла — и именно тут валятся вчерашние джуны.
Базы на уровне оптимизации. Не «умею писать SELECT», а читать план запроса, ставить индексы, понимать, почему запрос тупит на проде под реальными данными.
Docker и Kubernetes. Не теория — собрать образ, написать манифест, задеплоить, разобраться, почему под падает и рестартится в цикле.
Событийная архитектура. Kafka, очереди, как сервисы общаются асинхронно и что происходит с системой, когда один из них отваливается.
CI/CD. Как код доезжает до прода и как сделать так, чтобы релиз не положил систему.
Освоишь эти пять — и на собесе тебе будет что показать. Не строчку в резюме, а умение собрать работающую систему.
Коротко
Джун сидит в своей зоне и пишет задачи внутри неё. Мидл смотрит на проект целиком: как деплоится, как сервисы общаются, что упадёт под нагрузкой, почему вчерашний релиз положил прод. Архитектура для него — не то, что понимаешь, а то, что строишь.
За это и платят: по медиане backend-вакансий 2026 года джун получает около 135 тысяч, мидл — порядка 225. Почти вдвое.
Хочешь дорасти до мидла — не гонись за очередным фреймворком. Учись проектировать системы и отвечать за них. Ровно этому мы учим на нашем курсе бэкенд про.
➡️ Записаться.
Подписаться: @codeof_art
Вступить в чатик: @code_of_art
По стеку джуна и мидла сегодня спрашивают почти одно и то же. Открой любые вакансии - знание своего ЯП/фреймворка, SQL, Docker, Kafka/Redis, везде одно и то же. Так за что мидлу платят вдвое больше? Разбираемся на актуальных вакансиях Т-Банка и Ozon.
Джуну дают задачу. Мидлу — проблему
Джуну пишут конкретно, например, написать API под новый микросервис для техподдержки. Задача с границами: понятно, что на входе, что на выходе, когда готово. Бери и делай.
Мидлу пишут абстрактные вещи, для примера, рефакторить интеграционные решения и обеспечивать стабильность работы сервисов. Границ нет, не особо понятно, а какой конечный результат вообще и с чего начать-то. Тебе дают проблему, а задачу из неё ты достаёшь сам. И отвечаешь за результат, если твои микросервисы упадут в разгар рабочего дня и заказчик потеряет деньги, тут уже другой уровень отвественности по сравнению с джуном.
Вот и вся граница: джуна берут за умение закрывать задачи, мидла — за умение отвечать за систему. Всё остальное — следствие.
Стек тот же — уровень владения разный
В вакансиях джуна и мидла — одни и те же технологии. Разница в том, что от тебя с ними ждут.
Джуну: «знать Python», «понимать архитектуру ETL». Знать и понимать.
Мидлу: «проектировать микросервисы», «оптимизировать запросы», «самому работать с Docker». Не слышал про Kubernetes, а крутил руками.
Что конкретно учить, чтобы стать мидлом
«Бери больше ответственности и качай харды» - совет ни о чём. Ниже дам несколько конкертных советов, они не зависят от языка - работают хоть на Go, хоть на Python, хоть на Java.
System design. Главный навык мидла. Спроектировать сервис с нуля: где узкое место, что реплицировать, где кэш, что будет под нагрузкой в 10 раз больше. Это спрашивают почти на каждом собесе на мидла — и именно тут валятся вчерашние джуны.
Базы на уровне оптимизации. Не «умею писать SELECT», а читать план запроса, ставить индексы, понимать, почему запрос тупит на проде под реальными данными.
Docker и Kubernetes. Не теория — собрать образ, написать манифест, задеплоить, разобраться, почему под падает и рестартится в цикле.
Событийная архитектура. Kafka, очереди, как сервисы общаются асинхронно и что происходит с системой, когда один из них отваливается.
CI/CD. Как код доезжает до прода и как сделать так, чтобы релиз не положил систему.
Освоишь эти пять — и на собесе тебе будет что показать. Не строчку в резюме, а умение собрать работающую систему.
Коротко
Джун сидит в своей зоне и пишет задачи внутри неё. Мидл смотрит на проект целиком: как деплоится, как сервисы общаются, что упадёт под нагрузкой, почему вчерашний релиз положил прод. Архитектура для него — не то, что понимаешь, а то, что строишь.
За это и платят: по медиане backend-вакансий 2026 года джун получает около 135 тысяч, мидл — порядка 225. Почти вдвое.
Хочешь дорасти до мидла — не гонись за очередным фреймворком. Учись проектировать системы и отвечать за них. Ровно этому мы учим на нашем курсе бэкенд про.
Подписаться: @codeof_art
Вступить в чатик: @code_of_art
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3👍2
Стажировка в Яндексе одна из лучших возможностей для старта в разработке:
• МНОГО КРАСИВЫХ СВОБОДНЫХ ЖЕНЩИН
• специалисты высокого класса
• зарплаты в среднем выше рынка
• современный стек и проекты
• хорошо выстроены процессы
• корпоративная культура
Для участия нужно подать анкету заполнить анкету и зарешать контест. Разбор контеста уже выложен на нашем курсе бэкенд про, алгоритмы про.
➡ Записаться.
Как заполнять анкеты смотрим этот ролик. После контеста вас ждет два алгособеса на 2 литкод задачи medium + вопросы по языке и возможно серверам. И наконец собеседования с командами. На моем опыте максимально, сколько может быть собесов с командой - 9.
Финальные собесы
Если команда точно понимает, что им нужен стажёр закрыть пару дыр и после он не нужен, то собес больше про твой опыт, почему Яндекс, как планируешь совмещать с учебой, а что будешь делать, если стажку не продлим/не возьмём в штат. Такие больше на метч с командой и посмотреть не будешь ли ты ныть, что на стажке будешь заниматься скучной фигней, расскажут какой есть пул задач и спросят, что из этого интересно. Обычно такое в продуктовые команды.
Или, например наш студент, собесился в команду Поиска, которая занимается инфраструктурой. Устроили настоящий собес по систем дизайну, просили спроектировать калькулятор, который вот выдаётся после запроса в поисковой строке, как накрутить серверный рендеринг, гоняли по сетям, по знанию тулов реакта (линтер, сборщик кода как работает, как то-то настроить). И после этого другой интервьюер давил, что вот нам нужны гении, ты явно не такой, а вот чем ты занимаешься, а почему учишься в залупинске, а не в мск, говорил, что на удаленку никого не берём и тд.
Или другой наш студент собесился в другую команду Яндекс 360 календарь, там максимально чилово было, поспрашивал за опыт, так вышло что они выпускники одного факультета, пообсуждали преподов, хобби, и всё.
По итогу еще раз многое зависит от команды и кто собесит. Выбирайте команду с умом, ее можно поменять.
Штат
Можно сразу на финале спросить, а будут ли места в штате. Конечно обмануть могут, но за вопрос денег не берут и пусть сила вам подскажет.
После стажировки есть несколько вариантов:
1. Если плохой отзыв от команды и говорят «уходи», то нужно заново проходить все собесы на стажера
2. Могут сказать, что ты не очень и иди на стажировку снова (без собесов, только финалы)
3. Можешь пойти в штат:
а) ты классный - можешь пойти к нам на миддла (но нужно опять пройти АА, потом финалы), если не пройдешь, то возьмут на джуна
б) ты не дотягиваешь до миддла - ты джун и если команда не готова взять джуна, то нужно идти искать, кто может взять к себе джуна самому
в) можно искать, кто готов взять к себе миддла/джуна и врубать свои навыки социальной инженерии на максимум
При идеальном мэтче, вы в Яндексе - поздравляю!
Подписаться: @codeof_art
• МНОГО КРАСИВЫХ СВОБОДНЫХ ЖЕНЩИН
• специалисты высокого класса
• зарплаты в среднем выше рынка
• современный стек и проекты
• хорошо выстроены процессы
• корпоративная культура
Для участия нужно подать анкету заполнить анкету и зарешать контест. Разбор контеста уже выложен на нашем курсе бэкенд про, алгоритмы про.
Как заполнять анкеты смотрим этот ролик. После контеста вас ждет два алгособеса на 2 литкод задачи medium + вопросы по языке и возможно серверам. И наконец собеседования с командами. На моем опыте максимально, сколько может быть собесов с командой - 9.
Финальные собесы
Если команда точно понимает, что им нужен стажёр закрыть пару дыр и после он не нужен, то собес больше про твой опыт, почему Яндекс, как планируешь совмещать с учебой, а что будешь делать, если стажку не продлим/не возьмём в штат. Такие больше на метч с командой и посмотреть не будешь ли ты ныть, что на стажке будешь заниматься скучной фигней, расскажут какой есть пул задач и спросят, что из этого интересно. Обычно такое в продуктовые команды.
Или, например наш студент, собесился в команду Поиска, которая занимается инфраструктурой. Устроили настоящий собес по систем дизайну, просили спроектировать калькулятор, который вот выдаётся после запроса в поисковой строке, как накрутить серверный рендеринг, гоняли по сетям, по знанию тулов реакта (линтер, сборщик кода как работает, как то-то настроить). И после этого другой интервьюер давил, что вот нам нужны гении, ты явно не такой, а вот чем ты занимаешься, а почему учишься в залупинске, а не в мск, говорил, что на удаленку никого не берём и тд.
Или другой наш студент собесился в другую команду Яндекс 360 календарь, там максимально чилово было, поспрашивал за опыт, так вышло что они выпускники одного факультета, пообсуждали преподов, хобби, и всё.
По итогу еще раз многое зависит от команды и кто собесит. Выбирайте команду с умом, ее можно поменять.
Штат
Можно сразу на финале спросить, а будут ли места в штате. Конечно обмануть могут, но за вопрос денег не берут и пусть сила вам подскажет.
После стажировки есть несколько вариантов:
1. Если плохой отзыв от команды и говорят «уходи», то нужно заново проходить все собесы на стажера
2. Могут сказать, что ты не очень и иди на стажировку снова (без собесов, только финалы)
3. Можешь пойти в штат:
а) ты классный - можешь пойти к нам на миддла (но нужно опять пройти АА, потом финалы), если не пройдешь, то возьмут на джуна
б) ты не дотягиваешь до миддла - ты джун и если команда не готова взять джуна, то нужно идти искать, кто может взять к себе джуна самому
в) можно искать, кто готов взять к себе миддла/джуна и врубать свои навыки социальной инженерии на максимум
При идеальном мэтче, вы в Яндексе - поздравляю!
Подписаться: @codeof_art
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2🤯2
Второй пост серии про паттерны на реальном коде. В прошлый раз говорили, почему «сохранилось» и «точно сохранилось» — не одно и то же. Сегодня — про идею, на которой держится половина софта вокруг нас, хотя мало кто задумывается про нее.
Если тебе приходится запускать чужой код, которому ты не доверяешь, — держи его от себя подальше, в отдельном процессе. Причина простая: чужой код умеет падать, зависать намертво и течь по памяти. Пусти его внутрь своего приложения — и однажды он утащит тебя за собой на дно. А отдельный процесс работает как стена: за ней хоть потоп, а на твою сторону вода не дойдёт. Поэтому одна упавшая вкладка в браузере не роняет остальные, и поэтому же плагины в редакторах живут отдельно от самого редактора.
Посмотрим, как это сделано в VS Code — там всё честно и наглядно. Расширения крутятся не внутри редактора, а в собственном процессе, у него и название есть — extension host. Замысел в одну строчку: что бы ни стряслось с расширениями, редактор обязан устоять.
И он выдерживает. Процесс с расширениями рухнул целиком — а редактор даже бровью не повёл: курсор мигает, текст на месте, файл спокойно сохраняется. Разработчики так и ставили задачу — пусть расширения хоть все разом отвалятся, но ни строчки твоей работы пропасть при этом не должно. Когда процесс падает, сверху выезжает плашка «расширения отключились, перезапустить?», жмёшь — и он поднимается заново. На то он и отдельный, что пересоздать его можно, ничего вокруг не задев.
А теперь то, из-за чего у людей годами пригорает. Стена стоит между редактором и расширениями — но между самими расширениями никакой стены нет. Все они набиты в один общий процесс и делят на всех единственный поток выполнения. А в JavaScript поток ровно один. И получается некрасивое: стоит одному расширению уйти в тяжёлые вычисления и занять поток надолго — как замирают вообще все расширения сразу. Не только виновник, а все соседи по процессу. Человек видит, что редактор целиком отупел и не реагирует, ругает VS Code последними словами — а нашкодило одно расширение, просто остальные заперты с ним в одной комнате.
Показательно, что и сама команда эту штуку архитектурно не победила — пошла в обход. VS Code теперь приглядывает за процессом с расширениями, и если тот перестал отвечать, тихонько включает профайлер: выясняет, кто съел весь поток, находит виновника и предлагает написать его автору. Проблему не убрали — её хотя бы вытащили на свет.
Тут есть тонкость, которую легко проскочить. Отдельный процесс спасает ровно от одного: сломанное расширение не утянет за собой редактор. Но заставить расширения не мешать друг другу он не может — это не входит в его задачу. Чтобы одно зависшее расширение не морозило соседей, пришлось бы городить следующий этаж защиты: свой процесс под каждое, тяжёлые задачи в фоновые потоки, лимиты по времени. И всё это не бесплатно — лишняя память, возня с общением между частями, более медленный запуск. В VS Code прикинули цену и решили, что оно того не стоит: одна общая крыша над всеми расширениями — осознанный размен между надёжностью и расходами.
Чему тут стоит научиться, даже если ты никогда не будешь писать редактор кода. Когда проектируешь что-то, что запускает не свой код — плагины, пользовательские скрипты, обработчики от сторонних команд, — заранее спроси себя: от чего именно я тут защищаюсь. «Чтобы чужое не уронило моё» и «чтобы одно чужое не мешало другому чужому» — две разные задачи, и вторая решается дороже. Их легко перепутать и поставить границу не там: думаешь, что защитился, а закрыл только половину. И второе: если задачу нельзя решить чисто — не грех сделать её хотя бы заметной. VS Code не смог развести расширения по-настоящему, но научился показывать пальцем на виновника, и это уже куда лучше, чем молча тормозить. Иногда честная диагностика ценнее красивого, но недостижимого решения.
Подписаться: @codeof_art
Вступить в чатик: @code_of_art
Если тебе приходится запускать чужой код, которому ты не доверяешь, — держи его от себя подальше, в отдельном процессе. Причина простая: чужой код умеет падать, зависать намертво и течь по памяти. Пусти его внутрь своего приложения — и однажды он утащит тебя за собой на дно. А отдельный процесс работает как стена: за ней хоть потоп, а на твою сторону вода не дойдёт. Поэтому одна упавшая вкладка в браузере не роняет остальные, и поэтому же плагины в редакторах живут отдельно от самого редактора.
Посмотрим, как это сделано в VS Code — там всё честно и наглядно. Расширения крутятся не внутри редактора, а в собственном процессе, у него и название есть — extension host. Замысел в одну строчку: что бы ни стряслось с расширениями, редактор обязан устоять.
И он выдерживает. Процесс с расширениями рухнул целиком — а редактор даже бровью не повёл: курсор мигает, текст на месте, файл спокойно сохраняется. Разработчики так и ставили задачу — пусть расширения хоть все разом отвалятся, но ни строчки твоей работы пропасть при этом не должно. Когда процесс падает, сверху выезжает плашка «расширения отключились, перезапустить?», жмёшь — и он поднимается заново. На то он и отдельный, что пересоздать его можно, ничего вокруг не задев.
А теперь то, из-за чего у людей годами пригорает. Стена стоит между редактором и расширениями — но между самими расширениями никакой стены нет. Все они набиты в один общий процесс и делят на всех единственный поток выполнения. А в JavaScript поток ровно один. И получается некрасивое: стоит одному расширению уйти в тяжёлые вычисления и занять поток надолго — как замирают вообще все расширения сразу. Не только виновник, а все соседи по процессу. Человек видит, что редактор целиком отупел и не реагирует, ругает VS Code последними словами — а нашкодило одно расширение, просто остальные заперты с ним в одной комнате.
Показательно, что и сама команда эту штуку архитектурно не победила — пошла в обход. VS Code теперь приглядывает за процессом с расширениями, и если тот перестал отвечать, тихонько включает профайлер: выясняет, кто съел весь поток, находит виновника и предлагает написать его автору. Проблему не убрали — её хотя бы вытащили на свет.
Тут есть тонкость, которую легко проскочить. Отдельный процесс спасает ровно от одного: сломанное расширение не утянет за собой редактор. Но заставить расширения не мешать друг другу он не может — это не входит в его задачу. Чтобы одно зависшее расширение не морозило соседей, пришлось бы городить следующий этаж защиты: свой процесс под каждое, тяжёлые задачи в фоновые потоки, лимиты по времени. И всё это не бесплатно — лишняя память, возня с общением между частями, более медленный запуск. В VS Code прикинули цену и решили, что оно того не стоит: одна общая крыша над всеми расширениями — осознанный размен между надёжностью и расходами.
Чему тут стоит научиться, даже если ты никогда не будешь писать редактор кода. Когда проектируешь что-то, что запускает не свой код — плагины, пользовательские скрипты, обработчики от сторонних команд, — заранее спроси себя: от чего именно я тут защищаюсь. «Чтобы чужое не уронило моё» и «чтобы одно чужое не мешало другому чужому» — две разные задачи, и вторая решается дороже. Их легко перепутать и поставить границу не там: думаешь, что защитился, а закрыл только половину. И второе: если задачу нельзя решить чисто — не грех сделать её хотя бы заметной. VS Code не смог развести расширения по-настоящему, но научился показывать пальцем на виновника, и это уже куда лучше, чем молча тормозить. Иногда честная диагностика ценнее красивого, но недостижимого решения.
Подписаться: @codeof_art
Вступить в чатик: @code_of_art
🔥4❤1
System Design: frontend
Сегодня разберём задачу с собеса в геодезическую компанию — из тех, где приложение для полевых работ должно работать там, где связи нет в принципе. Спроектируй фронт, который живёт без интернета: специалист видит данные, что-то в них меняет, а когда сеть возвращается — всё уезжает на сервер и синхронизируется.
Почему такое вообще спрашивают. Геодезист выезжает на объект — поле, стройка, лес за городом, — и связи там может не быть весь день. А работать надо: открыть карту участка, занести замеры, отметить точки, что-то поправить. Если приложение при потере сети показывает белый экран, им попросту нельзя пользоваться в поле. Значит, оно должно работать так, будто интернет и не нужен, а сеть подхватывать само, когда специалист вернётся в зону покрытия.
Первое, что хочется ляпнуть, — «закешируем данные и всё». И вот это ловушка. Как только ты разрешаешь не только читать офлайн, но и менять данные, ты, по сути, строишь маленькую распределённую систему: у тебя появляется две копии правды (на устройстве и на сервере), и они умеют разъезжаться. Все классические боли распределёнки — конфликты, рассинхрон, порядок операций — теперь твои. Не подумал про них — решение развалится на первом же реальном сценарии.
Поэтому до того как проектировать, спроси интервьюера две вещи. Первая: что именно должно пахать офлайн — только чтение или запись тоже? Это небо и земля по сложности. Чисто чтение — задачка на кэш. Запись — уже та самая распределёнка. Вторая, и это гвоздь всей задачи: что делать, если геодезист поменял данные офлайн, а на сервере их за это время тоже кто-то поменял — например, коллега в офисе? Пока ты не ответил, как разруливать такой конфликт, — задача не закрыта.
Теперь как устроено внутри. Данные храним прямо на устройстве. Для структурированных данных — IndexedDB (это встроенная в браузер база; localStorage не годится — он крохотный и синхронный, тормозит всё вокруг). Картинки, стили, саму оболочку приложения кладём через Service Worker — это прослойка между приложением и сетью, которая отдаёт сохранённое, когда интернета нет. Читаем офлайн — берём из локальной базы. А с записью интереснее: когда человек что-то меняет без сети, мы не пытаемся тут же достучаться до сервера, а складываем изменение в локальную очередь. Появилась сеть — по очереди, в том же порядке, отправляем всё накопленное.
И вот мы уперлись в главное — в конфликты. Тут надо не просто сказать «ну разрулим», а назвать конкретный подход и объяснить, почему он. Самый простой — кто последний записал, того и правда. Работает, но молча затирает чужие изменения, а для замеров по объекту это чревато: перезатёр чью-то правку — и на объект поедут неверные координаты. Честнее — версии: у каждой записи есть номер версии, и если геодезист пытается сохранить поверх данных, которые на сервере уже обновились, сервер такое отклоняет, и мы решаем, что делать. Самый аккуратный, но и самый муторный вариант — сливать изменения по отдельным полям: один поправил координаты точки, другой — её описание, оба изменения выживают. Важно не назвать «правильный» ответ (его нет), а показать, что ты понимаешь разницу и осознанно выбираешь под ситуацию.
Ещё пара вещей, без которых разбор неполный. Синхронизацию лучше делать в фоне — есть Background Sync, который сам достучится до сервера, когда связь вернётся, даже если вкладку уже закрыли. И обязательно — честно показывать статус. Если человек поменял что-то офлайн, а на экране всё выглядит как «сохранено», он уйдёт довольный, а изменения висят в очереди и могут вообще не уехать. Маленькая плашка «изменения ещё не отправлены» снимает кучу боли.
Если совсем коротко: тут проверяют, понял ли ты, что offline-first — это не «кэш прикрутить», а полноценная распределёнка со своими конфликтами и с тем, что данные какое-то время живут несогласованными. Назвал конкретную стратегию разрешения конфликтов и вспомнил про честный статус для пользователя — значит, в теме.
Подписаться: @codeof_art
Вступить в чатик: @code_of_art
Сегодня разберём задачу с собеса в геодезическую компанию — из тех, где приложение для полевых работ должно работать там, где связи нет в принципе. Спроектируй фронт, который живёт без интернета: специалист видит данные, что-то в них меняет, а когда сеть возвращается — всё уезжает на сервер и синхронизируется.
Почему такое вообще спрашивают. Геодезист выезжает на объект — поле, стройка, лес за городом, — и связи там может не быть весь день. А работать надо: открыть карту участка, занести замеры, отметить точки, что-то поправить. Если приложение при потере сети показывает белый экран, им попросту нельзя пользоваться в поле. Значит, оно должно работать так, будто интернет и не нужен, а сеть подхватывать само, когда специалист вернётся в зону покрытия.
Первое, что хочется ляпнуть, — «закешируем данные и всё». И вот это ловушка. Как только ты разрешаешь не только читать офлайн, но и менять данные, ты, по сути, строишь маленькую распределённую систему: у тебя появляется две копии правды (на устройстве и на сервере), и они умеют разъезжаться. Все классические боли распределёнки — конфликты, рассинхрон, порядок операций — теперь твои. Не подумал про них — решение развалится на первом же реальном сценарии.
Поэтому до того как проектировать, спроси интервьюера две вещи. Первая: что именно должно пахать офлайн — только чтение или запись тоже? Это небо и земля по сложности. Чисто чтение — задачка на кэш. Запись — уже та самая распределёнка. Вторая, и это гвоздь всей задачи: что делать, если геодезист поменял данные офлайн, а на сервере их за это время тоже кто-то поменял — например, коллега в офисе? Пока ты не ответил, как разруливать такой конфликт, — задача не закрыта.
Теперь как устроено внутри. Данные храним прямо на устройстве. Для структурированных данных — IndexedDB (это встроенная в браузер база; localStorage не годится — он крохотный и синхронный, тормозит всё вокруг). Картинки, стили, саму оболочку приложения кладём через Service Worker — это прослойка между приложением и сетью, которая отдаёт сохранённое, когда интернета нет. Читаем офлайн — берём из локальной базы. А с записью интереснее: когда человек что-то меняет без сети, мы не пытаемся тут же достучаться до сервера, а складываем изменение в локальную очередь. Появилась сеть — по очереди, в том же порядке, отправляем всё накопленное.
И вот мы уперлись в главное — в конфликты. Тут надо не просто сказать «ну разрулим», а назвать конкретный подход и объяснить, почему он. Самый простой — кто последний записал, того и правда. Работает, но молча затирает чужие изменения, а для замеров по объекту это чревато: перезатёр чью-то правку — и на объект поедут неверные координаты. Честнее — версии: у каждой записи есть номер версии, и если геодезист пытается сохранить поверх данных, которые на сервере уже обновились, сервер такое отклоняет, и мы решаем, что делать. Самый аккуратный, но и самый муторный вариант — сливать изменения по отдельным полям: один поправил координаты точки, другой — её описание, оба изменения выживают. Важно не назвать «правильный» ответ (его нет), а показать, что ты понимаешь разницу и осознанно выбираешь под ситуацию.
Ещё пара вещей, без которых разбор неполный. Синхронизацию лучше делать в фоне — есть Background Sync, который сам достучится до сервера, когда связь вернётся, даже если вкладку уже закрыли. И обязательно — честно показывать статус. Если человек поменял что-то офлайн, а на экране всё выглядит как «сохранено», он уйдёт довольный, а изменения висят в очереди и могут вообще не уехать. Маленькая плашка «изменения ещё не отправлены» снимает кучу боли.
Если совсем коротко: тут проверяют, понял ли ты, что offline-first — это не «кэш прикрутить», а полноценная распределёнка со своими конфликтами и с тем, что данные какое-то время живут несогласованными. Назвал конкретную стратегию разрешения конфликтов и вспомнил про честный статус для пользователя — значит, в теме.
Подписаться: @codeof_art
Вступить в чатик: @code_of_art
🔥3
Сходил на собеседование в Шушу. Предложили интересную задачу: спроектировать агрегатор проституток. Смотрим! Смотрим! По ссылке:
https://www.youtube.com/shorts/PyVM4NU5ero
https://www.youtube.com/shorts/PyVM4NU5ero
YouTube
Агригатор простиуток | System Design
System Design: агрегатор бронирования с внешним расписанием. Разбир...
🔥1
В Яндекс без опыта с первого раза
Товарищи, продолжаем рассказывать про наших талантливых учеников.
На днях записали интервью с Полиной, нашей ученицей летнего потока Бэкенд СТАРТ.
➡ Записаться.
У неё не было опыта работы, топового вуза и олимпиад. И всего за 2 месяца получилось взять оффер в Яндекс.
Самое интересное, что она не откликалась на стажировку 👀
Смотрите в ролике как все получилось: https://www.youtube.com/watch?v=k6yYBESFHIs
В видео обсудили:
➡️ как попасть на мероприятия Яндекса, где можно пройти собеседование
➡️ как готовилась к алгосекциям и что на них спрашивали
➡️ о чём говорили на финалах
➡️ правда ли в Яндексе 500 этапов и сколько собесов было у неё
➡️ с какими компаниями были еще собесы
➡️ советы тем, кто сейчас ищет первую работу
Товарищи, продолжаем рассказывать про наших талантливых учеников.
На днях записали интервью с Полиной, нашей ученицей летнего потока Бэкенд СТАРТ.
У неё не было опыта работы, топового вуза и олимпиад. И всего за 2 месяца получилось взять оффер в Яндекс.
Самое интересное, что она не откликалась на стажировку 👀
Смотрите в ролике как все получилось: https://www.youtube.com/watch?v=k6yYBESFHIs
В видео обсудили:
Please open Telegram to view this post
VIEW IN TELEGRAM
🗿1
System Design: backend
Сегодня разберём задачу, которую мне давали на собесе в Яндекс. Штука на стыке проектирования и алгоритмов: мало накидать красивую схему на доске — надо ещё нормально объяснить, как данные поедут через систему. И вот тут сразу видно, шаришь ты или просто заучил модные слова.
Условие такое. Надо забэкапить данные — до терабайта. При сжатии они ужмутся где-то в полтора-три раза. Хранилище, куда мы всё складываем, принимает файлы не больше 100 мегабайт за раз. Нужно собрать конвейер: прочитать данные, сжать, записать. И главный подвох, вокруг которого вся задача: целиком в память это не влезет.
Первое, что приходит в голову, — «читаем файл, жмём, отправляем». И это ловушка. Терабайт в оперативку просто не поместится, так что про «прочитать файл целиком» надо забыть сразу. Задача с самого начала не про файл, а про поток: данные текут через тебя, ты хватаешь их по кусочку, обрабатываешь и отпускаешь — и никогда не держишь всё разом.
Но прежде чем что-то проектировать, я бы задал интервьюеру один вопрос. Как по мне, ради него задачу и придумали. Что делать, если данные сожмутся хуже обещанного, и очередной сжатый кусок всё равно вылезет за 100 мегабайт? Полтора-три раза — это как средняя температура по больнице, а не гарантия. Попадётся кусок, который жмётся плохо (уже сжатое видео, случайный мусор), — и он не влезет в лимит. Если ты сам спотыкаешься об этот момент, до того как тебя носом ткнули, — считай, полдела сделал: дальше этот вопрос всё равно вылезет. Заодно спроси, нужна ли параллельность и надо ли уметь продолжить с места обрыва, если всё грохнется на середине.
Теперь как оно работает внутри. Читаем данные небольшими порциями, каждую жмём и отправляем в хранилище куском не больше лимита. Получается конвейер из трёх шагов: читаем, жмём, отправляем. И логично, чтобы шаги крутились не по очереди, а разом — пока один кусок улетает в хранилище, следующий уже читается, а средний в это время жмётся. Само сжатие — самое прожорливое место, так что его можно раскидать на несколько потоков и жать куски параллельно.
И вот тут вылезает тонкость, которую многие упускают. Читать почти всегда быстрее, чем отправлять по сети. Если читать на полной скорости, а отправка не поспевает, то непрожатые куски начнут копиться в памяти — и привет, мы вернулись ровно к той беде, от которой бежали: память забита под завязку. Поэтому между шагами ставим очередь ограниченного размера. Забилась — чтение притормаживает и ждёт, пока отправка разгребёт накопленное. По сути система сама себя придушивает под нагрузкой и не даёт быстрой части захлебнуть медленную.
Вернёмся к главному вопросу — про плохое сжатие. Ответ «ну возьмём кусок поменьше» не катит: это отмашка, а не решение. По-нормальному — не фиксить размер куска намертво, а подстраивать. Не влез после сжатия — уменьшаем входную порцию и пробуем ещё раз. Или наоборот: сразу берём порцию с запасом, с расчётом на самый паршивый случай, чтобы результат влез при любом раскладе. Оба варианта живые, суть в том, что ты вообще про это подумал, а не понадеялся, что «да обычно нормально жмётся».
И ещё пара штук, которые отличают продуманное решение от учебного. Первая — контрольная сумма на каждый кусок. Иначе бэкап может тихо побиться, а узнаешь ты об этом в самый неподходящий момент — когда полез восстанавливаться, а там каша. Вторая — уметь продолжить с последнего нормально записанного куска, а не гнать терабайт по новой из-за обрыва на 90%. Для этого достаточно отмечать, что уже доехало.
Если коротко: тут смотрят, думаешь ли ты про неудобные случаи заранее, и дошло ли до тебя, что «не влезает в память» — это про потоковую обработку, а не про поиск хитрого способа всё равно запихнуть всё целиком. Разложил историю с плохим сжатием на конкретное решение — задача твоя.
Подписаться: @codeof_art
Вступить в чатик: @code_of_art
Сегодня разберём задачу, которую мне давали на собесе в Яндекс. Штука на стыке проектирования и алгоритмов: мало накидать красивую схему на доске — надо ещё нормально объяснить, как данные поедут через систему. И вот тут сразу видно, шаришь ты или просто заучил модные слова.
Условие такое. Надо забэкапить данные — до терабайта. При сжатии они ужмутся где-то в полтора-три раза. Хранилище, куда мы всё складываем, принимает файлы не больше 100 мегабайт за раз. Нужно собрать конвейер: прочитать данные, сжать, записать. И главный подвох, вокруг которого вся задача: целиком в память это не влезет.
Первое, что приходит в голову, — «читаем файл, жмём, отправляем». И это ловушка. Терабайт в оперативку просто не поместится, так что про «прочитать файл целиком» надо забыть сразу. Задача с самого начала не про файл, а про поток: данные текут через тебя, ты хватаешь их по кусочку, обрабатываешь и отпускаешь — и никогда не держишь всё разом.
Но прежде чем что-то проектировать, я бы задал интервьюеру один вопрос. Как по мне, ради него задачу и придумали. Что делать, если данные сожмутся хуже обещанного, и очередной сжатый кусок всё равно вылезет за 100 мегабайт? Полтора-три раза — это как средняя температура по больнице, а не гарантия. Попадётся кусок, который жмётся плохо (уже сжатое видео, случайный мусор), — и он не влезет в лимит. Если ты сам спотыкаешься об этот момент, до того как тебя носом ткнули, — считай, полдела сделал: дальше этот вопрос всё равно вылезет. Заодно спроси, нужна ли параллельность и надо ли уметь продолжить с места обрыва, если всё грохнется на середине.
Теперь как оно работает внутри. Читаем данные небольшими порциями, каждую жмём и отправляем в хранилище куском не больше лимита. Получается конвейер из трёх шагов: читаем, жмём, отправляем. И логично, чтобы шаги крутились не по очереди, а разом — пока один кусок улетает в хранилище, следующий уже читается, а средний в это время жмётся. Само сжатие — самое прожорливое место, так что его можно раскидать на несколько потоков и жать куски параллельно.
И вот тут вылезает тонкость, которую многие упускают. Читать почти всегда быстрее, чем отправлять по сети. Если читать на полной скорости, а отправка не поспевает, то непрожатые куски начнут копиться в памяти — и привет, мы вернулись ровно к той беде, от которой бежали: память забита под завязку. Поэтому между шагами ставим очередь ограниченного размера. Забилась — чтение притормаживает и ждёт, пока отправка разгребёт накопленное. По сути система сама себя придушивает под нагрузкой и не даёт быстрой части захлебнуть медленную.
Вернёмся к главному вопросу — про плохое сжатие. Ответ «ну возьмём кусок поменьше» не катит: это отмашка, а не решение. По-нормальному — не фиксить размер куска намертво, а подстраивать. Не влез после сжатия — уменьшаем входную порцию и пробуем ещё раз. Или наоборот: сразу берём порцию с запасом, с расчётом на самый паршивый случай, чтобы результат влез при любом раскладе. Оба варианта живые, суть в том, что ты вообще про это подумал, а не понадеялся, что «да обычно нормально жмётся».
И ещё пара штук, которые отличают продуманное решение от учебного. Первая — контрольная сумма на каждый кусок. Иначе бэкап может тихо побиться, а узнаешь ты об этом в самый неподходящий момент — когда полез восстанавливаться, а там каша. Вторая — уметь продолжить с последнего нормально записанного куска, а не гнать терабайт по новой из-за обрыва на 90%. Для этого достаточно отмечать, что уже доехало.
Если коротко: тут смотрят, думаешь ли ты про неудобные случаи заранее, и дошло ли до тебя, что «не влезает в память» — это про потоковую обработку, а не про поиск хитрого способа всё равно запихнуть всё целиком. Разложил историю с плохим сжатием на конкретное решение — задача твоя.
Подписаться: @codeof_art
Вступить в чатик: @code_of_art
👍1
Товарищи, Поступашкам нужны контент мейкеры в основной канал по алгоритмам и другим дисциплинам. Если вы творческая личность, интересующейся алгоритмами (или другим), вам нравится писать посты/ придумывать идеи для контента, то обязательно пишите @vice22821. Оплата сдельная, ориентировочно за один пост от 2 тыс до 15 тыс рублей.
Обязательно делитесь с ребятами, которым это может быть интересно.
Обязательно делитесь с ребятами, которым это может быть интересно.
🔥2
This media is not supported in your browser
VIEW IN TELEGRAM
Залетаем с ноги в Яндекс: регистрация проходит до октября, а задания уже лежат тут.
А чтобы ты точно получил оффер, мы уже сделали разбор контеста и технических этапов, они доступны нашим студентам на наших курсах:
Помимо разборов, которые проходят все скрытые тесты на наличие ИИ в решениях, на наших курсах вы получаете:
🔽 Доступ к закрытой базе собесов и тестовых заданий🔽 Разбор стажировки ДС Авито (на МЛ ПРО и ИИ агенты ПРО)🔽 Курс по выходу на доход в валюте🔽 Гарантия оффера🔽 Рефералка в бигтех после защиты пет-проекта🔽 mock-собеседования с обратной связью
Успей написать администратору и не откладывай: задания могут скоро поменять!
Please open Telegram to view this post
VIEW IN TELEGRAM
Полный цикл собесов в Яндекс (Бэкенд 2026)
Сейчас студенты наших курсов под чутким сопровождением проходят отборы в Яндекс, поэтому продолжаю радовать вас инсайдами и актуальными вопросами. Далее представлен слегка отредактированный текст нашего студента. Кстати разбор стажировки Яндекс и Яндекс Intern Week Offer по бэкенду уже выложен на наших курсах Бэкенд ПРО, Алгоритмы ПРО.
➡️ Записаться
Вступительный контест
Началось всё с Яндекс Контеста. На текущем наборе после подачи через yaintern приходит ссылка на пять задач, запустить его можно в любой момент в течение недели. На решение пяти задач дается пять часов, решать можно на любом языке, независимо от того, какой ты указал в анкете.
Я решил четыре задачи из пяти. Пятую посмотрел в разборе на курсе и попросил GPT переписать код, чтобы антиплагиат не нашёл совпадения. Четырёх хватило, хотя я часто слышал от ребят в чате, что проходили и с тремя, так что не стоит ставить на себе крест, если контест не закрыт полностью.
Также тут стоит отметить, что на контесте включён антиплагиат, и тут я советую следующее, как я сам обходил систему при использовании решения от GPT:
- руками вписывать решение, а не копировать из буфера обмена;
- не выделять и копировать условие, лучше сделать скрин и его уже отправить нейронке;
- не отправлять сразу лучшее решение, если у вас все пять задач с первой посылки решены верно, то либо вы гений, либо мухлюете;
- постарайтесь равномерно по времени делать посылки, а не закидывать все сразу, это первый звоночек, что вы решили их нечестно.
Что после контеста
Если приглашение долго не приходит, можно написать на intern@yandex-team.ru, другу это сдвигало процесс. Ещё нюанс: лучше отдельно уточнять у HR город стажировки, ведь информация на сайте и фактический набор могут отличаться.
Дальше технические интервью. Их было два, каждое примерно по часу, в Zoom, с камерой и редактором без автокомплита и нельзя запускать код, так будьте к такому готовы, заранее стоит потренироваться писать все руками и прогонять код в голове.
Алгособес
На первом дали палиндром, с которым я справился быстро. Потом попросили найти максимальную палиндромную подстроку. Я её быстренько решил, так как это довольно известная задача. Следующей задачей была LRU Cache, здесь уже подольше посидеть пришлось. И напоследок удаление n-й ноды с конца связного списка.
Технический
Второй собес начался со скобочной последовательности на стек, тоже быстро, а затем перешли к Go. Нужно было реализовать обход сайта по ссылкам, используя функции загрузки страницы, извлечения домена и парсинга ссылок, а после этого решение попросили распараллелить с ограничением числа воркеров. После алгоритмов пошли вопросы по Go: чем отличаются слайсы от массивов, как устроены map, как работают горутины и каналы, для чего нужен context и что делают defer, panic и recover.
Задачи во многом пересекались с ранжированным списком Поступашек, так что перед отбором стоит заранее прорешать задачи оттуда.
Финальные собесы с командами
После техсекций HR согласовала встречи с двумя командами. Первый собес прошёл в формате вайбчека. Интервьюер и я оказались с одного вуза, и у нас было то же направление, только на восемь лет раньше, поэтому разговор быстро ушёл в университет: что изменилось, те ли преподаватели остались. Затем попросили рассказать о нескольких пет-проектах, их задачах, стеке и результате. Я спросил, есть ли места после стажировки, мне честно ответили, что нет, но это меня не остановило, и я ответил, что всё равно готов пойти к ним в команду.
На втором собесе код тоже не писали, но обсуждали более прикладную задачу. Нужно было словами описать worker pool с graceful shutdown, где воркеры берут задачи из канала, после сигнала перестают принимать новые задачи, а WaitGroup дожидается завершения текущих задач. Отсюда вышли на мьютексы и другие примитивы синхронизации, а затем обсудили масштабирование: сколько запускать воркеров, зачем нужен буфер при всплесках нагрузки и когда стоит переходить на распределённую очередь.
В итоге обе команды были готовы меня принять, и я выбрал вторую из-за открытой позиции в штат команды. Если команда не может взять стажёра, HR подбирает другие варианты.
Я рекомендую при отборе в Яндекс иметь уверенную базу в алгоритмах, попадаются задачи разного уровня, поэтому стоит быть готовым ко всему. Также подтянуть знания по языку и сетям и ОС, всегда могут и по ним спросить. Ну и главное, это не бояться, если чего-то забыли или не знаете, всегда можно побеседовать с интервьюером и попробовать прийти к правильному ответу, это лучше, чем просто молчать или сдаться.
Подписаться: @codeof_art
Сейчас студенты наших курсов под чутким сопровождением проходят отборы в Яндекс, поэтому продолжаю радовать вас инсайдами и актуальными вопросами. Далее представлен слегка отредактированный текст нашего студента. Кстати разбор стажировки Яндекс и Яндекс Intern Week Offer по бэкенду уже выложен на наших курсах Бэкенд ПРО, Алгоритмы ПРО.
Вступительный контест
Началось всё с Яндекс Контеста. На текущем наборе после подачи через yaintern приходит ссылка на пять задач, запустить его можно в любой момент в течение недели. На решение пяти задач дается пять часов, решать можно на любом языке, независимо от того, какой ты указал в анкете.
Я решил четыре задачи из пяти. Пятую посмотрел в разборе на курсе и попросил GPT переписать код, чтобы антиплагиат не нашёл совпадения. Четырёх хватило, хотя я часто слышал от ребят в чате, что проходили и с тремя, так что не стоит ставить на себе крест, если контест не закрыт полностью.
Также тут стоит отметить, что на контесте включён антиплагиат, и тут я советую следующее, как я сам обходил систему при использовании решения от GPT:
- руками вписывать решение, а не копировать из буфера обмена;
- не выделять и копировать условие, лучше сделать скрин и его уже отправить нейронке;
- не отправлять сразу лучшее решение, если у вас все пять задач с первой посылки решены верно, то либо вы гений, либо мухлюете;
- постарайтесь равномерно по времени делать посылки, а не закидывать все сразу, это первый звоночек, что вы решили их нечестно.
Что после контеста
Если приглашение долго не приходит, можно написать на intern@yandex-team.ru, другу это сдвигало процесс. Ещё нюанс: лучше отдельно уточнять у HR город стажировки, ведь информация на сайте и фактический набор могут отличаться.
Дальше технические интервью. Их было два, каждое примерно по часу, в Zoom, с камерой и редактором без автокомплита и нельзя запускать код, так будьте к такому готовы, заранее стоит потренироваться писать все руками и прогонять код в голове.
Алгособес
На первом дали палиндром, с которым я справился быстро. Потом попросили найти максимальную палиндромную подстроку. Я её быстренько решил, так как это довольно известная задача. Следующей задачей была LRU Cache, здесь уже подольше посидеть пришлось. И напоследок удаление n-й ноды с конца связного списка.
Технический
Второй собес начался со скобочной последовательности на стек, тоже быстро, а затем перешли к Go. Нужно было реализовать обход сайта по ссылкам, используя функции загрузки страницы, извлечения домена и парсинга ссылок, а после этого решение попросили распараллелить с ограничением числа воркеров. После алгоритмов пошли вопросы по Go: чем отличаются слайсы от массивов, как устроены map, как работают горутины и каналы, для чего нужен context и что делают defer, panic и recover.
Задачи во многом пересекались с ранжированным списком Поступашек, так что перед отбором стоит заранее прорешать задачи оттуда.
Финальные собесы с командами
После техсекций HR согласовала встречи с двумя командами. Первый собес прошёл в формате вайбчека. Интервьюер и я оказались с одного вуза, и у нас было то же направление, только на восемь лет раньше, поэтому разговор быстро ушёл в университет: что изменилось, те ли преподаватели остались. Затем попросили рассказать о нескольких пет-проектах, их задачах, стеке и результате. Я спросил, есть ли места после стажировки, мне честно ответили, что нет, но это меня не остановило, и я ответил, что всё равно готов пойти к ним в команду.
На втором собесе код тоже не писали, но обсуждали более прикладную задачу. Нужно было словами описать worker pool с graceful shutdown, где воркеры берут задачи из канала, после сигнала перестают принимать новые задачи, а WaitGroup дожидается завершения текущих задач. Отсюда вышли на мьютексы и другие примитивы синхронизации, а затем обсудили масштабирование: сколько запускать воркеров, зачем нужен буфер при всплесках нагрузки и когда стоит переходить на распределённую очередь.
В итоге обе команды были готовы меня принять, и я выбрал вторую из-за открытой позиции в штат команды. Если команда не может взять стажёра, HR подбирает другие варианты.
Я рекомендую при отборе в Яндекс иметь уверенную базу в алгоритмах, попадаются задачи разного уровня, поэтому стоит быть готовым ко всему. Также подтянуть знания по языку и сетям и ОС, всегда могут и по ним спросить. Ну и главное, это не бояться, если чего-то забыли или не знаете, всегда можно побеседовать с интервьюером и попробовать прийти к правильному ответу, это лучше, чем просто молчать или сдаться.
Подписаться: @codeof_art
Please open Telegram to view this post
VIEW IN TELEGRAM
❤2🔥2
Новый пост из серии про паттерны на реальном коде. Разбираем штуку, с которой рано или поздно встречается любой сервис, живущий в интернете: в него начинают лить больше, чем он способен переварить.
Ситуация простая. У тебя есть сервис, который что-то принимает извне — запросы, события, сообщения. И в какой-то момент поток на входе становится больше, чем ты успеваешь обрабатывать. Причины разные: у клиента выкатили баг, и он спамит одним и тем же по кругу; резкий наплыв пользователей; банальный DDoS. Если просто сидеть и принимать всё подряд, исход один из двух — либо сервис ложится под нагрузкой, либо копит необработанное в памяти, пока она не кончится, и падает уже намертво. Защита от этого называется backpressure: сервис не молча захлёбывается, а сам говорит источникам «э, притормозите».
Разберём на Sentry. Если не знаком: это сервис, куда приложения шлют информацию о своих ошибках и падениях — упало что-то в проде, полетел отчёт с деталями, разработчики видят его в удобном интерфейсе, а не роются в логах. Нагрузка у неё дикая: тысячи чужих приложений долбят её событиями безостановочно. На входе у Sentry стоит отдельный компонент — Relay, он первым встречает весь этот поток и решает, что с ним делать. На нём и посмотрим, как грамотно держать удар. Код открыт: https://github.com/getsentry/relay
Первое, что там сделано с умом, — ограничение стоит не одним общим рубильником на всё, а раздельно, по типам данных и по каждому проекту. Можно прижать один вид событий у одного клиента, не задев остальной трафик. Клиенту, который упёрся в лимит, прилетает ответ 429 и заголовок с числом: «подожди столько-то секунд». И вот ключевая тонкость: правильный клиент в ответ на это НЕ шлёт то же самое заново — он выбрасывает событие и ждёт. Потому что если в ответ на «перегруз» все дружно начнут повторять запросы, они этим перегруз только усилят. В этом и суть backpressure: смысл ответа — «перестань слать вообще», а не «попробуй ещё разок». Обычная ошибка говорит «повтори», backpressure говорит «уймись» — это разные вещи.
Второй умный момент — как Relay хранит сами лимиты. Он держит их в памяти и освежает раз в несколько минут, а не бегает во внешнее хранилище на каждое событие (иначе оно само стало бы узким горлышком). Отсюда забавная деталь: самый первый запрос, упёршийся в свежий лимит, может ещё проскочить с ответом 200 — просто потому что в памяти лимит ещё не обновился, а следующий уже получит честный отказ. Осознанный размен: чуть менее точно, зато во много раз дешевле под нагрузкой. Клиентов, которые давно в лимите, Relay отшивает вообще бесплатно — их «приговор» уже лежит в памяти.
Третий уровень — что делать с тем, что уже приняли, но обработать пока не успели. Relay складывает такие события в очередь в памяти, но следит за её размером: пока памяти занято меньше порога (по умолчанию 80%) — держит очередь в ней, ради скорости. Перевалило за порог — начинает скидывать на диск. Медленнее, зато не сожрёт всю память и не рухнет, пока разгребает завал. Такой буфер сглаживает всплеск: не теряем события и не падаем от переполнения памяти.
Теперь — как это утащить к себе, даже без всякого Sentry. Принцип работает везде, где что-то принимает поток извне. Пишешь API, которое дёргают чужие сервисы? Отдавай на перегрузе честный 429 с «подожди столько-то», а не пытайся героически переварить всё и не роняй сервер. Обрабатываешь очередь сообщений? Следи за её длиной и умей притормозить того, кто в неё пишет. Ходишь во внешний API сам? Уважай его 429 и не ретрай мгновенно — ты этим только добьёшь того, кто и так лежит.
И три мысли на вынос. Лимиты делай точечными, а не «рубильник на всё сразу». Сигнал перегруза — это «перестань», а не «повтори», и клиенты должны его уважать. И заранее думай, что делать с тем, что уже принял, но не осилил, — буфер с выходом на диск лучше, чем гордое падение. Наивное «очередь большая — верну 500» не делает ничего из этого, поэтому и падает первым.
Подписаться: @codeof_art
Вступить в чатик: @code_of_art
Ситуация простая. У тебя есть сервис, который что-то принимает извне — запросы, события, сообщения. И в какой-то момент поток на входе становится больше, чем ты успеваешь обрабатывать. Причины разные: у клиента выкатили баг, и он спамит одним и тем же по кругу; резкий наплыв пользователей; банальный DDoS. Если просто сидеть и принимать всё подряд, исход один из двух — либо сервис ложится под нагрузкой, либо копит необработанное в памяти, пока она не кончится, и падает уже намертво. Защита от этого называется backpressure: сервис не молча захлёбывается, а сам говорит источникам «э, притормозите».
Разберём на Sentry. Если не знаком: это сервис, куда приложения шлют информацию о своих ошибках и падениях — упало что-то в проде, полетел отчёт с деталями, разработчики видят его в удобном интерфейсе, а не роются в логах. Нагрузка у неё дикая: тысячи чужих приложений долбят её событиями безостановочно. На входе у Sentry стоит отдельный компонент — Relay, он первым встречает весь этот поток и решает, что с ним делать. На нём и посмотрим, как грамотно держать удар. Код открыт: https://github.com/getsentry/relay
Первое, что там сделано с умом, — ограничение стоит не одним общим рубильником на всё, а раздельно, по типам данных и по каждому проекту. Можно прижать один вид событий у одного клиента, не задев остальной трафик. Клиенту, который упёрся в лимит, прилетает ответ 429 и заголовок с числом: «подожди столько-то секунд». И вот ключевая тонкость: правильный клиент в ответ на это НЕ шлёт то же самое заново — он выбрасывает событие и ждёт. Потому что если в ответ на «перегруз» все дружно начнут повторять запросы, они этим перегруз только усилят. В этом и суть backpressure: смысл ответа — «перестань слать вообще», а не «попробуй ещё разок». Обычная ошибка говорит «повтори», backpressure говорит «уймись» — это разные вещи.
Второй умный момент — как Relay хранит сами лимиты. Он держит их в памяти и освежает раз в несколько минут, а не бегает во внешнее хранилище на каждое событие (иначе оно само стало бы узким горлышком). Отсюда забавная деталь: самый первый запрос, упёршийся в свежий лимит, может ещё проскочить с ответом 200 — просто потому что в памяти лимит ещё не обновился, а следующий уже получит честный отказ. Осознанный размен: чуть менее точно, зато во много раз дешевле под нагрузкой. Клиентов, которые давно в лимите, Relay отшивает вообще бесплатно — их «приговор» уже лежит в памяти.
Третий уровень — что делать с тем, что уже приняли, но обработать пока не успели. Relay складывает такие события в очередь в памяти, но следит за её размером: пока памяти занято меньше порога (по умолчанию 80%) — держит очередь в ней, ради скорости. Перевалило за порог — начинает скидывать на диск. Медленнее, зато не сожрёт всю память и не рухнет, пока разгребает завал. Такой буфер сглаживает всплеск: не теряем события и не падаем от переполнения памяти.
Теперь — как это утащить к себе, даже без всякого Sentry. Принцип работает везде, где что-то принимает поток извне. Пишешь API, которое дёргают чужие сервисы? Отдавай на перегрузе честный 429 с «подожди столько-то», а не пытайся героически переварить всё и не роняй сервер. Обрабатываешь очередь сообщений? Следи за её длиной и умей притормозить того, кто в неё пишет. Ходишь во внешний API сам? Уважай его 429 и не ретрай мгновенно — ты этим только добьёшь того, кто и так лежит.
И три мысли на вынос. Лимиты делай точечными, а не «рубильник на всё сразу». Сигнал перегруза — это «перестань», а не «повтори», и клиенты должны его уважать. И заранее думай, что делать с тем, что уже принял, но не осилил, — буфер с выходом на диск лучше, чем гордое падение. Наивное «очередь большая — верну 500» не делает ничего из этого, поэтому и падает первым.
Подписаться: @codeof_art
Вступить в чатик: @code_of_art
❤3⚡2