Art of Code
2.17K subscribers
53 photos
2 videos
3 files
103 links
По вопросам: @vice22821

Чат: @code_of_art
Download Telegram
System Design: backend

Задача с реального собеса Яндекса. Условие: приходит уведомление — id, тип (EMAIL/SMS/PUSH), получатель, текст. У получателя есть разрешённые каналы и блок-лист отправителей. Нужно отфильтровать уведомление и не отправить дубль, если такое же уже было за последние 24 часа. Хранилище реализовывать не надо — только контракты и логика. Погнали.

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

Определим рамки задачи
Сначала границы: какие каналы поддерживаем, откуда берём настройки получателя, что считаем «таким же» уведомлением для дедупа.

Например, что значит «такое же»? «Ваш заказ №123 готов» и «Ваш заказ №124 готов» — дубль или нет? А если одно пришло по EMAIL, а второе по SMS?

Поэтому уточняем:
* дедуп общий для всех каналов или отдельный;
* что именно считается одинаковым уведомлением;
* что считается успешной отправкой;
* какие ожидаются RPS.

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

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

Не один раздутый if, а pipeline из мелких фильтров:
- канал разрешён у получателя;
- отправитель не в блок-листе;
- уведомление не дубль за последние 24 часа.

Первый же фильтр, сказавший «нет», отсекает уведомление — остальные не гоняем. Такую систему легко расширять: новый фильтр = ещё одно звено, а не правка портянки.

Возвращаемся к дедупликации
Дедуп за 24 часа означает, что система должна хранить след недавно отправленных уведомлений. Ключ вроде: recipient + type + id. А по нему — время отправки. Пришло новое — считаем ключ и смотрим, существует ли такой за последние 24 часа. И два неочевидных момента.

Первый — что именно входит в notificationIdentity. Сырый текст не всегда подходит: если в нём динамические данные, побайтовое сравнение может дать неправильную семантику. Поэтому сначала выясняем у интервьюера, что бизнес считает дублем. Второй — TTL. Записи должны сами протухать через 24 часа, иначе хранилище будет расти бесконечно.

Где сыпятся
Порядок фильтров: дешёвые и отсекающие проверки — вперёд. Канал и блок-лист — настройки. Дедуп — поход в стор. Глупо лезть в стор за дедупом, если уведомление и так отсечётся выключенным push.

Но есть ещё одна ловушка — гонка на дедупе. Поэтому check() и запись факта отправки должны быть атомарными. Например, через операцию tryReserve(key, ttl): первый запрос получает true, второй — false. А дальше интервьюер вполне может спросить: что будет, если мы зарезервировали уведомление, а внешний провайдер упал? Вот тут уже нужно отдельно определить семантику: защищаемся от повторного вызова сервиса или гарантируем отсутствие повторной доставки пользователю? Это разные задачи.

Контракты, а не реализация
Откуда берутся настройки и история отправок — прячем за интерфейсами: SettingsProvider, HistoryStore, и неважно, Redis там, PostgreSQL или внешний сервис. На собесе мы проектируем логику, а не привязываемся к конкретному хранилищу.

Что тут на самом деле проверяют
Проверяют одно: видишь ли ты, что это не «класс Notification с четырьмя полями», а конвейер фильтров с памятью о недавних отправках. Красивые модели нарисует и джун — и утонет в них, не дойдя до логики. Инженер сразу думает: что проверяем → в каком порядке → где храним состояние → что считаем дублем → что произойдёт при гонке.

А дальше строит pipeline от дешёвых проверок к дорогим, прячет источники данных за контрактами и понимает, что дедупликация — это не просто get() в Redis.

Подписаться: @codeof_art
Вступить в чатик: @code_of_art
🔥7👍2🏆2
razbor_testa.pdf
66.4 KB
Обычно здесь разбираем бэкенд и фронтенд, но сегодня о другом.

У Авито сейчас идёт набор на курс по QA. Регистрация была до 16 августа, а до 19-го нужно ещё пройти тест.

Кто уже подался и тест пока не решил — забирайте разбор выше: 32 вопроса, от базы тестирования и приоритетов багов до основ кода, HTTP и командной строки, с подробным объяснением каждого ответа. Сам тест не то чтобы сложный, но лучше сверить логику заранее, чем гадать на скрининге.

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

