Обновить
256K+

Java *

Объектно-ориентированный язык программирования

296,41
Рейтинг
Сначала показывать
Порог рейтинга

Прямая Web3-монетизация без посредников (Peer-to-Peer) для артистов на радио.

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

Задача была непростой. Нужно было объединить возможности мессенджера с его токеномикой и реализовать передачу медиаконтента (картинок, аудиофайлов, текстовых данных) на удаленный сервер в формате JSON. Для этого я написал серверную страницу на PHP, в которой реализовал весь необходимый API.

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

function isJpeg(string $data): bool
{
    return substr($data,0,2) === "\xFF\xD8";
}

function isMp3(string $data): bool
{
    if (substr($data,0,3)==="ID3") {
        return true;
    }

    return isset($data[1])
        &&
        ord($data[0])===0xFF
        &&
        (ord($data[1]) & 0xE0)===0xE0;
}

После получения данных нужно сразу определить что именно пришло - команда или файл:

if (preg_match('/^\/(help|bio|title|tracks|done)\b/i', $data))
{
    processCommand($db, $uuid, $data);
    exit;
}

if (isBase64($data))
{
    saveBinary($db, $uuid, $data);
    exit;
}

reply("Unknown command, please use /help.", false);

Описание профиля артиста и названия его треков передаются в текстовом виде используя специальный набор команд:

  • /help - Show this help

  • /bio text - Update artist biography

  • /tracks - Show info of all tracks

  • /title text - Update current track title

  • /pay amount - Pay for service

  • /done - Finalize current track

  • Send JPG image to update artist image

  • Send MP3 audio to update current track

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

  1. артист отправляет фото профиля

  2. артист отправляет описание профиля

  3. артист загружает трек

  4. артист отправляет описание трека

  5. артист выполняет оплату сервиса

  6. артист финализирует трек

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

МОНЕТИЗАЦИЯ

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

Таким образом, технология Web3 с использованием блокчейна позволяет оперативно выполнять оплату за предоставленный сервис без лишних трат и банковских процедур. При этом все транзакции становятся видны в блокчейне уже через несколько минут.

схема работы блокчейна
схема работы блокчейна

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

Таким образом, объединение двух разных сущностей, а именно интернет-радио с приложением для обмена сообщениями, является неким ноу-хау для оказания помощи в развитии молодых дарований. Лично для меня как для разработчика это отличный вызов и прекрасная возможность "пошевелить мозгами".

Если у вас появятся предложения, буду рад подискуссировать.

Теги:
0
Комментарии6

30 июня в 18:00 начнется  вебинар «Почему Java-разработчику следует брать на вооружение Quarkus». В прямом эфире рассмотрим ключевые преимущества Quarkus перед Spring Boot: родную сборку, малое потребление памяти и удобство разработки.

Создадим один и тот же REST-сервис на Spring Boot и на Quarkus, сравним время старта и затраты ресурсов.

Разберём настоящий случай из промышленной разработки. Вебинар будет полезен специалистам, которые хотят ускорить свои приложения и снизить счета за облако.

Содержание:

✅ Проблема долгого запуска и высокого потребления памяти в Spring Boot.

✅ Что такое Quarkus? Окружающая среда расширений, родная сборка.

✅ Живой код: создание REST-сервиса на Spring Boot и на Quarkus.

✅ Измерение времени запуска и потребления памяти.

✅ Как родная сборка ускоряет размещение в Kubernetes и снижает затраты.

✅ Настоящий случай из практики автора.

✅ Как продолжить изучение Quarkus.

🧑‍🎓 Спикер: Чвилёв Константин, эксперт в области разработки ПО

📆 Когда: 30 июня, 18:00–19:00 (Мск)

👉 Регистрация

Теги:
+3
Комментарии0

Представлено бесплатное десктопное приложение Streambert с открытым исходным кодом для ПК на Windows, macOS и Linux. Решение распространяется по лицензии GNU GPL v3.0. Главное преимущество Streambert — здесь совсем нет рекламы и трекеров. Разработчики подчёркивают, что приложение всегда будет бесплатным и не станет собирать личные данные пользователей.

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

Разработчики утверждают, что приложение обеспечивает более быструю потоковую передачу видео по сравнению с большинством браузерных кинотеатров и поддерживает многопоточную загрузку файлов. При этом Streambert не хранит и не распространяет защищённый авторским правом контент, программа лишь агрегирует ссылки с внешних источников и выступает в роли поисковика.

Теги:
+3
Комментарии2

Риски ИИ- генерируемого кода - качество, производительность, “УСПЕВАЮ ЛИ Я ЗА ТЕМПОМ” 

ИИ генерирует код быстрее, чем мы успеваем ловить его реальные проблемы.
В JPA/Hibernate это особенно больно: код компилируется, тесты зелёные — а внутри N+1 и лишние запросы. Veai проверяет такие гипотезы на фактах проекта прямо в IDE: семантические usages, реальные прогоны тестов, coverage, debugger, доступ к исходникам Hibernate.

Не “этот код, возможно, тормозит”, а проверка через запуск. Скорость растёт — контроль над качеством остаётся. Большой разбор продукта сделан в статье

Теги:
+4
Комментарии0

От падающего теста до правки: как General ведёт задачу в любимой IDE

Когда разработчик открывает AI-чат в IDE, он не думает категориями режимов. Он не формулирует задачу как «сначала Plan, потом Code, затем Test и Review» — он пишет проще:

Почини тест

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

Под этот сценарий в Veai сделан режим General: вы описываете цель обычными словами, а агент сам выбирает маршрут — проход по коду, планирование, тесты, ревью, отладка или подключение субагентов. Специализированные режимы (Ask, Code, Test, Plan, Review, Debug) остаются для случаев, когда вы хотите управлять процессом явно.

Почему ручной выбор режима мешает

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

Что происходит по шагам

На запрос «в сервисе оплаты падает тест, найди причину и почини» General в простом случае ведёт задачу сам:

  1. находит и запускает тест через IDE run configuration — в том же окружении, что и разработчик (SDK, профиль, переменные, модули), а не в собранном из терминала, которое может отличаться;

  2. читает стектрейс, открывает связанный production-код, при необходимости смотрит usages, warnings и inspections;

  3. вносит минимальную правку и перезапускает проверку: тест прошёл или упал — это факт из IDE, а не предположение модели.

Если стектрейса не хватает, агент опирается на отладчик (breakpoints, значения переменных, call tree), а если стектрейс уводит в библиотеку — открывает её код или декомпилированный класс через IDE, а не угадывает API по памяти модели.

Когда подключаются субагенты

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

Полностью исключить ошибки модели нельзя. Но General опирается не только на LLM, grep и RAG, а на JetBrains IDE как на источник проверяемых фактов: run configurations, SDK и classpath, структуру кода, usages и inspections, coverage, код зависимостей и ошибки компиляции так, как их видит IDE. Отсюда меньше галлюцинаций API и ситуаций «у агента прошло, а в IDE или CI падает».

Разницу можно измерить. 

Мы прогнали 8 enterprise-задач на Java/Spring через четыре агента на одной модели — Cursor, Claude Code, JetBrains Junie и Veai:

Контроль остаётся у разработчика

Даже когда агент ведёт задачу автономно, последнее слово за человеком: разработчик смотрит diff в окне Agent Changes и решает, что принять. Перед этим General может сам прогнать несколько субагентов-ревьюеров по своим изменениям и устранить критические проблемы ещё до того, как покажет результат человеку, — авторевью встроено в маршрут, а не остаётся отдельным ручным шагом. Идея не в том, чтобы убрать review, а в том, чтобы убрать лишнюю ручную маршрутизацию до него.

Установить Veai 5.12

Обратная связь — support@veai.ru и чат с командой.

Теги:
+9
Комментарии0

Вайб-кодинг на корпоративном контроле: как превращать хаос генерации в инженерную дисциплину

Приглашаем вас на совместный вебинар ITFB Group и компании Veai, посвящённый практике контролируемого применения ИИ в разработке.

Когда: 24 июня, 11:00
Где: онлайн

Ключевой вопрос: как использовать скорость вайб-кодинга, но при этом не допустить падения качества, потери управляемости и рисков безопасности?

О продукте

