👍2
Вопрос с собеседований
Что такое SPI (Service Provider Interface) в Java?🤓
Ответ:
SPI — это механизм для подключения модулей и расширений без изменения основного кода.
Реализуется через META-INF/services.
Используется во многих библиотеках (например, JDBC). Это паттерн «плагины» для Java-приложений.
#собеседование
Что такое SPI (Service Provider Interface) в Java?
Ответ:
SPI
Реализуется через META-INF/services.
Используется во многих библиотеках (например, JDBC). Это паттерн «плагины» для Java-приложений.
#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
История IT-технологий сегодня — 28 октября
ℹ️ Кто родился в этот день
Уи́льям Ге́нри Гейтс III (англ. William Henry Gates III; 28 октября 1955, Сиэтл, Вашингтон), более известный как Билл Гейтс (англ. Bill Gates) — американский предприниматель и программист, сооснователь компании Microsoft; один из пионеров персональных компьютеров и массового ПО.
Лэндон Курт Нолл (родился 28 октября 1960 года) — американский информатик и математик; со-обнаруживший 25-ю и 26-ю числа Мерсенна, автор хеш-функции Fowler–Noll–Vo и участник соревнований по обфускации кода.
🌐 Знаковые события
1914 — Фирма «Kodak» объявляет о начале работы над созданием технологий цветной фотографии.
#Biography #Birth_Date #Events #28Октября
Уи́льям Ге́нри Гейтс III (англ. William Henry Gates III; 28 октября 1955, Сиэтл, Вашингтон), более известный как Билл Гейтс (англ. Bill Gates) — американский предприниматель и программист, сооснователь компании Microsoft; один из пионеров персональных компьютеров и массового ПО.
Лэндон Курт Нолл (родился 28 октября 1960 года) — американский информатик и математик; со-обнаруживший 25-ю и 26-ю числа Мерсенна, автор хеш-функции Fowler–Noll–Vo и участник соревнований по обфускации кода.
1914 — Фирма «Kodak» объявляет о начале работы над созданием технологий цветной фотографии.
#Biography #Birth_Date #Events #28Октября
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Что такое gRPC и зачем он нужен
Представьте, что ваши программы — это люди в огромном городе. Им нужно обмениваться информацией: один спрашивает адрес, другой — погоду, третий — заказывает еду. Если они общаются письмами (медленно и объемно), то город встанет в пробке. А если по телефону — быстро, четко и без лишних слов?
Вот gRPC (высокопроизводительный фреймворк для удаленного вызова процедур) — это как суперсовременная телефонная сеть для программ. Он позволяет одной программе вызывать функции в другой, как будто они работают на одном компьютере, но через интернет или сеть.
Зачем изучать gRPC в 2025 году? Потому что мир софта ушел от простых сайтов к сложным системам: миллиарды устройств в интернете вещей, тысячи микросервисов в компаниях вроде Netflix или Uber. Обычные веб-API (как REST) здесь тормозят — gRPC ускоряет всё в 7–10 раз, экономит трафик и упрощает разработку.
Что такое RPC: Простое объяснение концепции удаленного вызова процедур
Удаленный вызов процедур (RPC — Remote Procedure Call) — это идея, где программа А "звонит" программе Б и говорит: "Выполни эту функцию и верни результат". Всё выглядит как обычный вызов локальной функции: передаешь данные, ждешь ответ — и готово. Никаких сложностей с сетью на уровне кода.
Пример из жизни: Вы в приложении нажимаете "Получить погоду" — ваше мобильное app вызывает функцию на сервере метеослужбы. Сервер считает, возвращает данные. В gRPC это пишется так же просто:
Без RPC пришлось бы вручную формировать запросы, парсить ответы — утомительно. gRPC автоматизирует всё: генерирует готовый код, управляет соединением и ошибками. В итоге — код чище, быстрее и надежнее.
Разница gRPC с REST: Почему RPC побеждает в скорости и гибкости
REST (Representational State Transfer — архитектурный стиль для веб-API) — популярный подход, где API строится вокруг эндпоинтов для получения данных. Использует HTTP-методы (GET, POST), текст в формате JSON. Просто читать человеку, но медленно для машин.
Вот ключевые различия:
Формат данных: REST — текст (JSON, большой и медленный), gRPC — бинарный (компактный, в 3–10 раз меньше). JSON "Привет, мир!" — 15 байт, в gRPC — 5 байт.
Скорость: gRPC на HTTP/2 (мультиплексирование — много запросов по одному каналу) в 7 раз быстрее при приеме данных, в 10 раз — при отправке. Идеально для мобильного интернета.
Гибкость общения: REST — только "запрос-ответ". gRPC поддерживает стриминг (поток сообщений): сервер шлет обновления в реальном времени (как чат), клиент загружает файлы порциями, или оба общаются одновременно.
Языки и платформы: REST — универсален, но код пишется вручную. gRPC генерирует код для 10+ языков (Python, Go, Java) из одного описания — никаких несоответствий.
Отладка: REST читаем в браузере, gRPC — бинарный, но есть инструменты вроде gRPCurl (аналог curl).
REST хорош для публичных API (сайты, простые apps). gRPC — для внутренних систем, где важна производительность. В 2025 году компании комбинируют: REST снаружи, gRPC внутри.
#Java #middle #gRPC
Представьте, что ваши программы — это люди в огромном городе. Им нужно обмениваться информацией: один спрашивает адрес, другой — погоду, третий — заказывает еду. Если они общаются письмами (медленно и объемно), то город встанет в пробке. А если по телефону — быстро, четко и без лишних слов?
Вот gRPC (высокопроизводительный фреймворк для удаленного вызова процедур) — это как суперсовременная телефонная сеть для программ. Он позволяет одной программе вызывать функции в другой, как будто они работают на одном компьютере, но через интернет или сеть.
Зачем изучать gRPC в 2025 году? Потому что мир софта ушел от простых сайтов к сложным системам: миллиарды устройств в интернете вещей, тысячи микросервисов в компаниях вроде Netflix или Uber. Обычные веб-API (как REST) здесь тормозят — gRPC ускоряет всё в 7–10 раз, экономит трафик и упрощает разработку.
Что такое RPC: Простое объяснение концепции удаленного вызова процедур
Удаленный вызов процедур (RPC — Remote Procedure Call) — это идея, где программа А "звонит" программе Б и говорит: "Выполни эту функцию и верни результат". Всё выглядит как обычный вызов локальной функции: передаешь данные, ждешь ответ — и готово. Никаких сложностей с сетью на уровне кода.
Пример из жизни: Вы в приложении нажимаете "Получить погоду" — ваше мобильное app вызывает функцию на сервере метеослужбы. Сервер считает, возвращает данные. В gRPC это пишется так же просто:
Клиент (ваше app): ответ = сервер.ПолучитьПогоду(город="Москва")
Сервер: выполняет расчет и отдает результат.
Без RPC пришлось бы вручную формировать запросы, парсить ответы — утомительно. gRPC автоматизирует всё: генерирует готовый код, управляет соединением и ошибками. В итоге — код чище, быстрее и надежнее.
Разница gRPC с REST: Почему RPC побеждает в скорости и гибкости
REST (Representational State Transfer — архитектурный стиль для веб-API) — популярный подход, где API строится вокруг эндпоинтов для получения данных. Использует HTTP-методы (GET, POST), текст в формате JSON. Просто читать человеку, но медленно для машин.
Вот ключевые различия:
Формат данных: REST — текст (JSON, большой и медленный), gRPC — бинарный (компактный, в 3–10 раз меньше). JSON "Привет, мир!" — 15 байт, в gRPC — 5 байт.
Скорость: gRPC на HTTP/2 (мультиплексирование — много запросов по одному каналу) в 7 раз быстрее при приеме данных, в 10 раз — при отправке. Идеально для мобильного интернета.
Гибкость общения: REST — только "запрос-ответ". gRPC поддерживает стриминг (поток сообщений): сервер шлет обновления в реальном времени (как чат), клиент загружает файлы порциями, или оба общаются одновременно.
Языки и платформы: REST — универсален, но код пишется вручную. gRPC генерирует код для 10+ языков (Python, Go, Java) из одного описания — никаких несоответствий.
Отладка: REST читаем в браузере, gRPC — бинарный, но есть инструменты вроде gRPCurl (аналог curl).
REST хорош для публичных API (сайты, простые apps). gRPC — для внутренних систем, где важна производительность. В 2025 году компании комбинируют: REST снаружи, gRPC внутри.
#Java #middle #gRPC
👍2👎1
Почему Google создал gRPC: От внутренних нужд к мировому стандарту
Google — гигант с миллионами микросервисов (маленькие программы, работающие вместе). С 2001 года они использовали внутренний фреймворк Stubby для их связи. Но Stubby был закрытым, и партнерам (Android, YouTube API) приходилось писать свои библиотеки.
В 2015 году Google открыл gRPC: эволюцию Stubby на HTTP/2 и Protocol Buffers (protobuf — бинарный формат для данных).
Цели:
Объединить сервисы в дата-центрах и на устройствах.
Поддержка стриминга для реал-тайма.
Автоматическая генерация кода — один .proto-файл для всех языков.
К 2025 году gRPC — проект CNCF (Cloud Native Computing Foundation), используется в Google Cloud, Netflix (стриминг видео), Uber (поездки в реальном времени), Cisco. За 10 лет обработал триллионы вызовов — доказанная надежность.
Где применяется gRPC: От микросервисов до умных устройств
gRPC — король сценариев с высокой нагрузкой:
Микросервисы: Тысячи маленьких сервисов в Kubernetes (оркестратор контейнеров). Netflix использует для рекомендаций фильмов — миллиарды запросов в секунду без задержек. Внутренняя связь: сервис оплаты "звонит" сервису доставки.
Интернет вещей (IoT): Миллиарды устройств (умные лампочки, датчики). gRPC соединяет их с облаком: низкий трафик, стриминг данных (температура в реальном времени). Пример: умный дом от Google Nest.
Внутренние API: В компаниях — связь backend'ов. Uber: расчет маршрутов между сервисами. Банки: обработка транзакций. Не для клиентов (там REST), а внутри — для скорости.
В 2025: gRPC в AI (TensorFlow), играх (реал-тайм мультиплеер), авто (Tesla — связь машин с облаком).
#Java #middle #gRPC
Google — гигант с миллионами микросервисов (маленькие программы, работающие вместе). С 2001 года они использовали внутренний фреймворк Stubby для их связи. Но Stubby был закрытым, и партнерам (Android, YouTube API) приходилось писать свои библиотеки.
В 2015 году Google открыл gRPC: эволюцию Stubby на HTTP/2 и Protocol Buffers (protobuf — бинарный формат для данных).
Цели:
Объединить сервисы в дата-центрах и на устройствах.
Поддержка стриминга для реал-тайма.
Автоматическая генерация кода — один .proto-файл для всех языков.
К 2025 году gRPC — проект CNCF (Cloud Native Computing Foundation), используется в Google Cloud, Netflix (стриминг видео), Uber (поездки в реальном времени), Cisco. За 10 лет обработал триллионы вызовов — доказанная надежность.
Где применяется gRPC: От микросервисов до умных устройств
gRPC — король сценариев с высокой нагрузкой:
Микросервисы: Тысячи маленьких сервисов в Kubernetes (оркестратор контейнеров). Netflix использует для рекомендаций фильмов — миллиарды запросов в секунду без задержек. Внутренняя связь: сервис оплаты "звонит" сервису доставки.
Интернет вещей (IoT): Миллиарды устройств (умные лампочки, датчики). gRPC соединяет их с облаком: низкий трафик, стриминг данных (температура в реальном времени). Пример: умный дом от Google Nest.
Внутренние API: В компаниях — связь backend'ов. Uber: расчет маршрутов между сервисами. Банки: обработка транзакций. Не для клиентов (там REST), а внутри — для скорости.
В 2025: gRPC в AI (TensorFlow), играх (реал-тайм мультиплеер), авто (Tesla — связь машин с облаком).
#Java #middle #gRPC
👍3
Что выведет код?
#Tasks
import java.util.HashSet;
public class Task281025 {
public static void main(String[] args) {
HashSet<String> set1 = new HashSet<>();
set1.add("hello");
set1.add("world");
HashSet<String> set2 = new HashSet<>();
set2.add("world");
set2.add("hello");
System.out.println(set1.equals(set2));
System.out.println(set1 == set2);
HashSet<String> set3 = set1;
set3.add("java");
System.out.println(set1.contains("java"));
System.out.println(set2.contains("java"));
}
}
#Tasks
👍2
Варианты ответа:
Anonymous Quiz
27%
false true true false
27%
true true false false
7%
false false true true
40%
true false true false
👍1
Вопрос с собеседований
Что такое memory leak (утечка памяти) в Java?🤓
Ответ:
Memory leak — это ситуация, когда объекты остаются достижимыми для GC, но больше не используются.
JVM не может их освободить, и память постепенно заполняется.
Частые причины: статические коллекции, кэши без очистки, слушатели без отписки и замыкания на внешние объекты.
#собеседование
Что такое memory leak (утечка памяти) в Java?
Ответ:
Memory leak
JVM не может их освободить, и память постепенно заполняется.
Частые причины: статические коллекции, кэши без очистки, слушатели без отписки и замыкания на внешние объекты.
#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
История IT-технологий сегодня — 29 октября
ℹ️ Кто родился в этот день
Дэниел Джулиус Бернстайн (родился 29 октября 1971 года) — американский математик и криптограф, разработчик алгоритмов Curve25519, ChaCha20, Poly1305, создатель почтового сервера qmail и DNS-сервера djbdns; один из ведущих специалистов по безопасности и криптографии в вычислительной науке.
Габриэле Котсис (родилась 29 октября 1967 года в Вене , Австрия) — австрийская информатик, профессор компьютерных наук (Johannes Kepler University), специалист по параллельным вычислениям и руководитель кафедры телекоммуникаций и кооперативных информационных систем; активный участник ACM и научной политики.
🌐 Знаковые события
1969 — первая передача данных между двумя компьютерами в сети в рамках проекта ARPANET — рождение Интернета.
#Biography #Birth_Date #Events #29Октября
Дэниел Джулиус Бернстайн (родился 29 октября 1971 года) — американский математик и криптограф, разработчик алгоритмов Curve25519, ChaCha20, Poly1305, создатель почтового сервера qmail и DNS-сервера djbdns; один из ведущих специалистов по безопасности и криптографии в вычислительной науке.
Габриэле Котсис (родилась 29 октября 1967 года в Вене , Австрия) — австрийская информатик, профессор компьютерных наук (Johannes Kepler University), специалист по параллельным вычислениям и руководитель кафедры телекоммуникаций и кооперативных информационных систем; активный участник ACM и научной политики.
1969 — первая передача данных между двумя компьютерами в сети в рамках проекта ARPANET — рождение Интернета.
#Biography #Birth_Date #Events #29Октября
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Какой из реализаций Map вам приходилось пользоваться чаще всего?
Anonymous Poll
87%
HashMap
7%
LinkedHashMap
0%
TreeMap
0%
Hashtable
3%
ConcurrentHashMap
0%
IdentityHashMap
0%
WeakHashMap
3%
EnumMap
👍1
Раздел 6. Коллекции в Java
Глава 5. Map — отображения (словари)
Интерфейс Map<K, V> — это часть Java Collections Framework (JCF) из пакета java.util, который представляет структуру для хранения ассоциативных данных. В отличие от других коллекций, таких как List или Set, которые хранят отдельные элементы, Map хранит пары, где каждый ключ (K) связан с значением (V). Это позволяет быстро находить значение по ключу, как в словаре или телефонной книге.
Основные понятия:
Ключ (Key): Уникальный идентификатор для доступа к значению. Ключи не могут дублироваться — если добавить пару с существующим ключом, значение перезапишется.
Значение (Value): Данные, ассоциированные с ключом. Значения могут дублироваться.
Пара (Entry): Единица хранения в Map — комбинация ключа и значения.
Map моделирует математическое отображение (mapping), где каждый ключ maps to ровно одно значение. Это делает Map идеальным для сценариев, где нужна ассоциация, например, ID пользователя — профиль, слово — перевод.
Отличия от Collection:
Map не расширяет Collection<E> — это отдельная ветвь JCF.
Collection — последовательность элементов, Map — ассоциативный массив.
В Map нет индексации (нет get(int index)), доступ только по ключу.
Размер Map — количество пар, не элементов.
Generics в Map: <K, V> обеспечивает типобезопасность: ключи одного типа (например, Integer), значения другого (String). Без generics (raw Map) — устарело и небезопасно.
Хранение пар «ключ–значение»: Особенности
Map хранит данные в форме пар, где ключ — уникальный, а значение — связанное с ним. Это позволяет эффективно решать задачи поиска и ассоциации.
Уникальность ключей:
Ключи всегда уникальны: Map не позволяет дубликаты ключей. Если ключ уже существует, значение обновляется.
Уникальность определяется методами equals() и hashCode() (в hash-based реализациях) или compareTo() (в sorted).
Нюанс: Для custom ключей обязательно переопределите equals() и hashCode() — иначе уникальность по ссылке, не по значению.
Дубликаты значений:
Значения могут повторяться: Несколько ключей могут ссылаться на одно значение.
Нюанс: Если значение — mutable объект, изменения в одном месте отразятся везде (по ссылке).
Null в Map:
Ключи: Большинство реализаций позволяют один null-ключ (HashMap, LinkedHashMap), но TreeMap — нет (NullPointerException).
Значения: Null разрешен всегда.
Порядок в Map:
В общем случае нет (зависит от реализации): Не полагайтесь на порядок пар.
Нюанс: Map не упорядочен, как List, но некоторые реализации добавляют порядок.
Размер и емкость:
Размер (size()) — количество пар.
Емкость: В hash-based — initial capacity и load factor (например, 0.75 — при заполнении >75% ресайз).
Производительность:
В среднем O(1) для доступа по ключу в hash-based, O(log n) в tree-based.
Нюанс: Зависит от качества hashCode() — плохие хэши приводят к деградации до O(n).
Полезные советы для новичков
Выбор типов K/V: Ключи — immutable (String, Integer), чтобы избежать изменений, влияющих на хэш.
Custom ключи: Переопределяйте equals/hashCode (IDE поможет: Generate → equals() and hashCode()).
Map vs другие коллекции: Используйте Map для ассоциаций, Set для уникальных элементов, List для последовательностей.
#Java #для_новичков #beginner #Map
Глава 5. Map — отображения (словари)
Интерфейс Map<K, V> — это часть Java Collections Framework (JCF) из пакета java.util, который представляет структуру для хранения ассоциативных данных. В отличие от других коллекций, таких как List или Set, которые хранят отдельные элементы, Map хранит пары, где каждый ключ (K) связан с значением (V). Это позволяет быстро находить значение по ключу, как в словаре или телефонной книге.
Основные понятия:
Ключ (Key): Уникальный идентификатор для доступа к значению. Ключи не могут дублироваться — если добавить пару с существующим ключом, значение перезапишется.
Значение (Value): Данные, ассоциированные с ключом. Значения могут дублироваться.
Пара (Entry): Единица хранения в Map — комбинация ключа и значения.
Map моделирует математическое отображение (mapping), где каждый ключ maps to ровно одно значение. Это делает Map идеальным для сценариев, где нужна ассоциация, например, ID пользователя — профиль, слово — перевод.
Отличия от Collection:
Map не расширяет Collection<E> — это отдельная ветвь JCF.
Collection — последовательность элементов, Map — ассоциативный массив.
В Map нет индексации (нет get(int index)), доступ только по ключу.
Размер Map — количество пар, не элементов.
Generics в Map: <K, V> обеспечивает типобезопасность: ключи одного типа (например, Integer), значения другого (String). Без generics (raw Map) — устарело и небезопасно.
Хранение пар «ключ–значение»: Особенности
Map хранит данные в форме пар, где ключ — уникальный, а значение — связанное с ним. Это позволяет эффективно решать задачи поиска и ассоциации.
Уникальность ключей:
Ключи всегда уникальны: Map не позволяет дубликаты ключей. Если ключ уже существует, значение обновляется.
Уникальность определяется методами equals() и hashCode() (в hash-based реализациях) или compareTo() (в sorted).
Нюанс: Для custom ключей обязательно переопределите equals() и hashCode() — иначе уникальность по ссылке, не по значению.
Дубликаты значений:
Значения могут повторяться: Несколько ключей могут ссылаться на одно значение.
Нюанс: Если значение — mutable объект, изменения в одном месте отразятся везде (по ссылке).
Null в Map:
Ключи: Большинство реализаций позволяют один null-ключ (HashMap, LinkedHashMap), но TreeMap — нет (NullPointerException).
Значения: Null разрешен всегда.
Порядок в Map:
В общем случае нет (зависит от реализации): Не полагайтесь на порядок пар.
Нюанс: Map не упорядочен, как List, но некоторые реализации добавляют порядок.
Размер и емкость:
Размер (size()) — количество пар.
Емкость: В hash-based — initial capacity и load factor (например, 0.75 — при заполнении >75% ресайз).
Производительность:
В среднем O(1) для доступа по ключу в hash-based, O(log n) в tree-based.
Нюанс: Зависит от качества hashCode() — плохие хэши приводят к деградации до O(n).
Полезные советы для новичков
Выбор типов K/V: Ключи — immutable (String, Integer), чтобы избежать изменений, влияющих на хэш.
Custom ключи: Переопределяйте equals/hashCode (IDE поможет: Generate → equals() and hashCode()).
Map vs другие коллекции: Используйте Map для ассоциаций, Set для уникальных элементов, List для последовательностей.
#Java #для_новичков #beginner #Map
👍4
Что выведет код?
#Tasks
import java.util.HashMap;
import java.util.Map;
public class Task291025 {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
map.put("a", 1);
map.put("b", 2);
map.put("a", 3);
map.putIfAbsent("b", 4);
map.putIfAbsent("c", 5);
System.out.println(map.get("a"));
System.out.println(map.get("b"));
System.out.println(map.get("c"));
System.out.println(map.getOrDefault("d", 6));
}
}
#Tasks
👍1
👍1
Вопрос с собеседований
Что такое strong, soft, weak и phantom ссылки?🤓
Ответ:
Strong — обычная ссылка, объект не собирается GC.
Soft — GC удалит объект при нехватке памяти.
Weak — GC удалит при первой возможности.
Phantom — используется для отслеживания удаления объекта. Эти типы ссылок помогают управлять кэшами и жизненным циклом объектов.
#собеседование
Что такое strong, soft, weak и phantom ссылки?
Ответ:
Strong
Soft — GC удалит объект при нехватке памяти.
Weak — GC удалит при первой возможности.
Phantom — используется для отслеживания удаления объекта. Эти типы ссылок помогают управлять кэшами и жизненным циклом объектов.
#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
История IT-технологий сегодня — 30 октября
ℹ️ Кто родился в этот день
Андре́й Никола́евич Ти́хонов (17 [30] октября 1906, Гжатск (в настоящее время город Гагарин) Смоленской губернии — 7 октября 1993, Москва) — советский математик и геофизик, академик Академии наук СССР, дважды Герой Социалистического Труда. Основатель факультета вычислительной математики и кибернетики МГУ.
Карло Генрих Сейкин (родился 30 октября 1941 года) — швейцарско-американский компьютерный учёный, профессор Университета Калифорнии, Беркли; пионер в области архитектуры процессоров, компьютерной графики и CAD-инструментов для проектирования электронных схем.
🌐 Знаковые события
1907 — русский физик Борис Розинг в ответ на поданную им 25 июля заявку получил патент № 18076 на «Способ электрической передачи изображений на расстояние», то есть телевидение.
#Biography #Birth_Date #Events #30Октября
Андре́й Никола́евич Ти́хонов (17 [30] октября 1906, Гжатск (в настоящее время город Гагарин) Смоленской губернии — 7 октября 1993, Москва) — советский математик и геофизик, академик Академии наук СССР, дважды Герой Социалистического Труда. Основатель факультета вычислительной математики и кибернетики МГУ.
Карло Генрих Сейкин (родился 30 октября 1941 года) — швейцарско-американский компьютерный учёный, профессор Университета Калифорнии, Беркли; пионер в области архитектуры процессоров, компьютерной графики и CAD-инструментов для проектирования электронных схем.
1907 — русский физик Борис Розинг в ответ на поданную им 25 июля заявку получил патент № 18076 на «Способ электрической передачи изображений на расстояние», то есть телевидение.
#Biography #Birth_Date #Events #30Октября
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Как вы себя оцениваете по грейду?
Anonymous Poll
33%
Я наверно даже не джун
33%
Я точно джун
17%
Я уверенный мидл
17%
Сеньор я