Подписаться: @codeof_art
Вступить в чатик: @code_of_art
❤5🔥2👍1
Гайд на GO в Авитo.pdf
203.4 KB
Полный цикл собесов на Go-разработчика в Авито

Идут последние 5 часов скидки на наши карьерные курсы ПРО. В честь этого в посте разберемся, как на самом деле устроен наём в Авито. Свёл официальный плейбук компании с внутренними методичками для интервьюеров по техническим секциям, которые предоставили наши выпускники. Получилась такая роудмапа: 4-5 встреч от первого созвона до оффера, и на каждом этапе могут разбить на несколько созвонов.

Этап 1. Звонок с рекрутером
Тут все по классике: обсуждение опыта, ожидания от новой работы, причины смены места. Можно и нужно закидывать встречные вопросы про команду и процессы - лучше перед этим с манифестом ознакомиться, так будешь выглядить подшаренным, что +реп дает.

Этап 2. Скоринговое интервью
30 минут в Zoom по техничке, но без лайвкодинга. Спрашивают несложные вопросы: по алгоритмам и структурам данных, языку программирования, HTTP, SQL, Git, Unix. Легкий фильтр перед тем, как тратить 2-3 часа на полноценную техничку, тут просто нужно готовиться по теории, ничего страшного здесь нет.

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

"Программирование" - общая для любого стека часть на алгоритмы и сложность, причём библиотечными функциями пользоваться нельзя, только руками. Час времени, easy/medium задачки, уровень определяют по чёткой сетке: от "не решил ни одной задачи" до "решил всё оптимально, без подсказок, ещё и объясняет вслух". В целом, если вдруг твой код не компилиться из-за синтаксической ошибки например, но ты объяснил свой код, то на это скорее всего закроют глаза просто. Реальные задачи в файле.

"Платформа" - уже под Go: указатели, горутины, каналы, context, сеть. Классика - горутины в цикле, которые ищут максимальное чётное число. Подробнее в файлике.

"Проектирование" - опциональная, идёт последней и только при успешном прохождении первых двух. Главный дифференциатор для выхода на грейд E5 и выше. Дают кейс вроде "спроектируй доску объявлений" или условие под конкретную команду, интервьюер играет заказчика и оценивает не столько итоговую схему, сколько ход рассуждений: начинают с простого варианта, а если остаётся время - усложняют требования. Рисуют в Draw.io, Miro, Whimsical или Excalidraw - стоит заранее зарегистрироваться и освоиться с инструментом, а не разбираться в интерфейсе на самом интервью.

Этап 4. Финальное интервью
Час с нанимающим менеджером и рекрутером. Уже не про код, а про мотивацию, soft skills и culture fit. Расскажут, чем занимается команда и как устроены процессы, а сами посмотрят, комфортно ли вам друг с другом и совпадают ли взгляды с ценностями команды.

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

Подробней с задачами в прикрепленном файле, все это закрывается на наших курсах. Отзывы о прошлом наборе на курс Бэкенд ПРО здесь и ниже (ставьте бананы).
➡️ Записаться

Подписаться: @postypashki_old
Please open Telegram to view this post
VIEW IN TELEGRAM
Почему бэкендеру-новичку в 2026 мало уметь перекладывать JSON

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

Что у джунов:
Junior Go, ITK academy: прямым текстом: PostgreSQL и SQL с транзакциями, JOIN и оптимизацией запросов, базовый Redis, REST API, сетевые протоколы и их уровни, принципы конкурентного программирования в Go, Docker и gRPC. Это джун, а тут уже и многопоточка, и сети, и транзакции.

Junior Java, ИТ-Холдинг Т1: позиция джуновская, а в требованиях: уверенное владение Java Core и multi-threading, знание основ и опыт разработки микросервисных систем, работа с брокерами сообщений (Kafka/RabbitMQ), опыт на высоконагруженных проектах, разные типы БД и понимание CI/CD. Многопоточка и брокеры в джун-вакансии буквально.

Младший Python-разработчик, Ozon: отдел разработки аналитических инструментов и управления данными. Бигтех спокойно берёт джунов на внутреннюю дата-платформу: Python, SQL и базы, REST-интеграции внутренних сервисов, дата-пайплайны.