Veai — первый российский ИИ-агент, сочетающий высокую скорость генерации кода с жёстким контролем на основе формальных методов. На вебинаре мы на реальных примерах покажем, чем Veai отличается от Cursor, Copilot и других доступных на рынке решений.

Программа вебинара

Практическая демонстрация: работа агента на реальном коде — от постановки задачи до готового результата.

Сравнительный анализ: объективная оценка сильных и слабых сторон популярных ИИ-ассистентов.

Метрики и экономика: данные по экономии часов, ROI, доле принятого сгенерированного кода и росту тестового покрытия (до 80% с использованием символьного исполнения и data-flow анализа).

Работа с некомпилируемым кодом: агент автоматически выявляет и исправляет ошибки компиляции и предупреждения IDE, используя нативные инструменты без дополнительных вызовов.

Безопасность и архитектура: варианты развертывания (on‑premise, self‑hosting, VPC, SaaS), механизмы контроля доступа и встроенный SAST-движок, проверяющий каждую генерацию.

Спикеры

Константин Волков, менеджер по техническим решениям Veai.
Наталья Романова, директор по развитию ITFB Group.

Формат — открытая дискуссия. Вы сможете задать любые вопросы, включая самые сложные и нестандартные.

Кому будет полезно: ИТ-директорам, руководителям разработки, архитекторам и всем, кто внедряет или планирует внедрять ИИ-инструменты в корпоративную среду.

👉 Зарегистрироваться

Теги:
+4
Комментарии0

Продолжаем делиться докладами с прошедших конференций! На этот раз у нас тут доклад с Joker 2025 🔥

Тема: "Как компилятор видит код. Поиск уязвимостей на графах"

Посмотрели, как код превращается из исходного представления в графовое, чтобы ответить на вопрос: «Как компилятор видит код?». Прошлись по технологиям фронтенда — от AST и графов на его основе до карты вызовов — и посмотрели на их визуализацию.

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

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

Посмотреть можно тут:
- наш сайт
- VK Video
- Rutube
- YouTube

Теги:
+5
Комментарии0

Что посмотреть на неделе: брокеры сообщений, Kubernetes и ИИ‑агенты

Привет, Хабр. На этой неделе в OTUS пройдет серия бесплатных уроков для тех, кто работает с архитектурой, инфраструктурой, разработкой, аналитикой и ИИ‑инструментами.

Будет много практики: выбор брокера сообщений, деплой Java‑приложения в Kubernetes, мониторинг распределённых систем, создание AI‑ассистентов и интеграция ИИ‑агентов в рабочую разработку.

Все уроки бесплатно проводят преподаватели в рамках курсов. Можно прийти на один вебинар по своей задаче или собрать мини‑маршрут на неделю.

Архитектура и backend

  • 8 июня, 19:00. «RabbitMQ vs Kafka. Как выбрать подходящий брокер сообщений?». Записаться
    разберём, чем отличаются RabbitMQ и Kafka, в каких задачах они работают лучше и как выбрать брокер под архитектуру проекта.

  • 15 июня, 20:00. «Системы обмена сообщениями: RabbitMQ и Kafka». Записаться
    поговорим об устройстве систем обмена сообщениями и сценариях, где брокеры помогают строить устойчивые распределённые решения.

Инфраструктура и эксплуатация

  • 8 июня, 20:00. «Java в Kubernetes за 40 минут: как задеплоить приложение в Minikube». Записаться
    покажем, как подготовить Java‑приложение к запуску в Kubernetes и развернуть его локально через Minikube.

  • 10 июня, 20:00. «Мониторинг распределённых систем». Записаться
    разберём, как отслеживать состояние сложных систем, быстрее находить проблемы и не теряться в метриках, логах и алертах.

ИИ в рабочих процессах

  • 11 июня, 20:00. «Создаём ИИ‑ассистента для системного аналитика за 1 час». Записаться
    покажем, как ИИ может помогать аналитику в рабочих задачах: от обработки требований до подготовки артефактов.

  • 15 июня, 20:00. «Интеграция ИИ‑агентов в рабочую разработку: обвязка агента навыками и MCP». Записаться
    разберём, как расширять возможности ИИ‑агента с помощью навыков и MCP, чтобы он был полезен в реальном рабочем процессе.

  • 15 июня, 20:00. «Создаём AI‑ассистента и интегрируем его в Telegram». Записаться
    покажем, как собрать AI‑ассистента и подключить его к Telegram для пользовательских сценариев.

Команды и процессы

  • 11 июня, 20:00. «Внутри Scrum: как работают мастер, владелец и команда». Записаться
    разберём, как на практике распределяются роли в Scrum и почему процесс часто ломается не из‑за фреймворка, а из‑за его применения.

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

Теги:
+3
Комментарии0

Представлен открытый проект waylandcraft - это полнофункциональный композитор Wayland полностью интегрирован в мод Fabric для Minecraft Java 26.1.2.

«Запускайте приложения и открывайте окна прямо в вашем мире Minecraft. Перетаскивайте данные из одного окна в другое. Закрепите видеоплеер на вашем HUD. Выбор за вами. Важно: этот мод работает только под Linux! MacOS и Windows не поддерживаются», — пояснил автор проекта.

Теги:
Всего голосов 1: ↑1 и ↓0+1
Комментарии1

В предыдущих сериях был реализован простейший движок на основе HashMap, в которой сохраняются данные key -> value, и в принципе была открыта дорога для написания сервера и клиента для тестов. Но я решил добавить в Space работу с распределенными (XA) транзакциями.

Наличие такого механизма обязательно приведет к деградации производительности. Закономерно возникает вопрос: для чего это было сделано? Memifydb - это распределенная БД и она должна обеспечивать конкурентный доступ к данным обеспечивая их целостность. Что проку если она будет работать быстро, но её содержимое будет - хаос? Ведь деже при создании простого приложения для обработки данных в нескольких потоках используется synchronized в java (и пр. механизмы синхронизации).

Второй момент состоит в том что я всегда работал с транзакциями на стороне клиента, т.е. работал с менеджером транзакции (TransactionManager). Теперь же я писал сервис и пришлось иметь место с менеджером ресурсов (XAResource), что тоже интересно (не забываем что проект модельный и исследовательский).

Итак, транзакционность добавил, пока что на уровне RAM без сохранения данных в долговременную помять для отката/восстановления. Следующий шаг это написание самого сервера, который будет управлять Space’ами и обработкой клиентских запросов.

👉 Telegram: https://t.me/memifydb 👉 GitHub: https://github.com/yourname/memifydb

Теги:
Всего голосов 2: ↑0 и ↓2-2
Комментарии0

Нововведения Java 26

В марте 2026 года вышла Java 26.

Поскольку мы в PVS-Studio используем Java для разработки наших Java, JavaScript и TypeScript анализаторов, такая новость нами не могла быть пропущена. Мы выпустили статью, где рассмотрели основные изменения, которые эта версия с собой принесла. Так что давайте вместе посмотрим на основные нововведения, появившиеся в Java 26.

Теги:
Всего голосов 6: ↑6 и ↓0+7
Комментарии0

Друзья, рады поделиться записью первого вебинара из цикла “Современный Gradle для Java-разработчика” 🔥

В первом вебинаре Егор Пиший, Java-разработчик в PVS-Studio, рассказал, зачем в современных проектах нужны модули и как они помогают масштабировать кодовую базу без хаоса. Вместе посмотрели, как устроен жизненный цикл Gradle и какие механизмы стоят за его скоростью и гибкостью.

Посмотреть ещё можно тут:

А зарегистрироваться на следующие вебинары цикла можно по этой ссылке!

Теги:
Всего голосов 1: ↑0 и ↓1-1
Комментарии0

Ближайшие события

Паттерны проектирования еще актуальны?

Вокруг все чаще говорят, что ИИ скоро будет писать код за нас. Логичный вопрос — нужны ли тогда паттерны? Зачем разбираться в паттернах GoF, если нейросеть и так сгенерирует рабочий код по описанию?

У меня ощущение обратное.

Я плотно вошел в разработку в 2019 году. Переходил из 1С в .NET. Книги по паттернам GoF у меня были, но долго лежали как «книга на полке». Казалось, они оторваны от повседневных задач. Теорию вроде понимал, но не видел, где это реально применяется.

