fa
Feedback
Java: fill the gaps

Java: fill the gaps

رفتن به کانال در Telegram

Привет! Меня зовут Диана, и я занимаюсь разработкой с 2013. Здесь пишу просто и понятно про джава бэк 🔥Тот самый курс по многопочке🔥 https://fillthegaps.ru/mt Комплименты, вопросы, предложения: @utki_letyat

نمایش بیشتر

📈 تحلیل کانال تلگرام Java: fill the gaps

کانال Java: fill the gaps (@java_fillthegaps) در بخش زبانی روسی بازیگری فعال است. در حال حاضر جامعه شامل 12 548 مشترک است و جایگاه 10 113 را در دسته فناوری و برنامه‌ها و رتبه 52 819 را در منطقه روسيا دارد.

📊 شاخص‌های مخاطب و پویایی

از زمان ایجاد در невідомо، پروژه رشد سریعی داشته و 12 548 مشترک جذب کرده است.

بر اساس آخرین داده‌ها در تاریخ 08 ژوئن, 2026، کانال فعالیت پایداری دارد. در ۳۰ روز گذشته تغییر اعضا برابر -43 و در ۲۴ ساعت گذشته برابر -3 بوده و همچنان دسترسی گسترده‌ای حفظ شده است.

  • وضعیت تأیید: تأیید نشده
  • نرخ تعامل (ER): میانگین تعامل مخاطب 34.73% است و در ۲۴ ساعت نخست پس از انتشار، محتوا معمولاً N/A% واکنش نسبت به کل مشترکان کسب می‌کند.
  • دسترسی پست‌ها: هر پست به طور میانگین 0 بازدید دریافت می‌کند. در اولین روز معمولاً 0 بازدید جمع‌آوری می‌شود.
  • واکنش‌ها و تعامل: مخاطبان به‌طور فعال حمایت می‌کنند؛ میانگین واکنش به هر پست 0 است.
  • علایق موضوعی: محتوا بر موضوعات کلیدی مانند redis, hashmap, linkedhashmap, индекс, фича تمرکز دارد.

📝 توضیح و سیاست محتوایی

نویسنده این فضا را محل بیان دیدگاه‌های شخصی توصیف می‌کند:
Привет! Меня зовут Диана, и я занимаюсь разработкой с 2013. Здесь пишу просто и понятно про джава бэк 🔥Тот самый курс по многопочке🔥 https://fillthegaps.ru/mt Комплименты, вопросы, предложения: @utki_letyat

به لطف به‌روزرسانی‌های پرتکرار (آخرین داده در تاریخ 09 ژوئن, 2026)، کانال همواره به‌روز و دارای دسترسی بالاست. تحلیل‌ها نشان می‌دهد مخاطبان به‌طور فعال با محتوا تعامل دارند و آن را به نقطه اثرگذاری مهم در دسته فناوری و برنامه‌ها تبدیل کرده‌اند.