Общая картина по всему рынку джунов та же: на бэкенде обязательны работа с БД, проектирование REST API и понимание архитектурных паттернов: микросервисы, монолит, event-driven. То есть очереди, кэш, микросервисы и БД глубже, чем «умею JOIN» - это базовый минимум.

А что с мидлами
Middle Go, Т-Банк, команда инструментов продуктовой аналитики: стек PostgreSQL, Kafka, Cassandra, Prometheus, Golang, Kubernetes; нужно понимать архитектуру многокомпонентных систем - балансировку нагрузки и отказоустойчивость, плюс менторить джунов.

Разница между грейдами
Средние вилки по рынку 2026: джун - 80–150 тысяч, миддл - 200–350. И попадают в верх именно те, кто дружит с распределёнкой и многопоточкой.

Именно это мы разбираем на курсе Backend Про. Всё, что нужно молодому специалисту, который хочет реально разбираться в коде и распределённых системах, а не перекладывать JSON. Как раз таких разрабов и требуют российский бигтех и западные компании на текущий момент.

Кому зайдёт:
- Джунам и стажёрам: выйти за пределы типичных CRUD и расширить выбор вакансий;
- Тем, кто имеет опыт и уже метит в миддлы: без архитектуры и распределёнки грейд не поднимут.

Что ботаем по модулям:
Модуль 1. Многопоточка: потоки и процессы, синхронизация, race condition, deadlock, thread-safe структуры. Там, где ИИ врёт чаще всего.
Модуль 2. Сети
Модуль 3. Межсервисное взаимодействие и микросервисы: микросервисы против монолита, RPC, REST, брокеры, gRPC, stateful/stateless.
Модуль 4. Базы: SQL и NoSQL, планы выполнения, блокировки, транзакции, уровни изоляции.
Модуль 5. Highload: репликация, шардирование, балансировка, оптимизация и отказоустойчивость.
Модуль 6. Разбираем blockchain
Отдельно проходимся по систем дизайну

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

➡️Записаться
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3❤1👍1
System Design: Frontend

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

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

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

Дальше поток. Дизайн-токены - это единый источник правды для цветов, отступов, шрифтов, радиусов. Не хардкод «#1E90FF» по компонентам, а семантические токены («color-primary», «spacing-md»). Компоненты ссылаются на токены, а не на конкретные значения.

А теперь про очки, и это ключевое решение. Переключение темы в рантайме проще и дешевле всего на CSS-переменных: компоненты используют var(--color-primary), а смена темы — это подмена значений переменных на корневом элементе. Никакого перерендера React вообще - браузер сам перекрашивает. Объясни, почему это лучше передачи темы через JS/контекст: контекст дёргает перерендер всего поддерева, CSS-переменные - нет. Токены выносим в отдельный пакет/слой, чтобы шарить между командами и микрофронтами. Честно назови trade-off: CSS-переменные требуют дисциплины - ни одного захардкоженного цвета в компонентах, иначе тема поедет частично. Проговорил «CSS-переменные вместо JS ради отсутствия перерендера» - это ответ архитектурного уровня.

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

Подписаться: @codeof_art
Вступить в чатик: @code_of_art
🔥3🤩1
Выходим на новый уровень с линейкой 1️⃣1️⃣1️⃣

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

Для этого мы запускаем ПРО — углублённые карьерные курсы для тех, кто хочет качать карьеру и заработок! Для записи и вопросов — пишите менеджеру

📎Курсы ПРО подойдут тем, кто:

— уже знает основы и хочет глубже разобраться в своей специализации
— хочет перейти с junior на middle и расти дальше
— готовится к собеседованиям на более сильные позиции
— хочет сменить роль и добрать недостающие навыки
— уже на старте имеет сильную базу и хочет целиться выше стажёрских и junior-позиций

➡️Действует гарантия: прошел курс, выполнил все рекомендации, но не получил оффер — вернем деньги
➡️Курс длится 6 недель: теория, практика, домашние задания и пет-проект. Всё это время рядом преподаватель и куратор.

Открываем сразу 5 направлений:

➡️Аналитика ПРО
Продвинутый SQL, A/B-тесты, эконометрика, Causal Inference и ML.


➡️ML ПРО
Вывод модели в прод, MLOps, рекомендательные системы, ранжирование, uplift и динамическое преобразование.