Все поменялось, когда я стал использовать ИИ как инструмент для обучения. Просил давать задачи, искать проблемы в решениях, объяснять, почему в одном месте уместен Strategy, а в другом лучше Mediator. Через практику и обсуждение паттерны перестали быть абстракцией.

Чем проще генерировать код, тем важнее понимать его форму и границы. Иначе не ускоришь разработку, а ускоришь накопление технического долга.

Из этого и вырос мой pet-project gofinsights.com. Я делаю его тренажером по паттернам проектирования. Не просто «прочитал и забыл», а через практику, сравнение решений и постепенное распознавание типовых архитектурных ходов.

Сейчас там есть интерактивный квиз, где можно проверить базу и не перепутать Factory Method с Abstract Factory. Дальше хочу развивать проект в сторону более глубокого ИИ-разбора. Чтобы можно было не только узнавать паттерн, но и разбирать кодовые запахи, причины проблем и возможную эволюцию решений.

Как вы это видите? Паттерны проектирования все еще рабочая база для разработчика? Или с появлением ИИ они станут менее важны?

Теги:
Всего голосов 6: ↑5 и ↓1+6
Комментарии1

🌲 Открываем регистрацию на Дебаг Кемп

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

📅 6–7 июня 2026 (выходные) 👥 Всего 25 мест — маленький формат, это принципиально.

Цена растёт по мере приближения к дате. Оплатить можно частями через сплит → регистрация

Если вы 💎 практик сообщества — скидка 15% применяется при регистрации автоматически. Ещё не практик, но думаете? Сейчас самый разумный момент.

👀 Узнать больше · 📝 Регистрация

Вопросы — в чат, мы там живём.

Теги:
Всего голосов 4: ↑0 и ↓4-4
Комментарии0

В предыдущих постах Разбираемся в in-memory базах и Выбираем базу и думаем о данных.

Взлетаем, создал репозиторий под проект https://github.com/mathter/memifydb.git

План

План общий такой:

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

  • Для работы с данными создам некоторый дополнительный уровнь абстракции, что бы не привязываться к конкретному формату данных/библиотеке и менять его налету для сравнения.

Сделано

  • Данные клиента будут храниться в space’ах - это будет аналог таблиц в БД. Для начала будет только key-value space что бы можно было подумать уже сейчас о WAL клиенской библиотеке для java и сетевом уровне в целом и конечно же о транзакциях.

  • Тестовая реализация WAL, которая в проекте будет называться Log.

Run.

Теги:
Рейтинг0
Комментарии0

🔌Форматы обмена и хранения данных

В предыдущих постах Разбираемся в in-memory базах и Выбираем базу я написал, что собираюсь сделать исследовательский проект по in-memory базам данных  и имя ему MemifyDB. Так же выбрал направление движения: это key-value хранилище, которое потом доработаю до документо-ориентированной системы.

Теперь ключевой вопрос: как клиенты будут с ней общаться?

Протокол обмена — это мост между сервером и клиентом. От его дизайна зависит скорость, удобство и даже то, какие фичи мы сможем реализовать.

Human readable (JSON, XML and etc.)

В современных системах активно используется как для транспорта так и для хранения текстовый формат данных, а точнее json и его вариации. У этого подхода есть несколько несомненных плюсов, например:

  • Простота реализации: не нужно поддерживать разные типы на уровне протокола, всё передаётся как строки, а клиент сам разбирается.

  • Гибкость: строкой можно закодировать что угодно — число, JSON, бинарные данные.

Но у этого подхода есть обратная сторона:

  • Нет нативной поддержки типов: Клиент сам должен сериализовать/десериализовать.

  • Оверхед на парсинг: Каждый раз нужно преобразовывать “42” в число и обратно.

  • Неэффективное использование памяти: Число 123456 занимает 6 байт как строка, хотя в бинарном виде — 4 или 8.

  • Невозможность частичного обновления сложных структур: Чтобы изменить одно поле в JSON-объекте, приходится переписывать весь объект (можно конечно поспорить).

## 🎯 Наш подход: типизированные данные с рождения В MemifyDB мы пойдём другим путём.
Мы будем хранить данные в памяти в типизированном виде: строки, числа, списки, хеши, документы — каждый тип со своим внутренним представлением.

И протокол обмена с клиентом должен это отражать.
Мы не хотим, чтобы клиент упаковывал число в строку только потому, что так проще.
Мы хотим передавать по сети те же бинарные структуры, которые лежат в памяти.

Это даст:

  1. Типизированность Формат должен явно различать типы данных: строки, числа (разной разрядности), булевы значения, null, массивы, объекты (документы).
    Это позволит серверу правильно интерпретировать данные без дополнительных метаданных.

  2. Компактность Формат не должен раздувать данные. Число 42 должно занимать 8 байт (или 4, если это int32), а не 2 символа ASCII.

  3. Быстрая навигация Мы должны иметь возможность быстро «прыгнуть» к определённому полю документа без полного парсинга.
    Это важно для частичных обновлений и запросов.

  4. Потоковость Формат должен допускать частичную отправку/приём, чтобы можно было обрабатывать большие документы по частям.

  5. Самодостаточность Данные должны содержать всю информацию для интерпретации, но при этом не дублировать имена полей без необходимости (как в JSON).

🔍 Что дальше?

Существуют несколько бинарных: CBOR, BSON, FlatBuffer и пр. Если у вас есть опыт работы с этим форматами, пишите в комментариях какие у них есть плюсы, минусы и подводные камни.

Теги:
Рейтинг0
Комментарии0

🧠 MemifyDB: прежде всего — видение (vision).

Прежде чем погружаться в код, нужно чётко ответить на вопрос: а что именно мы строим?
Этот пост — не про хардкорный кодинг, а про так называемое видение системы (system vision).
Мы разберём, какие вообще бывают in-memory базы данных, чем они отличаются и почему наш путь будет таким: key-value → документная БД.

Поехали!

📚 Типы in-memory баз данных

1. Key-Value хранилища

Самый простой и быстрый вид. Данные хранятся как пары «ключ — значение», где значение — обычно строка, число или бинарный объект.

  • Примеры: Redis, Memcached, DragonflyDB.

  • Сценарии: кэширование, сессии пользователей, счётчики, очереди задач.

  • Плюсы: максимальная скорость, минимальный оверхед, простота масштабирования (шардирование по ключу).

  • Минусы: ограниченная модель данных — нет сложных запросов, только операции по ключу.

2. Документо-ориентированные БД

Значение — структурированный документ (JSON, BSON, XML). Внутри документа можно индексировать поля и выполнять запросы по содержимому.

  • Примеры: MongoDB (in-memory storage engine), Couchbase.

  • Сценарии: хранение сложных объектов (профили, каталоги), где важна гибкость схемы.

  • Плюсы: удобство для разработчика, естественное представление данных, возможность частичного обновления.

  • Минусы: чуть более высокий оверхед по сравнению с key-value (парсинг, индексация).

3. Колоночные (Columnar) in-memory БД

Данные хранятся не по строкам, а по колонкам. Это даёт огромное преимущество при аналитических запросах (суммы, средние, группировки).

  • Примеры: SAP HANA, MemSQL (SingleStore) в колоночном режиме, Apache Arrow (формат, но не БД).

  • Сценарии: аналитика реального времени, отчёты, BI.

  • Плюсы: сверхбыстрая агрегация, высокая степень сжатия.

  • Минусы: медленные точечные обновления (OLTP-нагрузка), сложность реализации.

4. Графовые БД

Хранят сущности (узлы) и связи между ними (рёбра). Оптимизированы для обходов графа.

  • Примеры: RedisGraph (модуль Redis), Neo4j (с in-memory режимом).

  • Сценарии: социальные сети, рекомендательные системы, сети связей.

  • Плюсы: эффективные запросы связей, интуитивная модель для связанных данных.

  • Минусы: узкая ниша, сложность шардирования.

5. Time-series БД

Специализированы для временных рядов — метрик, логов, событий. Оптимизированы для записи и запросов по временным интервалам.

  • Примеры: InfluxDB, TimescaleDB (in-memory части).

  • Сценарии: мониторинг, IoT, финансовые тикеры.

  • Плюсы: высокая скорость записи, сжатие старых данных, встроенные функции по времени.

  • Минусы: слабо подходят для произвольных данных.