12 548
مشترکین
-324 ساعت
-207 روز
-4330 روز
آرشیو پست ها
Тестирование, часть 1. Вопросы на собеседовании Чем опытней разработчик, тем больше тем обсуждается на собеседованиях. Начиная с уровня middle будьте готовы к таким вопросам: 1️⃣ Назовите свойства юнит-тестов? Хорошие юнит-тесты соблюдают принцип FIRST: 🔸F – Fast Выполняются быстро. Никто не хочет лишний раз запускать медленные тесты. Один юнит-тест — не дольше 0.5 сек. 🔸I – Isolated / Independent Любой набор тестов можно запускать в любом порядке, тесты не зависят друг на друга. Каждый тест сфокусирован на одном действии и наборе параметров. Если тест упал, то сразу понятно, где и при каких условиях возникла ошибка. 🔸R – Repeatable Результат теста не зависит от операционной системы, конфигурации компьютера, внешних ресурсов и наличия интернета. Результат теста повторяется при многократном вызове. ⭐️ Это свойство хромает, когда тесты используют случайные числа или проверяют работу нескольких потоков. 🔸S – Self-Validating У теста два результата — прошёл или нет. Разработчик не должен проверять записи в логе или сравнивать текстовые файлы. 🔸T - Timely Тесты пишутся вовремя, в рамках той же задачи, что и основной код. ⭐️ Юнит-тесты должны быть читаемыми. Тогда их легко поменять, если бизнес-логика изменится. Сложно разбираться в методах test1(), test2(), test3() и переменных a, b, c. ⭐️ По тестам можно оценить инженерную культуру компании. Обратите внимание на количество и качество юнит-тестов, кто и когда их пишет. Если тестов нет, или сеньор пишет код и создаёт подзадачу «написать тесты» для джуниора - это дно. Откладывать тесты из-за дедлайна — тоже так себе. ⭐️ Тесты можно не писать для PoC (proof of concept) — временный код для проверки гипотез, который не связан с продакшн кодом. Тесты организуют по структуре 3A (Arrange-Act-Assert), также встречается название Given-When-Then.
// given
Инициализация переменных и моков.
// when
Вызов проверяемого метода.
// then
Проверка результата и состояния других объектов. 3 блока должны чётко следовать друг за другом, тогда тест легко читать. Если после блока проверок идёт действие и дополнительные проверки — значит тест слишком большой. 2️⃣ Что такое TDD? Test Driven Development - процесс разработки, когда сначала пишется тест, а потом код. Подробно это выглядит так: ▫️Написать тест для кода, которого нет ▫️Запустить тесты, новый тест падает ▫️Написать код, чтобы тест проходил ▫️Запустить тесты, тесты проходят ▫️Рефакторинг нового кода ▫️Запустить тесты, тесты проходят Плюсы TDD: ➕Код сразу покрыт тестами ➕У класса удобный интерфейс, который сразу используется в тестах ➕Структурированный код После этого следует такой диалог: - А Вы лично используете TDD? - Нет. - Почему? У него же столько плюсов. - Большой минус - частое переключение контекста и фокус на деталях. Мне удобнее написать простое рабочее решение, и только потом добавить проверки, валидацию и обработку ошибок. После этого в соответствии с требованиями как следует оттестировать то, что получилось. Я сразу пишу код, который легко использовать и тестировать, поэтому TDD меня только замедляет. - Согласен.

Статический анализ кода, часть 2. Инструменты В части 1 обсудили основные метрики: связность, связанность, сложность и размер. Также статический анализ включает проверку форматирования, поиск уязвимостей и возможных ошибок. Когда и чем можно выполнять статистический анализ? 1️⃣ Во время написания кода. С помощью встроенных правил IDE и дополнительных плагинов: ▫️Checkstyle проверяет форматирование, возможные ошибки, показывает сложные классы. Самый популярный плагин для Intellij IDEA. ▫️SonarLint и FindBugs ищут возможные ошибки, уязвимости, проверяют код на несколько тысяч ошибочных паттернов. ▫️CodeMR замеряет атрибуты качества кода — связность, сложность и т.д. Считает метрики, рисует картинки, показывает проблемные места с точки зрения дизайна. ▫️PMD ищет ошибочные паттерны в разных категориях — дизайн, кодстайл, производительность. Не знаю, почему этот плагин попадает во все списки анализаторов, у него достаточно скудный список правил по сравнению с аналогами. 2️⃣ Во время сборки. Анализ редко делают в процессе сборки, но такая опция доступна — с помощью maven или gradle плагинов: Checkstyle Plugin, PMD Plugin. 3️⃣ На этапах CI/CD. Можно запускать периодически или после определённых событий: создание пул-реквеста, слияние ветки. Результаты могут иметь рекомендательный характер, а могут не пропускать дальше по CI. Конкретных инструментов много, как платных, так и бесплатных. Самый популярный - SonarQube. Метрики качества не считает, но проверяет на гигантское количество ошибочных паттернов и интегрируется с плагином в IDE. JArchitect менее распространён и стоит дороже. Но и функций больше — метрики качества и красивые графики. Статический анализ проводят в большинстве проектов. Обычно это проверка форматирования и поиск частых ошибок. Конкретные метрики считаются редко. И зря, ведь по ним можно объективно оценить: 🔸Текущее состояние кода 🔸Развитие системы от релиза к релизу 🔸Необходимость рефакторинга 🔸Проблемные места системы