➡️Backend ПРО
Многопоточка, System Desgin, Микросервисы, базы данных, кеширование, мониторинг и распределённые системы.


➡️Алгоритмы ПРО
Продвинутые алгоритмы и задачи для сложных технических интервью в hft фонды, faang+, для олимпиад и контестов.


➡️ИИ-агенты ПРО
Будем разбираться не просто в LLM. Вы научитесь проектировать полноценные агентные системы и за курс соберём 5 собственных AI-агентов и пройдём весь путь от архитектуры и инструментов до работы с RAG, multi-agent системами, MCP, evals и деплоем.


В программу всех курсов войдет:

🔵закрытый банк вопросов с интервью топовых бигтехов
🔵разбор ближайшей стажировки в Т-банк и Яндекс
🔵mock-собеседования с обратной связью
🔵рефералка в бигтех после защиты пет-проекта
🔵карьерная стратегия: резюме, поиск вакансий, подготовка к HR секциям

💰Бонус для всех записавшихся до 23.08 — курс про поиск валютной удалёнки и работы за рубежом в подарок
Please open Telegram to view this post
VIEW IN TELEGRAM
Мы тут постоянно разбираем system design — и по фронту, и по бэку. Но у теории есть одна засада: паттерны легко выучить как список названий. Гидратация, оптимистичное обновление, идемпотентность и т.д. — все слышали, многие даже перескажут определение. А на собесе или в проде вопрос звучит иначе: не «что такое circuit breaker», а «почему у тебя порог в 5 ошибок подряд не сработал» и «что бы ты поменял». И вот тут список названий не помогает.

Поэтому запускаем новую рубрику. Формат простой: берём известный опенсорсный проект — React, etcd, Excalidraw, Kafka, Postgres-обвязки — открываем их реальный код, PR или issue, и смотрим, какой паттерн там применён и, главное, зачем. Не абстрактное «есть коробочка, туда идут запросы», а конкретно: вот была проблема, вот как её решили, вот где решение всё равно упирается в потолок и какой компромисс инженеры сознательно приняли.

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

Что планируется по бэку. Распределённые системы (консенсус, выборы лидера, репликация и почему «сервер подтвердил» ещё не значит «сохранено»), устойчивость под нагрузкой (circuit breaker, rate limiting, backpressure), и работа с данными (очереди, идемпотентность, изоляция транзакций).

Что будет по фронту. Тоже не про «как сверстать кнопку», а про архитектуру: как устроен прерываемый рендеринг в React, почему undo/redo в коллаборативных редакторах переписывают с нуля, как работает изоляция расширений и почему она защищает не от всего, что не так очевидно в optimistic update и реактивности.

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

Подписаться: @codeof_art
Вступить в чатик: @code_of_art
❤4🔥3
«Кабанчика» обязан знать каждый уважающий себя айти специалист, но осилить 700 страниц сплошного текста не так уж и просто.. Чтобы ты не тратил нервы и силы, я пересказ всю книгу всего за минуту. Смотрим!

https://www.youtube.com/shorts/i0nsmAUByZk
🔥2
Стажировка в Авито одна из лучших возможностей для старта в разработке:

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

Для участия нужно подать анкету заполнить анкету до 30.08 и выполнить тест. Разбор теста уже выложен на нашем курсе бэкенд про.
➡️ Записаться.

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

• Видео интервью в асинхронном формате - это, когда вы говорите сами с собой, а ваши ответы записывают. Для подготовки смотрите этот пост.
• Обычно тестовое задание: написать какой-нибудь сервер. Примеры тут
• На собеседовании будут обсуждать тестовое задание. Финальных собеседований может быть несколько: с лидом, с менеджером, с ментором и так далее. Гайд на собесы тут.

При идеальном мэтче, вы в Авито - поздравляю! На единичные стажировки можно подать здесь.

Подписаться: @codeof_art
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3
Стажировка в Т-банк одна из лучших возможностей для старта в разработке:

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

Для участия нужно подать анкету заполнить анкету до 6 сентября и выполнить экзамен. Разбор программирования уже выложен на нашем курсе бэкенд про.
➡️ Записаться.

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