…## 🧭 Наш курс: от Key-Value к документам

Для MemifyDB я выбрал путь, который кажется самым прагматичным:

  1. Создаём ядро Key-Value
    Это фундамент. Мы реализуем:

    • потокобезопасное in-memory хранилище;

    • поддержку разных типов значений (строки, списки, хеши, числа);

    • механизмы TTL и эвикшена (LRU);

    • бинарный протокол, близкий к внутреннему представлению.

    Key-value движок даст нам максимальную скорость и стабильность, а также позволит отточить все низкоуровневые механизмы (аллокаторы, сериализацию, сетевое взаимодействие).

  2. Надстраиваем документный слой
    Поверх key-value ядра мы добавляем возможность интерпретировать значение как JSON-подобный документ:

    • индексация по полям;

    • поддержка частичного обновления;

    • запросы с фильтрацией по содержимому.

При этом сами документы будут храниться в key-value хранилище как обычные значения, а индексы — как дополнительные структуры (хеш-таблицы, B-деревья) в памяти.

Такая двухслойная архитектура даёт:

  • гибкость — можно работать и как с обычным кэшем, и как с документной БД;

  • производительность — key-value ядро остаётся быстрым, а документные операции добавляются без потери эффективности;

  • расширяемость — позже можно добавить другие модели (например, колоночные агрегаты) как отдельные слои.

Теги:
Всего голосов 4: ↑0 и ↓4-4
Комментарии2

🧠 Разбираемся, как устроены in-memory БД: пишем MemifyDB с нуля.

Redis быстр, но не всегда удобен. SAP HANA — мощь, но ценник…
А что, если заглянуть под капот и создать свою enterprise in-memory СУБД?
Не чёрный ящик, а полностью прозрачную, современную, open-source — и при этом готовую к высоким нагрузкам. Разбираемся как это работает!

Знакомьтесь — MemifyDB.

📌 Что это будет?
Настоящая in-memory система уровня enterprise, в которой мы разберёмся до винтика:

  • живёт в RAM, отвечает за микросекунды;

  • сохраняет данные на диск (RDB + WAL) — никакой потери после ребута;

  • реплицируется и шардируется «из коробки»;

  • поддерживает транзакции (не хуже MULTI/EXEC, но с возможным rollback);

  • и при этом не просит продать почку за лицензию.

Весь код — open source, все решения — с объяснениями.

🛠 Технический фундамент (выбираем стек вместе)
Платформа — JVM. Я сейчас выбираю между Java 21 (Loom) и Scala 3 (ZIO / Akka).

  • Сеть: Netty или виртуальные потоки — посмотрим на бенчмарках.

  • Память: off-heap + собственный slab-аллокатор на ByteBuffer. GC не мешает, фрагментация под контролем.

  • Конкурентность: Lock-Free структуры данных, чтобы не блокировать потоки.

  • Протокол: RESP-совместимость — redis-cli сможет общаться с нами.

🗺 Дорожная карта: что и когда разберём

  1. Ядро: потокобезопасное KV-хранилище в памяти. Как работают LRU и TTL?

  2. Persistence: снапшоты и WAL. Как не потерять данные при краше?

  3. Сеть: пишем TCP-сервер. Netty vs Loom — кто быстрее?

  4. Транзакции: реализуем MULTI/EXEC, WATCH. Нужен ли MVCC?

  5. Репликация и Raft: как достичь консенсуса в распределённой системе?

Каждый этап — открытый код, пост с разбором, грабли и профит.

🤔 Зачем я это делаю публично?
Во‑первых, разобраться самому и дать шанс разобраться другим.
Во‑вторых, фидбек сообщества ловит ошибки на берегу.
В‑третьих, хочется сделать реально полезный инструмент, а не очередной pet‑project.

💬 Вопрос к залу:
Какой стек предпочтительнее для enterprise in‑memory БД — Java 21 + Loom или Scala + ZIO/Akka?
Какие фичи вы бы добавили в дорожную карту?
Пишите в комментариях — лучшие идеи уйдут в реализацию!

👉 Подписывайтесь, чтобы не пропустить:

  • глубокий разбор off‑heap аллокатора;

  • сравнение моделей конкурентности на реальных бенчмарках;

  • историю о том, как одна строка unsafe кода валила прод три дня.

Теги:
Всего голосов 13: ↑3 и ↓10-7
Комментарии22

Всё, что нужно знать для начала работы в PVS-Studio

Статический анализатор PVS-Studio — это инструмент для поиска ошибок в коде на протяжении всего жизненного цикла проекта.
В новой статье разберём основные особенности анализатора PVS-Studio, сценарии и варианты анализа, а также узнаем всё, что нужно знать для начала работы с инструментом.

Теги:
Рейтинг0
Комментарии0

Бесплатный тест для Java‑разработчиков: оцени уровень и найди точки роста

Хороший Java‑разработчик — это не просто тот, кто пишет код, а специалист, который держит в голове целую экосистему: от базовых принципов языка до архитектуры распределенных систем.

Чтобы осознанно развиваться дальше, важно понимать:

  • какие технические навыки уже прокачаны;

  • где есть пробелы в знаниях архитектуры и проектировании;

  • какие технологии стоит изучить подробнее;

  • насколько уверенно ты ориентируешься в современном Java‑стеке.

Мы сделали бесплатный пробный тест — он поможет оценить твой уровень как Java‑разработчика и подсветит зоны для развития.

За 20 минут ты получишь:

  • оценку текущего уровня;

  • карту компетенций — наглядную схему всех навыков, необходимых для развития в профессии;

  • подборку материалов для самостоятельного изучения.

Пройти тест

Кстати, мы подробно разбирали ключевые навыки и компетенции Java-разработчика в отдельной статье — рекомендуем прочитать ее или перечитать, чтобы освежить и структурировать знания перед тестом.

Теги:
Всего голосов 2: ↑1 и ↓1+2
Комментарии1

Зелёные тесты ≠ хорошие тесты

Впервые в истории писать тесты стало легко и совсем не страшно. Вокруг теперь у всех покрытие 80%, 90%, а то и вовсе 100%. И вот тут начинается проблема: зелёные тесты ≠ хорошие тесты.

Проблема в метрике, которой мы все привыкли доверять. Code coverage считает строку протестированной, если она выполнилась во время теста. Всё. Не «поймает ли тест баг в этой строке», не «проверяет ли он правильность результата» — просто выполнилась. Можно написать тест без единого assert, и покрытие вырастет. 500 тестов, 90% coverage, а пользы ноль.

Мутационное тестирование — это совершенно другой путь. В простейшей реализации этот инструмент тупо берёт твой код и намеренно ломает его: меняет > на >=, + на ‑, True на False. Каждая такая поломка — мутант. Если после мутации все тесты по‑прежнему зелёные — значит они ничего не проверяют. Покрытие есть, защиты нет.

Почему это важно именно сейчас?

Потому что нейронка любит зелёненькое. Чем больше зелёных тестов — тем субъективно лучше. 100 тестов внушают больше доверия, чем 10, правда? А внутри там assert response.status_code == 200. assert result is not None. assert len(items) > 0. Тест проверяет, что функция вернула хоть что‑то — и радостно зеленеет. Поменяй логику условия, перепутай знак, сломай граничный случай — тест всё равно зелёный. Потому что он проверяет не правильность, а наличие.

Мутационное тестирование — единственный автоматический способ это поймать. Метрика называется mutation score: процент убитых мутантов. 60% — плохо. 90%+ — тесты реально что‑то защищают.

Кое‑какие инструменты для такого тестирования уже есть: mutmut и cosmic‑ray для Python, Stryker для JS/TS, PIT для Java. Медленно? Да, значительно медленнее обычного тест‑рана. Но запускать его не нужно на каждый коммит — достаточно на PR в критические модули.

Но есть нюансы. А где их нет, правда?

Первый: мутации рандомные. Замена > на >= — это не баг, который кто‑то реально допустит. Это синтетическая поломка. Половина мутантов генерирует код, который в реальности никогда не появится. Ты тратишь время на убийство мутантов, которые не имеют отношения к настоящим ошибкам. Это как тестировать замок, ковыряя его вилкой — формально проверка, по факту мимо.