Как на вашем проекте проверяется качество кода?
Anonymous voting

Статический анализ кода, часть 1. Основные метрики Главная цель принципов разработки и паттернов проектирования — снизить стоимость разработки. Хорошим считается код, который легко: 🔸читать 🔸менять 🔸тестировать 🔸переиспользовать Простота - субъективное понятие. Разработчику, который в проекте со дня основания, легко ориентироваться в коде и исправлять ошибки. Джуниор, который недавно пришёл и получил первое задание, вряд ли с ним согласится. К счастью, есть объективные показатели качества кода, которые можно отслеживать и анализировать. Их получают с помощью статического анализа на основе исходного и байт-кода. Базовых метрик больше 50, и обычно они группируются в 4 категории: 1️⃣ Связность (Cohesion) Показывает, насколько сильно внутренние элементы взаимодействуют друг с другом, насколько сфокусирован класс. В классе с низкой связностью много методов, которые мало взаимодействуют между собой:
class Программист {
   void написатьКод()
   void помытьПосуду()
   void погладитьКота()
}
Идеальная сущность с точки зрения Cohesion - лямбда-выражение. Их легко читать, тестировать и переиспользовать. 2️⃣ Связанность (Coupling) Показывает, как одна сущность взаимодействует с другими. Класс А связан с классом Б, если в классе А ▫️Поля класса Б ▫️Вызов методов класса Б ▫️Локальные переменные класса Б ▫️Если класс А - подкласс Б В большинстве проектов есть модуль base или common - часто он является примером сильной связанности. Менять такой модуль - всегда большой риск. 3️⃣ Сложность (Complexity) На этот показатель влияет: ▪️Сколько сущностей взаимодействуют ▪️Количество операций в методе ▪️Глубина наследования ▪️Количество ветвлений и возможных состояний Показатель сложности часто идёт рука об руку с размером, но не всегда. Сложный метод может быть небольшим по размеру, но скрывать внутри себя десятки вариантов развития событий:
public void check(long id) {
  dao.get(id).findProcessor()
  .getAccount().checkBalance();
}

4️⃣ Размер (Size) Большие сущности сложно поддерживать. В этой категории много метрик, например, количество: 🔹Полей 🔹Методов 🔹Статических методов 🔹Подклассов 🔹Связанных библиотек А теперь ответы на вопросы перед постом: ✅ Если класс А часто использует класс Б, то это признак высокой связанности. Связанность (coupling) характеризует внешние отношения между сущностями. Связность (cohesion) - про внутреннюю структуру самой сущности. ✅ На сложность влияет количество ветвлений и глубина наследования. Остальные характеристики относятся к категории "размер".

Что из этого напрямую влияет на показатель "сложность кода" (Complexity)?
Anonymous voting

Если внутри класса А часто используется класс Б, это
Anonymous voting

Intellij IDEA: комментарии TODO Часто встречаются ситуации, когда нужно запомнить место в коде: 🔸Внести изменения по задаче. 🔸Отметить непокрытый тестами код. 🔸Обсудить логику с коллегой. 🔸Сделать рефакторинг метода, не относящегося к задаче. Для таких случаев в IDEA есть специальный тип комментариев. Он начинается со слов TODO и выглядит так:
// TODO добавить тесты

Такие комментариии будут отображаться в окне TODO внизу экрана. Через него можно перейти в нужное место кода в один клик. Открыть список можно через ▫️Alt+6 ▫️View→Tool Windows→TODO Помимо стандартных TODO и FIXME можно добавить свои метки, например, OPTIMIZE, ASK, TEST. Сделать это можно в File →Settings→ Editor→ TODO.

