5 советов по написанию действительно хороших юнит-тестов
1) Тестируйте поведение, а не реализацию
Пишите тесты, которые проверяют, что код должен делать, а не как именно он это делает внутри.
Потому что внутренние методы могут изменяться, но ожидаемое поведение должно оставаться стабильным.
2) Давайте тестам имена как документации, а не как коду
Пишите имена тестовых методов так, как будто они рассказывают историю - - чётко, конкретно и читаемо для человека.
Это облегчает чтение отчетов о тестах — не нужно углубляться в код.
3) Пишите тест до исправления ошибки
Когда вы обнаруживаете ошибку, сначала напишите тест, который воспроизводит её, прежде чем исправить код.
Это докажет, что ошибка действительно существует (а не только в вашей голове).
Допустим, вы обнаружили, что дни рождения в високосный год крашат вашу систему.
4) Используйте тесты с параметрами для граничных случаев
Вместо того чтобы писать много похожих тестов, пробегитесь по набору входных данных с помощью параметризованных тестов.
Это предотвращает беспорядок от копипаста и делает набор тестов более чистым.
5) Проверяйте только важные моменты, а не все поля
Сфокусируйтесь на утверждениях, касающихся важных бизнес-результатов, а не на каждом поле объекта.
Это помогает тестам оставаться стабильными, даже когда несущественные детали изменяются.
👉 Java Portal
1) Тестируйте поведение, а не реализацию
Пишите тесты, которые проверяют, что код должен делать, а не как именно он это делает внутри.
Потому что внутренние методы могут изменяться, но ожидаемое поведение должно оставаться стабильным.
2) Давайте тестам имена как документации, а не как коду
Пишите имена тестовых методов так, как будто они рассказывают историю - - чётко, конкретно и читаемо для человека.
Это облегчает чтение отчетов о тестах — не нужно углубляться в код.
3) Пишите тест до исправления ошибки
Когда вы обнаруживаете ошибку, сначала напишите тест, который воспроизводит её, прежде чем исправить код.
Это докажет, что ошибка действительно существует (а не только в вашей голове).
Допустим, вы обнаружили, что дни рождения в високосный год крашат вашу систему.
4) Используйте тесты с параметрами для граничных случаев
Вместо того чтобы писать много похожих тестов, пробегитесь по набору входных данных с помощью параметризованных тестов.
Это предотвращает беспорядок от копипаста и делает набор тестов более чистым.
5) Проверяйте только важные моменты, а не все поля
Сфокусируйтесь на утверждениях, касающихся важных бизнес-результатов, а не на каждом поле объекта.
Это помогает тестам оставаться стабильными, даже когда несущественные детали изменяются.
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10❤7
7 ключевых сложностей по времени выполнения, которые нужно знать для собеседований по программированию:
1. O(1) — Константное время
- Время выполнения не зависит от размера входных данных.
-📌 Пример: доступ к элементу массива по индексу.
2. O(log n) — Логарифмическое время
- Время выполнения растёт медленно по мере увеличения входных данных. Обычно встречается в алгоритмах, делящих задачу пополам на каждом шаге.
-📌 Пример: бинарный поиск в отсортированном массиве.
3. O(n) — Линейное время
- Время выполнения растёт пропорционально объёму входных данных.
-📌 Пример: поиск элемента в массиве перебором.
4. O(n log n) — Линеаритмическое время
- Время выполнения немного быстрее, чем квадратичное, и включает логарифмическое количество операций на каждый элемент.
-📌 Пример: сортировка массива алгоритмами быстрой сортировки (quick sort) или слиянием (merge sort).
5. O(n²) — Квадратичное время
- Время выполнения растёт пропорционально квадрату входных данных.
-📌 Пример: сортировка пузырьком, где сравниваются и при необходимости меняются местами все пары элементов.
6. O(2ⁿ) — Экспоненциальное время
- Время выполнения удваивается с каждым новым элементом входа. Такие алгоритмы быстро становятся неэффективными при больших объёмах данных.
-📌 Пример: генерация всех подмножеств множества.
7. O(n!) — Факториальное время
- Время выполнения растёт как факториал от количества входных данных.
-📌 Пример: генерация всех перестановок множества.
👉 Java Portal
1. O(1) — Константное время
- Время выполнения не зависит от размера входных данных.
-
2. O(log n) — Логарифмическое время
- Время выполнения растёт медленно по мере увеличения входных данных. Обычно встречается в алгоритмах, делящих задачу пополам на каждом шаге.
-
3. O(n) — Линейное время
- Время выполнения растёт пропорционально объёму входных данных.
-
4. O(n log n) — Линеаритмическое время
- Время выполнения немного быстрее, чем квадратичное, и включает логарифмическое количество операций на каждый элемент.
-
5. O(n²) — Квадратичное время
- Время выполнения растёт пропорционально квадрату входных данных.
-
6. O(2ⁿ) — Экспоненциальное время
- Время выполнения удваивается с каждым новым элементом входа. Такие алгоритмы быстро становятся неэффективными при больших объёмах данных.
-
7. O(n!) — Факториальное время
- Время выполнения растёт как факториал от количества входных данных.
-
Please open Telegram to view this post
VIEW IN TELEGRAM
👍16❤2🤔1
Функциональное программирование в Java с использованием Streams и лямбд:
Streams обрабатывают фильтрацию, сортировку и свёртку данных, а лямбды упрощают определение функций. В Spring они используются для построения реактивных API, а в задачах алгоритмического программирования — для оптимизации обработки данных.
Выше приведён пример REST-эндпойнта на Spring, фильтрующего пользователей, и функции в стиле олимпиадного программирования для поиска лидеров по очкам.
👉 Java Portal
Streams обрабатывают фильтрацию, сортировку и свёртку данных, а лямбды упрощают определение функций. В Spring они используются для построения реактивных API, а в задачах алгоритмического программирования — для оптимизации обработки данных.
Выше приведён пример REST-эндпойнта на Spring, фильтрующего пользователей, и функции в стиле олимпиадного программирования для поиска лидеров по очкам.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤10😁4👍3
Как вернуть результат в виде Map из запроса JPA или Hibernate
⏩ Читать подробнее
👉 Java Portal | #cтатья
Please open Telegram to view this post
VIEW IN TELEGRAM
❤6👍4🌭2
This media is not supported in your browser
VIEW IN TELEGRAM
Необходимый репозиторий с сотнями бесплатных API для практики программирования и создания проектов.
Обновляется еженедельно и разделён по темам😇
⇢ http://github.com/public-apis-dev/public-apis
👉 Java Portal
Обновляется еженедельно и разделён по темам
⇢ http://github.com/public-apis-dev/public-apis
Please open Telegram to view this post
VIEW IN TELEGRAM
❤7👍5
This media is not supported in your browser
VIEW IN TELEGRAM
Этот репозиторий представляет собой целую энциклопедию для Java-разработчиков. Автор структурировал материал от основ языка до продвинутых тем
Он охватывает основы, ООП, многопоточность, сборку мусора, коллекции и другие важные темы
Проект имеет полезные разделы с примерами кода: от классических паттернов вроде Singleton до задач на динамическое программирование. Для тех, кто готовится к собеседованиям, есть подборка LeetCode-шаблонов и реальных interview-задач.😡
👉 Java Portal
Он охватывает основы, ООП, многопоточность, сборку мусора, коллекции и другие важные темы
Проект имеет полезные разделы с примерами кода: от классических паттернов вроде Singleton до задач на динамическое программирование. Для тех, кто готовится к собеседованиям, есть подборка LeetCode-шаблонов и реальных interview-задач.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤10👍5🔥4
8 концепций проектирования систем, объясненных в одной диаграмме
👉 Java Portal
1. Availability with Load Balancers
Использование балансировщиков (Layer 7) для распределения трафика между несколькими экземплярами сервисов (например, Comment Service, Post Service).
Повышает отказоустойчивость и доступность.
2. Latency with CDNs
CDN кэширует контент ближе к пользователю, уменьшая задержки.
Первый запрос идёт на origin-сервер, второй — уже из кэша CDN.
3. Scalability with Replication
Данные реплицируются между несколькими узлами.
Увеличивает доступность и масштабируемость систем.
4. Durability with Transaction Logs
Система сохраняет изменения в журнал транзакций перед применением.
В случае сбоя состояние может быть восстановлено из лога.
5. Consistency with Eventual Consistency
Записи и чтения могут идти в разные источники.
Система приходит к согласованному состоянию со временем (eventually).
6. Modularity with Loose Coupling and High Cohesion
Модули имеют чёткие границы и хорошо организованы внутри.
Улучшает читаемость, повторное использование и сопровождение кода.
7. Configurability with Configuration-as-Code
Инфраструктура управляется через код (например, Terraform, Ansible).
Контроль версий, автоматизация и повторяемость.
8. Resiliency with Message Queues
Задания помещаются в очередь, откуда обрабатываются несколькими потребителями.
Улучшает отказоустойчивость и масштабируемость обработки.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8❤4
Метод
Если тебе нужно выполнить сложную выборку (например, последнюю запись на дату) — не бойся использовать
⏩ Читать подробнее
👉 Java Portal | #cтатья
createNativeQuery
из JPA EntityManager
Если тебе нужно выполнить сложную выборку (например, последнюю запись на дату) — не бойся использовать
createNativeQuery
. Нативный SQL в JPA — это мощный инструмент, особенно когда JPQL ограниченPlease open Telegram to view this post
VIEW IN TELEGRAM
👍7👀2
Виртуальные потоки с Project Loom
Традиционные потоки в Java мощный, но тяжёлый механизм, который ограничивает масштабируемость в высоконагруженных многопоточных приложениях.
С появлением Project Loom вводится концепция виртуальных потоков т.е. лёгких потоков, управляемых самой JVM, которые упрощают работу с конкурентностью и делают её более эффективной.
Виртуальные потоки позволяют запускать тысячи параллельных задач с минимальными накладными расходами, при этом сохраняя простой, блокирующий стиль написания кода без ущерба для производительности.😇
👉 Java Portal
Традиционные потоки в Java мощный, но тяжёлый механизм, который ограничивает масштабируемость в высоконагруженных многопоточных приложениях.
С появлением Project Loom вводится концепция виртуальных потоков т.е. лёгких потоков, управляемых самой JVM, которые упрощают работу с конкурентностью и делают её более эффективной.
Виртуальные потоки позволяют запускать тысячи параллельных задач с минимальными накладными расходами, при этом сохраняя простой, блокирующий стиль написания кода без ущерба для производительности.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤8
Гайд как откатить последний коммит в Git (пошагово)
① Если ещё не делал
Оставить изменения в
Полностью удалить изменения:
Отредактировать последний коммит (сообщение или содержимое):
② Если уже сделал
Используй
(Если возникнут конфликты — их придётся разрулить вручную.)
Получи хеш нужного коммита с помощью:
★ Уровень «эксперт»:
Используй
Можно менять порядок, объединять, править или удалять коммиты.
После изменений —
Важно: Делай
или вся команда согласована и не против переписывания истории.
👉 Java Portal
① Если ещё не делал
push
:Оставить изменения в
staging
(индексе):git reset --soft HEAD~1
Полностью удалить изменения:
git reset --hard HEAD~1
Отредактировать последний коммит (сообщение или содержимое):
git commit --amend -m "Исправленное сообщение"
② Если уже сделал
push
:Используй
git revert <хеш>
, чтобы создать новый коммит, отменяющий изменения предыдущего.(Если возникнут конфликты — их придётся разрулить вручную.)
Получи хеш нужного коммита с помощью:
git log
★ Уровень «эксперт»:
Используй
git rebase -i
для редактирования локального коммит-истории:Можно менять порядок, объединять, править или удалять коммиты.
После изменений —
git push --force-with-lease
Важно: Делай
rebase
и push --force-with-lease
только если ты один работаешь в веткеили вся команда согласована и не против переписывания истории.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤8👍4
Пример проекта, демонстрирующий, как использовать GraphQL вместе с Spring Boot.
В репозитории показано:
🔸 как настроить GraphQL в Spring-приложении,
🔸 как описывать схемы, резолверы и DTO,
🔸 как работать с базой данных (MongoDB),
🔸 и как совмещать GraphQL с REST-контроллерами.
Подойдёт, если ты хочешь разобраться, как устроен GraphQL в экосистеме Spring или ищешь базу для своего pet-проекта.
👉 Java Portal
В репозитории показано:
Подойдёт, если ты хочешь разобраться, как устроен GraphQL в экосистеме Spring или ищешь базу для своего pet-проекта.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5👍3
Как выдержать нагрузку в 10 000 одновременных пользователей
1. Поставь балансировщик нагрузки (Load Balancer) спереди
- Распределяй трафик между несколькими backend-серверами.
- Инструменты:
2. Масштабируй горизонтально
- Один мощный сервер — нет.
- Используй несколько небольших stateless-серверов за LB.
3. Пиши stateless-сервисы
- Не храни сессии или состояние в оперативке.
- Используй
4. Используй connection pooling
- Базы «захлебываются» от 10 000 одновременных подключений.
- Ограничь число подключений к БД с каждого сервера через пул (например,
5. Активно кэшируй
Кешировать можно:
- Static files → CDN
- DB-запросы → Redis
- HTML-фрагменты → Edge cache
6. Используй read-replicas
- Разделяй чтение и запись, чтобы масштабировать чтение из базы.
7. Async и очереди (Queued Workloads)
- Переноси тяжёлые задачи (почта, видео и т.д.) в background jobs.
- Используй очереди:
8. Включи авто-масштабирование
- Используй инфраструктуру, способную масштабироваться под нагрузку:
9. WebSocket / Реалтайм? Используй gateway-сервисы
- Запускай WebSocket-шлюзы (например,
- Масштабируй через sticky-сессии или pub/sub (
10. Мониторь всё
- Отслеживай
- Инструменты:
👉 Java Portal
1. Поставь балансировщик нагрузки (Load Balancer) спереди
- Распределяй трафик между несколькими backend-серверами.
- Инструменты:
NGINX
, HAProxy
, AWS ELB
.2. Масштабируй горизонтально
- Один мощный сервер — нет.
- Используй несколько небольших stateless-серверов за LB.
3. Пиши stateless-сервисы
- Не храни сессии или состояние в оперативке.
- Используй
Redis
/ Memcached
или JWT
для сессий и авторизации.4. Используй connection pooling
- Базы «захлебываются» от 10 000 одновременных подключений.
- Ограничь число подключений к БД с каждого сервера через пул (например,
HikariCP
).5. Активно кэшируй
Кешировать можно:
- Static files → CDN
- DB-запросы → Redis
- HTML-фрагменты → Edge cache
6. Используй read-replicas
- Разделяй чтение и запись, чтобы масштабировать чтение из базы.
7. Async и очереди (Queued Workloads)
- Переноси тяжёлые задачи (почта, видео и т.д.) в background jobs.
- Используй очереди:
SQS
, RabbitMQ
, Kafka
.8. Включи авто-масштабирование
- Используй инфраструктуру, способную масштабироваться под нагрузку:
AWS EC2 + ASG
, GCP GKE
и т.д.9. WebSocket / Реалтайм? Используй gateway-сервисы
- Запускай WebSocket-шлюзы (например,
Socket.io
за LB). - Масштабируй через sticky-сессии или pub/sub (
Redis
, Kafka
).10. Мониторь всё
- Отслеживай
CPU
, память
, задержки
, глубину очередей
. - Инструменты:
Prometheus + Grafana
, Datadog
, New Relic
.Please open Telegram to view this post
VIEW IN TELEGRAM
❤8🔥7👍2👀1
Выделение памяти в Java
В Java память по умолчанию выделяется в куче с помощью new.
Это просто, управляется сборщиком мусора и подходит для большинства приложений.
Но если нужны высокая производительность или низкие задержки, можно использовать off-heap память через
Такой подход выделяет память вне кучи, снижает нагрузку на GC и повышает эффективность при работе с большими или долго живущими данными.
Off-heap даёт больше контроля и производительности,
но требует аккуратного управления ресурсами,
так как такая память не очищается автоматически, в отличие от памяти в куче.
👉 Java Portal
В Java память по умолчанию выделяется в куче с помощью new.
Это просто, управляется сборщиком мусора и подходит для большинства приложений.
Но если нужны высокая производительность или низкие задержки, можно использовать off-heap память через
ByteBuffer.allocateDirect()
. Такой подход выделяет память вне кучи, снижает нагрузку на GC и повышает эффективность при работе с большими или долго живущими данными.
Off-heap даёт больше контроля и производительности,
но требует аккуратного управления ресурсами,
так как такая память не очищается автоматически, в отличие от памяти в куче.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9❤2🔥2
Вопросы на собеседование по Spring Boot
1. Как Spring Boot определяет, какие бины создавать при автоконфигурации?
2. Для чего используется аннотация
3. Как реализовать пользовательскую валидацию в Spring Boot с помощью аннотаций?
4. Как
5. В чём разница между
6. Как вынести конфигурацию Spring Boot для разных окружений (environments)?
7. Что такое
👉 Java Portal
1. Как Spring Boot определяет, какие бины создавать при автоконфигурации?
2. Для чего используется аннотация
@ConditionalOnProperty
?3. Как реализовать пользовательскую валидацию в Spring Boot с помощью аннотаций?
4. Как
@Transactional
обрабатывает вложенные транзакции?5. В чём разница между
application.properties
и application.yml
в Spring Boot?6. Как вынести конфигурацию Spring Boot для разных окружений (environments)?
7. Что такое
WebClient
в Spring Boot и чем он отличается от RestTemplate
?Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Сохраняем себе: Jimmer
это иммутабельный ORM, заточенный под работу с графами объектов, а не отдельными сущностями.
🔹 Авто-генерация DTO
🔹 Без N+1 (batch fetch из коробки)
🔹 Умные SQL без лишних JOIN'ов
🔹 DSL с type-safety
🔹 GraphQL + TypeScript-генерация
🔹 Кеширование (включая Redis)
🔹 Работает через APT/KSP
⇢ https://github.com/babyfish-ct/jimmer
👉 Java Portal
это иммутабельный ORM, заточенный под работу с графами объектов, а не отдельными сущностями.
⇢ https://github.com/babyfish-ct/jimmer
Please open Telegram to view this post
VIEW IN TELEGRAM
👀5❤3
Слышал когда-нибудь про объект, который отказывается умирать?
В Java можно «воскресить» объект во время сборки мусора с помощью метода finalize(). Но это — рискованная практика, и сам метод уже помечен как устаревший.
Этот код демонстрирует поведение метода
👉 Java Portal
В Java можно «воскресить» объект во время сборки мусора с помощью метода finalize(). Но это — рискованная практика, и сам метод уже помечен как устаревший.
Этот код демонстрирует поведение метода
finalize()
в Java — он вызывается только один раз перед удалением объекта сборщиком мусора. В первой попытке объект «воскрешается» внутри finalize
, но при повторной попытке finalize
уже не вызывается, и объект действительно удаляется.Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🤔5❤2