Второй — ещё хуже. Чтобы убить мутанта, тест должен зафиксировать конкретное поведение. Каждую ветку, каждое значение, каждый edge case. Доведи mutation score до 100% — и ты прибил гвоздями каждую строчку кода. Буквально. Теперь попробуй отрефакторить. Переименовал внутренний метод — 40 тестов красные. Поменял порядок полей в ответе — ещё 20. Тесты превращаются из страховки в кандалы: код работает правильно, но тесты падают, потому что они проверяют не поведение, а реализацию.

Это реально ловушка. Слишком гонишься за mutation score — получаешь хрупкие тесты. Не гонишься — получаешь видимость тестирования.

Перемены — впереди!

И вот тут становится по‑настоящему интересно. Представь, что мутации генерирует не тупой набор правил «замени плюс на минус», а нейронка, которая понимает контекст. Которая знает, какие баги реально встречаются в таком коде. Которая мутирует не синтаксис, а логику: меняет порядок проверок, путает граничные условия, забывает обработать edge case — ровно так, как ошибается человек. Или другая нейронка.

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

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

Ждём, когда мутанты станут умнее.

Теги:
Всего голосов 5: ↑5 и ↓0+7
Комментарии3

JEP 524 в JDK 26 — второй preview PEM API

Наконец-то работа с PEM в Java становится похожа на API, а не на набор ручного парсинга, Base64 и странных телодвижений.

Справка: PEM или Privacy-Enhanced Mail - это текстовый контейнер для криптографических данных. Проще говоря – это способ хранить или передавать ключ, сертификат или другой crypto-объект не в бинарном виде, а в текстовом.

Раньше с PEM работали так:

String pem = "-----BEGIN PUBLIC KEY-----\n"
        + Base64.getMimeEncoder(64, "\n".getBytes())
                .encodeToString(publicKey.getEncoded())
        + "\n-----END PUBLIC KEY-----";

А в обратную сторону, но уже с ручной нормализацией PEM, Base64-декодированием и KeyFactory:

String normalized = pem
        .replace("-----BEGIN PUBLIC KEY-----", "")
        .replace("-----END PUBLIC KEY-----", "")
        .replaceAll("\\s", "");

byte[] der = Base64.getDecoder().decode(normalized);

PublicKey key = KeyFactory.getInstance("EC")
        .generatePublic(new X509EncodedKeySpec(der));

По факту PEM в Java долгое время был не отдельным API, а набором низкоуровневых шагов, которые разработчик собирал руками.

А теперь это выглядит так:

var encoder = PEMEncoder.of();
String pem = encoder.encodeToString(keyPair);

var decoder = PEMDecoder.of();
KeyPair decoded = decoder.decode(pem, KeyPair.class);

То есть ключевую пару можно закодировать в PEM и декодировать обратно буквально в несколько строк.

Во втором preview:

  • PEMRecord переименовали в PEM

  • добавили decode()

  • расширили поддержку KeyPair и PKCS8EncodedKeySpec

  • упростили шифрование через EncryptedPrivateKeyInfo

А так, как все это дело еще в preview, не забываем использовать --enable-preview.

❓ Минус еще один кусок криптографической копипасты из Java-кода. PEM в Java постепенно перестает быть унылым?

Присоединяйтесь к русскоязычному сообществу разработчиков на Spring Boot в телеграм — Spring АйО, чтобы быть в курсе последних новостей из мира разработки на Spring Boot и всего, что с ним связано.

Теги:
Всего голосов 4: ↑4 и ↓0+4
Комментарии0

🚀 Бесплатный курс для разработчиков: создаём свой язык программирования!

Приглашаем вас пройти наш курс и разобраться, как устроены языки программирования изнутри.

Изначально курс делали для прохождения внутри компании, но решили, что полезного материала так много, что хочется рассказать всему миру!

Этот курс подойдёт разработчикам, которые хотят выйти за рамки повседневной разработки и глубже понять фундаментальные принципы работы кода. Да, примеры будут на C++, но сам материал гораздо шире и будет полезен программистам с любым стеком. Независимо от того, пишете вы на C++, C#, Java или любом другом языке, понимание внутренней архитектуры языков сделает вас сильнее как инженера.

В рамках курса мы шаг за шагом разберём, как создаётся язык программирования:
— что такое лексер и парсер и какую роль они играют;
— как работает семантический анализ;
— как происходит вычисление и обработка кода;
— как все эти части объединяются в единую систему.

Вы увидите, как текст программы превращается в структуру, понятную машине, и поймёте, какие решения стоят за этим процессом.

Даже если вы не планируете создавать собственный язык программирования, курс поможет чуть глубже понять, как всё это устроено "под капотом", расширить технический кругозор и по-новому взглянуть на привычные инструменты. Это хороший способ систематизировать знания, освежить базовые концепции и просто обсудить интересные темы с коллегами.

Мы постарались сделать материал одновременно понятным и практико-ориентированным: минимум абстракции ради абстракции — максимум смысла.

Если вы хотите лучше понимать, что происходит "под капотом" программирования и прокачать инженерное мышление — этот курс для вас.

👉 Подробности и доступ к курсу по ссылке.

Присоединяйтесь и изучайте программирование глубже — бесплатно!

Теги:
Всего голосов 3: ↑2 и ↓1+1
Комментарии0

Приглашаем на доклад Deep Dive into JVM JDI: Capturing Live Execution for Automatic JUnit Test Generation

Привет! Если на выходных судьба занесёт вас в Новосибирский Академгородок, приходите на технический доклад с мемами от нашего коллеги Даниила Степанова на самой ламповой Java-конференции Сибири — SnowOne 2026 ❄️.

📌 28 февраля, 14:00–15:00 (время Новосибирска)
👨‍💻 Даниил Степанов — разработчик-исследователь в Veai, к.т.н., преподаватель ИТМО

Deep Dive into JVM JDI: Capturing Live Execution for Automatic JUnit Test Generation

Глубокий технический разбор архитектуры инструмента, который использует Java Debug Interface (JDI) для захвата состояния работающей JVM и автоматического синтеза валидных unit-тестов.

Что будет в докладе:

  • Deep Dive в JDI. Подробный рассказ про JDI, преимущества и недостатки, а также как его использовать в нестандартных сценариях для безопасного захвата Heap и Stack Frame в реальном времени.

  • Реконструкция объектов. Reverse Engineering JVM-состояния для воссоздания сложных графов объектов.

  • Синтез Java-кода. Как превратить сырой дамп памяти в чистый, валидный JUnit-тест.

  • Роль LLM. Для решения каких проблем мы используем искусственный интеллект?

Доклад будет полезен Java-разработчикам, тем, кто интересуется внутренним устройством JVM, и всем, кто хочет автоматизировать написание тестов.

Технологии: Java, JVM, JDI (Java Debug Interface), Mockito, JUnit, LLM.

Отличной пятницы и увидимся на SnowOne 🖖

Теги:
Рейтинг0
Комментарии0

Практический Тренажер по Java — самый популярный тренажер по Java на Stepik

В 2024 году я опубликовал курс «Практический Тренажер по Java» на платформе Stepik. Тогда это был просто практический курс с задачами — без воды, без длинной теории, только код и постоянная тренировка.

Прошло несколько лет.

Сегодня курс проходит более 19 000 учеников, и это самый популярный тренажёр по языку Java на платформе Stepik.

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

И я хочу заново пригласить вас в этот проект.

Почему Java?

Java — один из самых востребованных языков программирования в мире.

Он используется в:

— веб-разработке

— мобильной разработке (Android)

— корпоративных системах

— финансовых сервисах

— высоконагруженных backend-проектах

Java — это стабильность, масштабируемость и высокий спрос на рынке труда.

Что представляет собой курс сегодня?

Это полностью практический формат обучения. Только задачи и реальная практика.

Многие ученики используют тренажер как системную подготовку к техническим интервью. Такой формат не просто помогает решать задачи, а выстраивает алгоритмическое мышление, формирует уверенность в собственном коде и укрепляет уверенность в своих силах и уровне владения Java.

Кому подойдёт курс?

— начинающим разработчикам

— тем, кто хочет перейти в backend

— Android-разработчикам

— QA Automation инженерам

— тем, кто готовится к собеседованиям

Я приглашаю вас присоединиться :)