Функциональные интерфейсы, часть 2. Best practices. В части 1 был обзор функциональных интерфейсов (ФИ), а в этом посте — 4 рекомендации по их использованию. 1️⃣ Не реализуйте ФИ через анонимные классы. Используйте лямбда-выражения и ссылки на методы. Это короче и понятнее. ✅ Runnable r=() -> … Runnable r=new Runnable{ @Override public void run(){…} } 2️⃣ Определите сценарии использования ФИ. ФИ — это интерфейс, но с одним абстрактным методом. В него можно добавить сколько угодно методов с реализацией — дефолтных, приватных и статических. Один ФИ может расширять другой ФИ. Класс может реализовать ФИ через implements. Чтобы код был простым и понятным, нужно разграничивать его компоненты: 🔸Цель обычного интерфейса - обозначить набор методов для будущих классов. 🔸Цель ФИ — передать набор инструкций через лямбды и ссылки на методы. Один метод в ФИ - оптимальный вариант. Но есть случаи, когда дополнительные методы уместны, так как тесно связаны с самим интерфейсом. Пример: интерфейс Predicate. Несмотря на то, что он функциональный, в нём есть 4 метода с заданной реализацией: and, or, isEqual и negate. 3️⃣ Используйте аннотацию FunctionalInterface. Она не обязательна, но облегчает чтение кода. 4️⃣ Если используете ФИ как аргумент, отражайте тип ФИ в названии метода. Пример: в классе 2 метода с одним именем и разными типами аргументов:
void adapt(Callable)
void adapt(Supplier)

Этот код компилируется, но у него 2 недостатка: ▪️Чтобы понять разницу между методами нужно читать код или документацию. ▪️В качестве аргумента нельзя передать лямбда-выражение, т.к оно подходит под оба типа:
❌ adapt(str->print(str))

Чтобы избежать этих проблем, используйте разные имена для методов. Хороший пример — класс CompletableFuture для многоэтапных вычислений. В его методах легко ориентироваться благодаря удачным названиям: ▫️thenAccept(Consumer) ▫️thenApply(Function) ▫️thenRun(Runnable)

Сколько методов может быть в функциональном интерфейсе?
Anonymous voting

Может ли класс реализовать функциональный интерфейс?
Anonymous voting

Функциональные интерфейсы, часть 1. Java 8 добавила много возможностей писать короткий и выразительный код. Одна из них — функциональный интерфейс (ФИ). Интерфейс считается функциональным, если у него только один абстрактный метод. Это единственное требование, даже аннотация FunctionalInterface необязательна. Например, у интерфейса Comparable всего один метод, по определению он функциональный, но аннотации у него нет. Во всём остальном ФИ - это обычный интерфейс. У метода можно объявлять исключения и использовать любые типы параметров:
@FunctionalInterface
public interface Archiver{
    void archive(String file) 
    throws FileNotFoundEx;
}

Экземплярами ФИ могут быть: 🔸Лямбда-выражение 🔸Ссылка на метод 🔸Ссылка на конструктор Для большинства задач подойдут стандартные интерфейсы из пакета java.util.function. Всего их 43, но можно выделить 5 групп: 1️⃣ Consumer (потребитель) Метод принимает один параметр и ничего не возвращает.
Consumer<String> c = 
   System.out::println;

2️⃣ Supplier (поставщик) Ничего не принимает, но возвращает значение.
Supplier<List> s = 
   ArrayList::new;

3️⃣ Function Принимает один параметр, возвращает одно значение:
Function<String,Long> map = 
   s -> Long.valueOf(s);

4️⃣ UnaryOperator Метод принимает один параметр и возвращает значение того же типа:
UnaryOperator<Integer> inc = 
   i -> i+1;

5️⃣ Predicate Принимает аргумент и возвращает boolean значение.
Predicate<String> filter = 
  s -> !s.isEmpty() 
    && !s.contains("q");

У этих ФИ есть удобные вариации: 🔹BiConsumer, BiFunction, BiPredicate, BinaryOperator принимают два аргумента:
BiConsumer<Integer,Integer> b = 
   (x,y) -> println(x+y);

🔹LongFunction, LongSupplier , ToLongFunction и т.д позволяют не прописывать типы аргументов или выходных значений:
LongFunction<String> to = 
   Long::toString;

Ответ на вопрос перед постом: Интерфейс становится функциональным если в нём есть один абстрактный метод. Все остальные свойства у него такие же, как у обычного интерфейса. Аннотация FunctionalInterface не обязательна, но желательна для понимания кода.