На собесе может быть все, что угодно на усмотрение интервьюера: могут быть даже математические задачи на логику в духе тюремных загадок. Обязателен лайвкодинг с задачами, которые часто подбирают под ваше направление (фронтендерам замыкания и event loop, Goшникам работа с рутинами и т.п.). Технические вопросы сильно зависят от команды: например, в команде T‑Мобайла гоняют по сетям, а в продуктовых в основном спрашивают синтаксис и основы. Иногда собеседование может пройти в формате "вайбчека" без технических вопросов, но это скорее исключение. Короче все, что есть в нашей программе курсов бэкенд старт и бэкенд про. Пример нашего выпускника здесь.

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

При идеальном мэтче, вы в Т-банке - поздравляю!

Подписаться: @codeof_art
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3
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.
• Проверка наличия ключа – использовалась 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
🔥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
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3👍2
Стажировка в Яндексе одна из лучших возможностей для старта в разработке:

• МНОГО КРАСИВЫХ СВОБОДНЫХ ЖЕНЩИН
• специалисты высокого класса
• зарплаты в среднем выше рынка
• современный стек и проекты
• хорошо выстроены процессы
• корпоративная культура

Для участия нужно подать анкету заполнить анкету и зарешать контест. Разбор контеста уже выложен на нашем курсе бэкенд про, алгоритмы про.
➡ Записаться.

Как заполнять анкеты смотрим этот ролик. После контеста вас ждет два алгособеса на 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
🔥4❤1
System Design: frontend

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

Почему такое вообще спрашивают. Геодезист выезжает на объект — поле, стройка, лес за городом, — и связи там может не быть весь день. А работать надо: открыть карту участка, занести замеры, отметить точки, что-то поправить. Если приложение при потере сети показывает белый экран, им попросту нельзя пользоваться в поле. Значит, оно должно работать так, будто интернет и не нужен, а сеть подхватывать само, когда специалист вернётся в зону покрытия.

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

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

Теперь как устроено внутри. Данные храним прямо на устройстве. Для структурированных данных — IndexedDB (это встроенная в браузер база; localStorage не годится — он крохотный и синхронный, тормозит всё вокруг). Картинки, стили, саму оболочку приложения кладём через Service Worker — это прослойка между приложением и сетью, которая отдаёт сохранённое, когда интернета нет. Читаем офлайн — берём из локальной базы. А с записью интереснее: когда человек что-то меняет без сети, мы не пытаемся тут же достучаться до сервера, а складываем изменение в локальную очередь. Появилась сеть — по очереди, в том же порядке, отправляем всё накопленное.

И вот мы уперлись в главное — в конфликты. Тут надо не просто сказать «ну разрулим», а назвать конкретный подход и объяснить, почему он. Самый простой — кто последний записал, того и правда. Работает, но молча затирает чужие изменения, а для замеров по объекту это чревато: перезатёр чью-то правку — и на объект поедут неверные координаты. Честнее — версии: у каждой записи есть номер версии, и если геодезист пытается сохранить поверх данных, которые на сервере уже обновились, сервер такое отклоняет, и мы решаем, что делать. Самый аккуратный, но и самый муторный вариант — сливать изменения по отдельным полям: один поправил координаты точки, другой — её описание, оба изменения выживают. Важно не назвать «правильный» ответ (его нет), а показать, что ты понимаешь разницу и осознанно выбираешь под ситуацию.

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

Если совсем коротко: тут проверяют, понял ли ты, что offline-first — это не «кэш прикрутить», а полноценная распределёнка со своими конфликтами и с тем, что данные какое-то время живут несогласованными. Назвал конкретную стратегию разрешения конфликтов и вспомнил про честный статус для пользователя — значит, в теме.

Подписаться: @codeof_art
Вступить в чатик: @code_of_art
🔥3
Сходил на собеседование в Шушу. Предложили интересную задачу: спроектировать агрегатор проституток. Смотрим! Смотрим! По ссылке:

https://www.youtube.com/shorts/PyVM4NU5ero
🔥1
В Яндекс без опыта с первого раза

Товарищи, продолжаем рассказывать про наших талантливых учеников.
На днях записали интервью с Полиной, нашей ученицей летнего потока Бэкенд СТАРТ.
➡ Записаться.

У неё не было опыта работы, топового вуза и олимпиад. И всего за 2 месяца получилось взять оффер в Яндекс.
Самое интересное, что она не откликалась на стажировку 👀