➡️ Java Тренажер на Stepik

Теги:
Всего голосов 3: ↑2 и ↓1+1
Комментарии0

Применяем кодогенерацию в Java для решения алгоритмических задач

В прошлый раз мы разобрались, как решается задача трансляции деревьев. И остановились на том, что в случае с AST от компилятора TypeScript, придётся руками обрабатывать 263 типов узлов. Тысячи строк однотипного boilerplate-кода: приведения типов, аннотации, объявления методов — всё это нужно не просто написать, но ещё и поддерживать. А если требования к архитектуре поменяются — переписывать заново.

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

Как реализовать это с помощью JavaPoet, что умеет эта библиотека, а также как встроить в процесс нормализацию можно узнать в новом материале, посвящённом использованию кодогенерации для трансляции деревьев.

Теги:
Всего голосов 1: ↑1 и ↓0+2
Комментарии0

OpenAPI Generator через призму статического анализатора

Знаете ли вы про OpenAPI Generator — open source проект, задача которого — автоматическая генерация клиентских библиотек, серверных заглушек, документации и файлов конфигурации на основе спецификации OpenAPI в формате JSON или YAML. Проект является достаточно популярным: у него чуть больше 25000 звёзд на GitHub.

Мы проверили его статическим анализатором для языка Java и написали статью про найденные в коде OpenAPI Generator ошибки.

Теги:
Всего голосов 1: ↑1 и ↓0+1
Комментарии0

⚠️ Java продолжает готовиться к удалению finalize()

В рамках JDK 27 у ThreadPoolExecutor-а, очень популярного API в Java, будет удалён метод finalize(). Несмотря на то, что в силу dynamic dispatch вызов метода finalize() всё равно будет транслирован в Object, данное изменение не source level compatible.

А все потому, что у Object.finalize() сигнатура содержит throws Throwable, в то время как ThreadPoolExecutor.finalize() — нет. Пока метод был в ThreadPoolExecutor, компилятору было ок. Как только его удалят, вызов super.finalize() начнет резолвиться в Object.finalize(), и тогда прилетит “unreported exception Throwable”.

Комментарий от Михаила Поливаха:

Вот это кстати довольно редкий пример того, что имзенение может быть binary level compatible, но не source level compatible.

Например:

class MyPool extends ThreadPoolExecutor {

  @Override
  protected void finalize() {
    super.finalize(); // JDK 27: теперь это Object.finalize() throws Throwable
  }
}

Как избежать?

  • поискать и удалить любые finalize() / super.finalize() (и вообще любые авто-cleanup через финализацию)

  • управлять жизненным циклом executor’ов явно: shutdown()/awaitTermination() или просто close() в try-with-resources (да, ExecutorServiceAutoCloseable)

Spring АйО рекомендует не использовать finalize() в целом, но если подобного рода хук нужен, то лучше использовать Java Cleaner API. С его помощью нельзя "случайно" воскресить объект, сломать integrity объекта или т.п.

Ждем JDK 27 🫠

Присоединяйтесь к русскоязычному сообществу разработчиков на Spring Boot в телеграм — Spring АйО, чтобы быть в курсе последних новостей из мира разработки на Spring Boot и всего, что с ним связано.

Теги:
Всего голосов 3: ↑3 и ↓0+3
Комментарии0

Автоимпорт при копировании кода — штука настолько приятная и удобная, что без неё уже невозможно представить работу в IDE. 

Мы пошли дальше и вслед за умным импортом во время набора кода сделали автоматическую инжекцию бинов при копировании кода!

Теперь при копировании кода Amplicode автоматически добавляет нужную инжекцию бинов. С учётом контекста, @Primary, @Qualifier, дженериков, @Bean-методов, Java и Kotlin — без ручной возни после вставки.

Будет доступно всем пользователям Amplicode, без подписки.

Теги:
Всего голосов 5: ↑4 и ↓1+3
Комментарии0

Как оставаться релевантным на рынке QA/AQA/SDET в 2026: опыт, харды, софты, ответы

Последнее время всё чаще слышу вопросы про состояние рынка.
Многие говорят, что рынок «умер», вакансий стало меньше, а требования выросли настолько, что найти работу почти нереально.

Часто это выглядит так: человек активно откликается, ходит на собеседования, делает тестовые задания, общается с рекрутерами.
А на выходе получает либо отказы без конкретных причин, либо формулировки вроде «вы хороший специалист, но нам нужен немного другой профиль».

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

Я регулярно общаюсь с QA, AQA и SDET, которые находятся в активном поиске, и сам продолжаю проходить собеседования, чтобы понимать, как именно сейчас устроен процесс найма.
И вот что я понял из всех историй: сегодня выигрывает не самый наглый кандидат (как было раньше), а тот, кто хорошо понимает свой опыт и умеет его объяснять.

Что изменилось

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

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

Это не «заговор рынка», а естественная фильтрация. Когда выбор кандидатов большой, требования становятся строже.

Почему в этом есть плюсы

Жесткий рынок хорошо отсеивает слабые места. Причем чаще всего самые базовые.

На собеседованиях у ребят регулярно всплывают одни и те же проблемы:

  • человек говорит, что строил фреймворк, но не может связно объяснить архитектуру;

  • упоминает автотесты, но не понимает, почему был выбран конкретный стек;

  • рассказывает про CI, но путается в вопросах стабильности;

  • заявляет ответственность за качество, но не может описать процессы и зоны ответственности.

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

Как сейчас смотрят на опыт

На интервью все меньше внимания уделяется формальным строчкам в резюме и все больше мышлению.

Интервьюеру важно понять:

  1. Почему было принято именно такое решение;

  2. Какие были трудности;

  3. Как проблемы диагностировали;

  4. Какие выводы сделали.

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

Поэтому сейчас важна не красивая история, а осознанное понимание своего опыта.

Что с этим делать

Минимальный практический набор:

  1. Разложить свой опыт по зонам - архитектура, API, UI, CI/CD, процессы, инциденты.

  2. Подготовить ответы в формате «проблема - решение - результат - выводы». (Для шарящих - по STAR)

  3. Прогнать опыт через уточняющие вопросы и проверить, где ответы выглядят слабо или непоследовательно.

  4. Упаковать резюме как набор конкретных ответов - что улучшал, что оптимизировал, за что отвечал + быть готовым это подтвердить.

Вывод

Рынок действительно стал сложнее.
Но именно поэтому он стал более комфортным для тех, кто держит фокус на релевантности, понимает свой опыт и готовится к проверке.

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

Ну а всем нуждающимся желаю скорее обрести себя на сегодняшнем рынке! Готов подискутировать на смежные темы в комментариях)

Теги:
Всего голосов 3: ↑0 и ↓3-3
Комментарии0

О поддержке opensource - как показателе безопасности

Случались ситуации, когда компании использовали open source, который перестал развиваться. И в этом open source находили уязвимости. Итог: компаниям сложно ликвидировать уязвимости в используемом open source. По этой причине рождались предложения: дабы не попасть в такую ситуацию - при выборе open source проверять, что проект ещё поддерживается. Мысль здравая. Но, и тут могут быть нюансы. Пример - проект JasperReports (для Java). Судя по репозиторию - проект поддерживается. 16 сентября 2025 была опубликована информация об уязвимости в проекте (критического уровня: 9.8 по шкале CVSS v3.1 - CVE-2025-10492). А 19 сентября 2025 разработчик сообщил, что фикс выйдет только для коммерческой версии.

Теги:
Всего голосов 2: ↑1 и ↓1+2
Комментарии0

Автостопом по LTS: основные изменения при переходе с 8 на 11 Java

Совсем недавно мы выпускали статью про нововведения в Java 25. И один из комментаторов сказал, что ему было бы интересно прочитать от нас цикл статей, в которых рассказано и показано, как менялась Java от LTS к LTS, начиная с Java 8.

Нам эта идея показалась интересной, и с этой статьи мы начинаем наш новый цикл, в котором рассказываем, с чем придётся столкнуться разработчику при переходе между LTS-версиями Java. В этой статье рассмотрим основные изменения, которые ждут программиста, если он решит перейти с Java 8 на Java 11.

Теги:
Всего голосов 4: ↑3 и ↓1+3
Комментарии0