Есть ли у Вас в проекте свои функциональные интерфейсы?
Anonymous voting

Какие утверждения про функциональный интерфейс (ФИ) верны?
Anonymous voting

HeadHunter: 3 совета по поиску вакансий. 1️⃣ Не пользуйтесь фильтрами. Фильтрация скрывает вакансии, у которых параметры не выставлены или выставлены неверно: 🔸У 10% вакансий выставлен неподходящий опыт работы. Например, в Спб для Senior разработчиков есть 14 вакансий с тегом "опыт не требуется" или "1-3 года". 🔸Адрес стоит только у 53% вакансий. Иногда у компании есть несколько зданий в разных районах города, а указан адрес только одного из них. 🔸Уровень заработной платы указан в 17% вакансий. Это слабый ориентир, реальный диапазон зарплат часто шире указанного. Оффер зависит от опыта, соответствия проекту и наличию других кандидатов. 2️⃣ Пробуйте разные запросы в строке поиска. Границы Junior/Middle, Middle/Senior, Senior/Lead нечёткие, поэтому имеет смысл откликнуться на вакансии уровнем выше или ниже желаемой должности. Некоторые компании не акцентируют внимание на иерархии и называют все вакансии Java Developer. Технический специалист смотрит резюме и соотносит его с задачами проекта. Если Вы интересный кандидат, то без проблем получите подходящую должность и зарплату. Если Вы чётко уверены в своём уровне, пишите желаемую позицию на разных языках: Senior java / старший java Junior java / младший java 3️⃣ Исключите неподходящие варианты c помощью NOT. Это сокращает количество вариантов в 3-4 раза. Пример для бэкэнд java разработчика: java NOT QA NOT Android NOT Junior NOT Архитектор NOT DevOps

Технологии в вакансиях HeadHunter. Позиция: Java-разработчик Город: Санкт-Петербург Вакансий: 309 Собрала статистику вакансий HeadHunter для разработчиков с разным уровнем опыта. В списке указана технология и % упоминания в вакансиях. Это значит, что технология находится либо в требованиях, либо в описании проекта. Иногда категории объединены, а в скобках указаны самые распространенные варианты. Списки получились очень скучные, но хорошо отражают стек большинства java проектов🧐 Разработчики без опыта: 60▫️SQL (PostgreSQL, Oracle) 50▫️Spring (MVC, Boot, Security, Data) 45▫️Hibernate 40▫️Git 30▫️Maven 25▫️Apache Tomcat 25▫️Docker 20▫️Linux 15▫️Jenkins Опыт от года до 3х лет: 66🔸SQL 61🔸Spring (MVC, Boot, Security, Data, Cloud) 60🔸Git 34🔸Maven 34🔸Docker 30🔸Hibernate 21🔸Jenkins 17🔸Linux 17🔸Big Data (Hadoop) 17🔸Kotlin 11🔸Cloud платформы (AWS, GCP) Опыт от 3х до 6 лет: 69▪️SQL 67▪️Spring (MVC, Boot, Security, Data, Cloud) 40▪️Git 37▪️Docker 28▪️Maven 26▪️Hibernate 25▪️Apache Kafka 23▪️Kubernetes 21▪️Kotlin 18▪️jenkins 17▪️Linux 17▪️Cloud провайдеры 16▪️noSql (Redis, MongoDB, Cassandra, CouchBase) Опыт более 6 лет: 65🔹SQL 59🔹Spring (Boot, Data, Cloud) 35🔹noSql (Redis, MongoDB, Cassandra, CouchBase) 35🔹Big Data (Hadoop) 35🔹Docker 35🔹Cloud провайдеры (AWS, GCP) 29🔹Apache Kafka 24🔹Kotlin 24🔹Git 24🔹ElasticSearch 24🔹RabbitMQ 18🔹Maven 18🔹ELK 18🔹Kubernetes 12🔹SAP