Смотрите в ролике как все получилось: https://www.youtube.com/watch?v=k6yYBESFHIs

В видео обсудили:
➡️как попасть на мероприятия Яндекса, где можно пройти собеседование
➡️как готовилась к алгосекциям и что на них спрашивали
➡️о чём говорили на финалах
➡️правда ли в Яндексе 500 этапов и сколько собесов было у неё
➡️с какими компаниями были еще собесы
➡️советы тем, кто сейчас ищет первую работу
Please open Telegram to view this post
VIEW IN TELEGRAM
🗿1
System Design: backend

Сегодня разберём задачу, которую мне давали на собесе в Яндекс. Штука на стыке проектирования и алгоритмов: мало накидать красивую схему на доске — надо ещё нормально объяснить, как данные поедут через систему. И вот тут сразу видно, шаришь ты или просто заучил модные слова.

Условие такое. Надо забэкапить данные — до терабайта. При сжатии они ужмутся где-то в полтора-три раза. Хранилище, куда мы всё складываем, принимает файлы не больше 100 мегабайт за раз. Нужно собрать конвейер: прочитать данные, сжать, записать. И главный подвох, вокруг которого вся задача: целиком в память это не влезет.

Первое, что приходит в голову, — «читаем файл, жмём, отправляем». И это ловушка. Терабайт в оперативку просто не поместится, так что про «прочитать файл целиком» надо забыть сразу. Задача с самого начала не про файл, а про поток: данные текут через тебя, ты хватаешь их по кусочку, обрабатываешь и отпускаешь — и никогда не держишь всё разом.

Но прежде чем что-то проектировать, я бы задал интервьюеру один вопрос. Как по мне, ради него задачу и придумали. Что делать, если данные сожмутся хуже обещанного, и очередной сжатый кусок всё равно вылезет за 100 мегабайт? Полтора-три раза — это как средняя температура по больнице, а не гарантия. Попадётся кусок, который жмётся плохо (уже сжатое видео, случайный мусор), — и он не влезет в лимит. Если ты сам спотыкаешься об этот момент, до того как тебя носом ткнули, — считай, полдела сделал: дальше этот вопрос всё равно вылезет. Заодно спроси, нужна ли параллельность и надо ли уметь продолжить с места обрыва, если всё грохнется на середине.

Теперь как оно работает внутри. Читаем данные небольшими порциями, каждую жмём и отправляем в хранилище куском не больше лимита. Получается конвейер из трёх шагов: читаем, жмём, отправляем. И логично, чтобы шаги крутились не по очереди, а разом — пока один кусок улетает в хранилище, следующий уже читается, а средний в это время жмётся. Само сжатие — самое прожорливое место, так что его можно раскидать на несколько потоков и жать куски параллельно.

И вот тут вылезает тонкость, которую многие упускают. Читать почти всегда быстрее, чем отправлять по сети. Если читать на полной скорости, а отправка не поспевает, то непрожатые куски начнут копиться в памяти — и привет, мы вернулись ровно к той беде, от которой бежали: память забита под завязку. Поэтому между шагами ставим очередь ограниченного размера. Забилась — чтение притормаживает и ждёт, пока отправка разгребёт накопленное. По сути система сама себя придушивает под нагрузкой и не даёт быстрой части захлебнуть медленную.

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

И ещё пара штук, которые отличают продуманное решение от учебного. Первая — контрольная сумма на каждый кусок. Иначе бэкап может тихо побиться, а узнаешь ты об этом в самый неподходящий момент — когда полез восстанавливаться, а там каша. Вторая — уметь продолжить с последнего нормально записанного куска, а не гнать терабайт по новой из-за обрыва на 90%. Для этого достаточно отмечать, что уже доехало.

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

Подписаться: @codeof_art
Вступить в чатик: @code_of_art
👍1
Товарищи, Поступашкам нужны контент мейкеры в основной канал по алгоритмам и другим дисциплинам. Если вы творческая личность, интересующейся алгоритмами (или другим), вам нравится писать посты/ придумывать идеи для контента, то обязательно пишите @vice22821. Оплата сдельная, ориентировочно за один пост от 2 тыс до 15 тыс рублей.

Обязательно делитесь с ребятами, которым это может быть интересно.
🔥2