Что нового появилось в PVS-Studio в 2025 году

Новый 2026 год уже вовсю идёт, и мы решили оглянуться назад и вспомнить, что интересного появилось в PVS-Studio за богатый на изменения 2025 год:

  • десятки новых диагностических правил, включая проверки, ориентированные на безопасность;

  • обновления интеграций в популярные IDE, CI/CD-системы, ASOC и сборочные системы;

  • улучшения анализа;

  • расширенная поддержка стандартов.

Всё это и многое другое описано в новой статье в нашем блоге.

Теги:
Всего голосов 1: ↑1 и ↓0+1
Комментарии0

При написании интеграционных тестов для Spring Boot приложения часто возникает проблема, что разработчики бездумно добавляют аннотации @MockBean, @SpyBean, @DirtiesContext или переопределяют прямо в тестовом классе различные property. Всё это приводит к изменению Spring Context, невозможности использовать закэшированный контекст и следовательно созданию нового. Часто создание нового контекста это длительная операция.

Существуют инструменты по отслеживанию этих процессов. Самым простым способом увидеть количество контекстов и количество попаданий в кэш является добавление логирования либо через свойство logging.level.org.springframework.test.context.cache=DEBUG либо настройкой вашего логгера.

Один известный автор статей про тестирование на Java / Spring Boot, Philip Riecks (со товарищи), создал инструмент с открытым исходным кодом Spring Test Profiler при помощи которого можно получить html отчёт о поднимаемых контекстах во время тестов, о количестве и типе бинов в этих контекстах. На Хабре есть перевод его статьи в сообществе Spring АйО.

У нас на проекте стал вопрос, как нам показать разработчикам, что их тест порождает новый Спринг Контекст. Мы решили считать контексты в тестах и при превышении ожидаемого количества падать. Это "руинит" сборку и CI/CD пайплайн.
Для этого мы добавили реализацию интерфейса ContextCustomizer

class LimitingSpringContextCustomizer implements ContextCustomizer {

    private static final AtomicInteger CONTEXT_COUNTER = new AtomicInteger();
    private static final int EXPECTED_SPRING_TEST_CONTEXT_COUNT = 16;

    @Override
    public void customizeContext(ConfigurableApplicationContext context, MergedContextConfiguration mergedConfig) {
        int numberOfContexts = CONTEXT_COUNTER.incrementAndGet();
        log.info("Number of Spring Test Contexts: {}/{}", numberOfContexts, EXPECTED_SPRING_TEST_CONTEXT_COUNT);
        Assert.state(numberOfContexts <= EXPECTED_SPRING_TEST_CONTEXT_COUNT,
                () -> "Number of test contexts exceeds configured maximum: " + EXPECTED_SPRING_TEST_CONTEXT_COUNT);
    }

    @Override
    public boolean equals(Object obj) {
        return (obj != null) && (getClass() == obj.getClass());
    }

    @Override
    public int hashCode() {
        return getClass().hashCode();
    }
}

Здесь, согласно документации интерфейса ContextCustomizer необходимо корректно переопределить методы equals и hashCode.

WARNING: implementations must implement correct equals and hashCode methods since customizers form part of the MergedContextConfiguration which is used as a cache key.

Далее добавляем фабрику.

class LimitingSpringContextCustomizerFactory implements ContextCustomizerFactory {

    @Override
    public ContextCustomizer createContextCustomizer(Class<?> testClass,
                                                     List<ContextConfigurationAttributes> configAttributes) {
        return new LimitingSpringContextCustomizer();
    }
}

Затем регистрируем эту фабрику при помощи spring.factories чтобы она применялась ко всем тестам.
Для этого создаём в тестовых ресурсах файл по пути src/test/resources/META-INF/spring.factories со следующим содержимым

org.springframework.test.context.ContextCustomizerFactory=\  
com.mycompany.app.support.spring.LimitingSpringContextCustomizerFactory

Теперь, если во время выполнения тестов будет превышено количество инициализированных тестовых контекстов, то мы увидим ошибку в тестах и сборка завершится неудачей.

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

Теги:
Всего голосов 6: ↑5 и ↓1+4
Комментарии0

Как не потерять сервер в Minecraft из-за опасных модов

Уверен, что многие владельцы Minecraft-проектов сталкивались с игроками, которые хотели взломать сервер и выдать себе права администратора. Я понимаю, что подобное случается не только в играх, и из научного интереса изучаю, как и почему это происходит.

В этой статье мы рассмотрим CVE, найденную в моде Integrated Scripting.

Теги:
Всего голосов 6: ↑4 и ↓2+3
Комментарии0

Kotlin и Hyperskill: как я искал курс и что получил в итоге.

Когда я решил изучать Kotlin, ожидал, что найти хороший курс будет просто: язык популярный, используется в Android и бэкенде, вокруг много материалов. Искал менторов и упирался в людей которые знаю java и вроде как используют в работе Kotlin. Это одновременно пугало и заинтересовывало, я решил поступить как мне казалось правильным, найти готовый курс  — особенно если хочется не “смотреть видео”, а именно учиться через практику и задачи.

Я перепробовал разные форматы обучения (платные и бесплатные), поэтому в этот раз подход был простой: найти платформу, где есть структурированная программа и много практики. В итоге я добрался до Hyperskill (hyperskill.org). Это не реклама — просто личный опыт, кому-то он может сэкономить время.

Как я пришёл к ресурсу.

Изначально искал курсы по Kotlin на привычных площадках. На Stepik в тот момент не нашёл того, что мне подходило по структуре (возможно, сейчас ситуация лучше). Видео-курсы на крупных “известных сайтах” сознательно не рассматривал: мне удобнее формат “прочитал → сделал → получил проверку”.

Дальше — обычный путь через поисковик и сравнение нескольких платформ. Из того, что выглядело цельно и практично, больше всего зацепил Hyperskill. Отдельно сыграло роль то, что платформа связана с JetBra…. (то есть ребята явно понимают, как устроена экосистема вокруг Kotlin и IDE).После регистрации быстро становится понятно: платформа активно ведёт к подписке.Раньше в сети встречались статьи про возможность оформить бесплатную подписку на полгода, но это устаревшая информация — сейчас такой опции нет (по крайней мере, в том виде, в каком её описывают старые гайды).

При этом у Hyperskill есть бесплатный режим, и я проходил курс именно так.

Что я проходил: Introduction to Kotlin.

На платформе несколько треков по Kotlin, я начал с Introduction to Kotlin. По ощущениям, это “введение с практикой”:

  • около 9 учебных проектов

  • порядка 60–70 тем

  • внутри тем — задачи/тренажёры с автоматической проверкой

В целом структура понравилась: материал подаётся дозировано, и почти сразу закрепляется практикой. Похожая на Степик.

Система “кристаллов” и лимиты.

Самая спорная часть бесплатного режима — ограничения на попытки.

У Hyperskill есть внутренняя валюта (“кристаллы”): ошибаешься в заданиях — кристаллы списываются. Когда кристаллы заканчиваются, обучение может блокироваться на 12–24 часа. Да, кристаллы можно зарабатывать активностью и выполнением некоторых задач, но при активном обучении и регулярных ошибках (что нормально) этого может не хватать.

Подписка проблему снимает, но именно этот момент сильнее всего влияет на комфорт обучения в бесплатном режиме.

Проекты: что внутри и зачем это полезно.

Сильная сторона Hyperskill — проекты. Они не выглядят как “игрушки ради галочки”, а позволяют постепенно потрогать основные конструкции языка.

Из того, что запомнилось:

  • “Сапёр”

  • “Крестики-нолики”

  • “Чат-бот”

  • “Кофемашина”

Например, в проекте “кофемашина” уже нормально используются циклы, классы и базовые элементы ООП. В таком формате проще понять, “зачем оно нужно”, чем на изолированных задачках.

Минус: часть проектов закрыта платной подпиской, и это немного обидно — именно проекты дают максимальную пользу и ощущение прогресса.

Проверка решений: не всегда понятно, почему “не принято”

Ещё один недостаток — качество обратной связи в тестах. Иногда тесты “падают” так, что ты видишь только факт ошибки, но не понимаешь причину: что именно ожидалось, на каком кейсе сломалось, где расхождение.Часть проектов проверяется через IntelliJ IDEA, и здесь иногда всплывают технические нюансы: несовпадение версий, необходимость обновить IDE или компилятор, странные падения на конкретном проекте.