Интерфейсы, часть 3: различия с абстрактным классом. Отличия интерфейса и абстрактного класса — популярный вопрос на собеседовании. Во времена java 7 ответ был простой: «В интерфейсе нет реализаций методов». В java 9 в интерфейс можно добавить приватные, статические и дефолтные методы с готовой реализацией. Это сближает интерфейсы с абстрактными классами. ❓В чём теперь разница интерфейса и абстрактного класса? Сравним по нескольким критериям: 1️⃣ Абстрактный класс. Можно добавить: ▪️Конструкторы. ▪️Реализацию экземплярных методов. ▪️Нестатические поля. ▪️private static поля. ▪️Модификаторы final, synchronized, protected. 🔨Использование: Класс реализует не больше одного абстрактного класса через ключевое слово extends. В имени часто содержится Abstract, Template, Base. ✴️ Назначение: Шаблон класса. Вспомогательная структура, чтобы не дублировать код в классах одной иерархии. ⭐️Репутация: Средняя. Абстрактный класс сокращает объем необходимого кода, когда иерархия классов конечна или известна заранее. Большое количество абстрактных классов считается анти-паттерном, у такой системы плохая читаемость, и в неё сложно вносить изменения. 2️⃣ Интерфейс ▪️Только статические поля. ▪️Методам с реализацией недоступны экземплярные поля, поэтому их возможности слабее, чем у абстрактных методов. 🔨Использование: Класс реализует несколько интерфейсов через ключевое слово implements. 5 лет назад интерфейсам было модно добавлять суффикс able: Iterable, Comparable. Норма сегодняшнего дня - называть интерфейс по тем же правилам, что и класс. ✴️ Назначение: Описывает методы для верхнеуровнего взаимодействия с классом, модулем или системой. ⭐️Репутация: Высокая. Широко используется в большинстве паттернов GoF, принципах SOLID. Поддерживает инкапсуляцию.

Что выведется в консоль?
Anonymous voting

Что выведется в консоль? Обратите внимание, интерфейс В теперь расширяет интерфейс А

Интерфейсы, часть 2: методы по умолчанию. В java 8 появилась новая возможность интерфейсов - методы с заданной реализацией:
interface Adapter {
   default int get() {…}
}
Класс, который реализует интерфейс, переопределяет такой метод при необходимости. ❓Зачем нужны такие методы? 1️⃣ Облегчить изменения API Во времена java 7 интерфейсы содержали только определения методов:
interface Collection<Т> {
   void add(Т);
   Т get();
}
Чтобы добавить, удалить или поменять сигнатуру метода нужно одновременно поменять код со стороны пользователей интерфейса и во всех реализациях. В рамках одного проекта это несложно, но для библиотек это сложная задача. Пользователи могут столкнутся с проблемами совместимости при переходе на новую версию. Задача дефолтных методов - сгладить этот процесс и предоставить приемлемую или временную альтернативу. 2️⃣ Вспомогательные методы Те методы, которые не входят в прямую функциональность интерфейса - методы для мониторинга, логгирования и т.д. Используйте с осторожностью, этот приём может нарушать принцип Interface segregation. 3️⃣ Комбинации базовых методов В интерфейсе объявляется минимально необходимый набор методов, а некоторые методы являются просто их комбинациями. Мы обсуждали этот случай в прошлом посте. Такой "удобный" метод можно добавить в интерфейс как статический. Статические методы вызываются через имя интерфейса и недоступны у экземпляров. Если это неудобно, оформите метод как метод по умолчанию. Пример: интерфейс Comparator. Основная функция — сравнение объектов через метод compare, индивидуальный для каждого класса. Цепочка из 2 компараторов - это 2 вызова compare и объединение результатов. Логика всегда одинакова, и нет смысла дублировать её в каждом подклассе:
default Comparator<T> thenComparing(Comparator) {…};

Что если класс реализует 2 интерфейса с методами по умолчанию? Для разрешения конфликта используются 2 правила: 1️⃣ Если в классе переопределён метод по умолчанию — используется метод класса. 2️⃣ В иерархии интерфейсов используется метод наследника:
interface Child extends Parent
Если класс реализует интерфейс Child, то будет использоваться дефолтный метод интерфейса Child. В опросе перед постом ни одно правило не подходит, поэтому будет ошибка компиляции. Чтобы разрешить конфликт, класс должен явно реализовать метод get();

Что выведется на консоль?
Anonymous voting