Хороший момент: поддержка отвечает. По моему опыту, вопросы не игнорируют, и проблемы реально разбирают.

Итоги:

  • бесплатный режим может раздражать лимитами на ошибки (кристаллы и блокировки)

  • часть контента (включая проекты) закрыта подпиской

  • обратная связь тестов местами недостаточно информативная

    Если готовы, то вперед!

Теги:
Всего голосов 1: ↑1 и ↓0+1
Комментарии0

Работаем из Java с устройствами с serial-интерфейсом (COM и USB) без JNI — по TCP.

Раньше пользовались rxtx, затем jssc. После очередных крэшей JVM в коде нативных библиотек решил не выбирать замену, а отказаться от них полностью.

В качестве прокси serial-TCP можно взять ser2net или поэкспериментировать с socat, но я запилил свое простое (Rust, mio), под конкретную задачу:

  1. Запускается из основного приложения, свой процесс для каждого устройства

  2. Конфигурация через аргументы запуска и переменные окружения

  3. Завершает работу при отсутствии или отключении устройства (для USB), отключении или отсутствия подключения TCP-клиента

В качестве TCP-клиента Netty. Для интеграции с легаси данные читаются в кольцевой буфер ( OneToOneRingBuffer из agrona), а оттуда уже используются по месту в удобное время.

За счет неблокирующего чтения и использования epoll в mio и Netty минимальные задержки, моментальное оповещение о наличии данных (без Thread.sleep) и об отключении USB-устройства.

Задержки настолько меньше, что пришлось адаптировать кривой код, который не был готов к тому, что драйвер железного serial-порта в Linux отдает данные порциями по 8 байт. Решилось реализацией ByteToMessageDecoder, где возможно, а где нет — буферизацией на стороне прокси и отправкой по таймеру.

Для надежной работы уменьшаем и выравниваем буферы записи, пишем через writeAndFlush с ожиданием завершения, чтобы устройство успевало читать.

Бонус: можно работать с устройством, подключенным к другому системному блоку (например, для разработки) и использовать TCP-эмуляторы вместо реальных устройств без изменения кода интеграции.

Теги:
Всего голосов 2: ↑2 и ↓0+2
Комментарии0

Новогодняя аномалия в данных мониторинга.

С Новым Годом!
С Новым Годом!

Воспроизвести достаточно просто

  • Скачать и установить Dimension-UI.

  • Развернуть локально PostgreSQL.

  • Запустить в Dimension-UI мониторинг данных PostgreSQL с помощью запроса с интервалом 3 сек.

WITH params AS (
    SELECT 
        15 AS total_frames,
        20 AS canvas_height,
        3  AS frame_duration_sec
),
animation_state AS (
    SELECT 
        (CAST(EXTRACT(EPOCH FROM CURRENT_TIMESTAMP) AS INTEGER) / frame_duration_sec) % total_frames AS frame_idx
    FROM params
),
tree_definition AS (
    SELECT 
        frame_id, 
        y_pos,
        CASE
            -- ═══════════════════════════════════════
            -- ЗВЕЗДА на верхушке
            -- ═══════════════════════════════════════
            WHEN y_pos = 20 AND frame_id = 7 THEN '*'
            
            -- ═══════════════════════════════════════
            -- ВЕРХУШКА елки (острая)
            -- ═══════════════════════════════════════
            WHEN y_pos = 19 AND frame_id = 7 THEN 'G'
            
            -- ═══════════════════════════════════════
            -- ЯРУС 1 (y=16-18) — расширяется книзу
            -- ═══════════════════════════════════════
            WHEN y_pos = 18 AND frame_id BETWEEN 6 AND 8 THEN 'G'
            WHEN y_pos = 17 AND frame_id BETWEEN 5 AND 9 THEN 'G'
            WHEN y_pos = 16 AND frame_id BETWEEN 4 AND 10 THEN 'G'  -- широкий низ яруса
            
            -- Сужение перед ярусом 2
            WHEN y_pos = 15 AND frame_id BETWEEN 5 AND 9 THEN 'G'
            
            -- ═══════════════════════════════════════
            -- ЯРУС 2 (y=12-14)
            -- ═══════════════════════════════════════
            WHEN y_pos = 14 AND frame_id BETWEEN 4 AND 10 THEN 'G'
            WHEN y_pos = 13 AND frame_id BETWEEN 3 AND 11 THEN 'G'
            WHEN y_pos = 12 AND frame_id BETWEEN 2 AND 12 THEN 'G'  -- широкий низ яруса
            
            -- Сужение перед ярусом 3
            WHEN y_pos = 11 AND frame_id BETWEEN 4 AND 10 THEN 'G'
            
            -- ═══════════════════════════════════════
            -- ЯРУС 3 (y=8-10)
            -- ═══════════════════════════════════════
            WHEN y_pos = 10 AND frame_id BETWEEN 3 AND 11 THEN 'G'
            WHEN y_pos = 9  AND frame_id BETWEEN 2 AND 12 THEN 'G'
            WHEN y_pos = 8  AND frame_id BETWEEN 1 AND 13 THEN 'G'  -- широкий низ яруса
            
            -- Сужение перед ярусом 4
            WHEN y_pos = 7 AND frame_id BETWEEN 3 AND 11 THEN 'G'
            
            -- ═══════════════════════════════════════
            -- ЯРУС 4 — нижний, самый широкий (y=4-6)
            -- ═══════════════════════════════════════
            WHEN y_pos = 6 AND frame_id BETWEEN 2 AND 12 THEN 'G'
            WHEN y_pos = 5 AND frame_id BETWEEN 1 AND 13 THEN 'G'
            WHEN y_pos = 4 AND frame_id BETWEEN 0 AND 14 THEN 'G'  -- во всю ширину!
            
            -- ═══════════════════════════════════════
            -- СТВОЛ (y=1-3)
            -- ═══════════════════════════════════════
            WHEN y_pos BETWEEN 1 AND 3 AND frame_id BETWEEN 6 AND 8 THEN 'T'
            
            -- Всё остальное — фон
            ELSE 'S'
        END AS pixel_char
    FROM generate_series(0, 14) AS frame(frame_id)
    CROSS JOIN generate_series(1, 20) AS y(y_pos)
),
pixel_data AS (
    SELECT td.*
    FROM tree_definition td
    JOIN animation_state ast ON td.frame_id = ast.frame_idx
),
layers_logic AS (
    SELECT 
        y_pos,
        pixel_char,
        MAX(CASE WHEN pixel_char IN ('T', 'G', '*') THEN y_pos ELSE 0 END) OVER () as max_obj_height
    FROM pixel_data
)
SELECT 
    CURRENT_TIMESTAMP as dt,
    CASE 
        WHEN pixel_char = 'T' THEN '4_Trunk'
        WHEN pixel_char = 'G' THEN '3_Tree'
        WHEN pixel_char = '*' THEN '2_Star'
        WHEN pixel_char = 'S' THEN 
            CASE WHEN y_pos > max_obj_height 
    

p.s. Данные по запросу любезно предоставлены Claude Opus 4.5.

Теги:
Всего голосов 5: ↑3 и ↓2+3
Комментарии1

StingrayTV Alice стал ещё лучше - теперь оно уже почти production-ready, с кучей фиксов и улучшений.

В частности:

  1. Пофиксил пару специфичных моментов, связанные с получением информации о текущем телеканале (они идут как SSE, поэтому пришлось воспользоваться WebClient для работы с SSE-запросами) - это позволило наконец-то избавиться от торможения запросов к ресиверу, что в свою очередь позволило наконец-то довести приложение до полностью работоспособного состояния.

  2. Теперь StingrayTV Alice использует bridge-сеть Docker'а, а для работы с mDNS теперь используется ретранслятор, соединяющий контейнер и mDNS-сеть вместе через выделенный контейнер. Это позволило окончательно разграничить сетевой стек в контейнерах, и улучшить общую безопасность.

Приложение уже окончательно протестировано на моём ресивере, осталось только совсем чуть-чуть, и скоро выйдет первая бета.

Теги:
Всего голосов 1: ↑1 и ↓0+1
Комментарии0
1
23 ...