Как Junie от JetBrains помогла ускорить разработку внутреннего проекта
Всем привет! Я Станислав Радченко, Android-разработчик из Effective. В этой статье я расскажу о том, как с помощью Junie от JetBrains мы ускорили разработку внутреннего проекта — приложения для бронирования переговорных комнат.
Junie — AI-агент от JetBrains, который помогает автоматизировать целый ряд задач в IDE.
Он может самостоятeльно читать структуру проекта, работать с файлами, запускать код, тесты и терминальные команды, вносить изменения в файловую систему. При этом контроль остаётся за человеком: пользователь задаёт задачу, даёт одобрение или корректировку промежуточных шагов — а Junie показывает план действий и отчёты о выполнении.
Структура статьи
- О проекте
- Стек проекта
- Почему мы выбрали Junie
- Как Junie применялся в проекте
- Примеры работы Junie
- Плюсы и минусы
- Выводы
О проекте
Effective Office — внутренняя экосистема, которая объединяет приложения для автоматизации офисных процессов. Одно из них отвечает за бронирование переговорных комнат.
Несмотря на то что IT-компании уже давно перешли на гибридный или полностью удалённый формат, работа в физическом офисе по‑прежнему не теряет своей актуальности: встречи с командой, брейнштормы, важные звонки — всё это требует переговорных комнат и чёткой системы их бронирования. Когда таких ресурсов становится много, ручное управление превращается в хаос: пересекающиеся брони, потерянные слоты и вечное «А кто занял эту комнату?».
Мы решили автоматизировать этот процесс и создать внутренний сервис, который управляет всеми ресурсами офиса. Серверная часть реализована на Spring Boot и предоставляет REST API для работы с бронированием, а клиентское приложение на Kotlin Multiplatform развёрнуто на планшетах у дверей переговорных. На них сотрудники в реальном времени видят статус конкретной переговорной и могут мгновенно забронировать слот прямо с устройства — без переключения на ноутбук или телефон.
Чтобы исключить ручные действия и максимально интегрироваться в экосистему компании, мы добавили поддержку Google Workspace и Google Calendar, что позволило синхронизировать все встречи автоматически.
Проект сразу задумывался как Open Source, потому что мы хотели не только решить задачу внутри своей компании, но и поделиться опытом с другими разработчиками.
Код доступен для изучения, доработки и контрибьюта, а сама архитектура построена так, чтобы её можно было легко адаптировать под разные сценарии.
Однако в этой статье я хочу рассказать не только о технической стороне проекта, но и о том, как мы использовали AI-агента Junie для его реализации.
Junie не просто инструмент для генерации кода — он стал полноценным участником процесса разработки: помогал проектировать архитектуру, писать boilerplate, документировать API и даже искал узкие места! Я покажу, где Junie действительно ускоряет работу, а где всё ещё нужен опыт разработчика.
Если вы работаете с Kotlin интересуетесь AI‑инструментами или просто хотите увидеть, как можно автоматизировать офисные процессы, наш опыт будет вам полезен.
Стек проекта
Effective Office существует уже 3 года, и изначально разрабатывался студентами как учебная задача, поэтому у него было много проблем с кодом и инфраструктурой. Неудачные технические решения, устаревшие библиотеки и сложность поддержки привели нас к решению отрефакторить проект с нуля.
При рефакторинге хотелось найти баланс между простотой и надёжностью. Важно было, чтобы новые разработчики легко ориентировались в структуре проекта и могли быстро поднимать его локально, а деплой не превращался в отдельный квест.
В итоге получилась следующая структура:
- Многомодульная архитектура: gradle-проект с модулями backend, client. Так как бэкенд и клиент — это модули одного проекта, мы при желании сможем переиспользовать общие модели данных и сформировать более строгий контракт между слоями. Плюс ко всему, система реализована как монорепозиторий. В будущем мы планируем добавлять новые сервисы, поэтому иметь для них единую точку входа будет удобно;
- Модуль build-logic содержит Gradle Conventions Plugins для упрощения работы с множеством модулей и снижения дублирования конфигураций.
Backend
Серверная часть реализована на Kotlin и Spring Boot. Она отвечает за:
- REST API для работы с бронированиями (CRUD для переговорных, создание и отмена бронирований);
- Интеграцию с Google Calendar для автоматической синхронизации событий;
- Авторизацию через Google Workspace;
- Хранение данных в PostgreSQL.
Client
Приложение создано на Kotlin Multiplatform с UI на Compose Multiplatform.
Интерфейс минималистичен: крупные кнопки, высокая контрастность, минимум шагов для бронирования.
Инфраструктура
- Сборка Docker-образа и деплой на выделенный сервер. Для автоматизации этого процесса мы используем Gradle Tasks.
- Разделение окружения на dev и prod для безопасного тестирования и стабильной работы продакшена.
- Возможность запуска сервиса локально в несколько команд без сложной конфигурации.
Такой подход позволяет запускать полный цикл разработки и тестирования прямо на локальной машине, а деплой на сервер занимает считанные минуты. Всё это делает проект дружелюбным как для опытных разработчиков, так и для новичков в команде.
Почему мы выбрали Junie
Мы хотели провести рефакторинг за минимальные сроки, и в этом нам должны были помочь AI-агенты.
Очень удачно к тому моменту на KotlinConf 2025 показали Junie — AI-агента, встроенного прямо в IntelliJ IDEA.
Идея мгновенно откликнулась: привычная среда разработки для Kotlin, никаких переключений между браузером и IDE, никакого бесконечного копипаста из ChatGPT. Забегая вперёд, скажу: решение использовать Junie — оказалось именно тем, что нам было нужно.
Как Junie применялся в проекте
Инициализация backend проекта
Первостепенной задачей было создание базового проекта и структуры модулей для backend-приложения. На мой взгляд, Junie отлично справился с этой задачей. Используя этот промпт:
Junie составил план:
На его основе Junie создал структуру проекта.
Что можно отметить на этом этапе?
- Создан backend app модуль
- Часть библиотек вынесена в libs.version.toml
- Созданы и применены модули convention plugins
- Создан базовый CRUD для пользователей: модели Dto, Domain и Entity, Contoller, Service и Application-класс
- Реализована интеграция с базой данных и файл миграции
- Настроен Docker-файл
- Сгенерирован REAMDE с гайдом к запуску различных environments
Потом я попросил Junie обновить все библиотеки до самых последних версий:
Результат:
Как видите, библиотеки обновлены, но не всегда до самой последней версии. Например, версия Kotlin.
Вообще, я заметил, что, когда работа доходит до какой-то конкретной версии библиотеки, Junie это игнорирует и ориентируется на ту версию, которую знает. Отдельно об этом расскажу в главе о миграции клиентских фичей.
Отдельным промптом я попросил сделать несколько окружений:
Результат:
Как и следовало ожидать, проект не запустился с первого раза. Однако, пересылая ошибки из консоли в Junie, парой-тройкой промптов мы довели проект до успешной сборки.
В целом я считаю результат отличным. Да, Junie не всегда работает идеально и требует контроля, но даже в таком виде он ускорил разработку в разы.
Я считаю, что мне как Android-разработчику без опыта в backend Junie сильно помог на этом этапе. Одним подробным промптом Junie сгенерировал базовый CRUD проект с гайдом о том, как его запускать.
Миграция backend-фичей из legacy проекта
Следующей задачей была миграция кода старого Ktor-бэкенда на Kotlin Spring Boot.
Для успешной миграции мне было важно понять, как работал legacy-код, чтобы иметь полный контекст проекта. Поэтому перед переносом каждой фичи я:
- просил у Junie объяснения конкретных участков старого проекта;
- запрашивал у него список критических проблем и потенциальных рисков;
- после получения контекста передавал его Junie.
Структура модулей
Для начала я задал Junie структуру модулей проекта:
Промпт для миграции фичи бронирования переговорных:
Результат:
Результат работы Junie показал, что такой подход работает:
- соблюдены общий code style и структура модулей;
- перенесено много компонентов и логики, однако часто Junie оставлял моковую реализацию с комментарием «В production-коде мы бы сделали так-то»;
- реализована абстракция над фреймворком календаря;
- для создания модулей использованы gradle-convention плагины;
- константы, ключи и секреты вынесены в файл конфигурации и подгружаются через .env.
После этого потребовались следующие доработки:
Миграция фичей client из legacy-проекта
После миграции бэкенда мы вернулись к клиентской части. У нас уже было старое приложение, но его код требовал серьёзного рефакторинга: хотелось упростить архитектуру и избавиться от лишнего оверхеда.
Раньше мы использовали связку Decompose + MVI Kotlin, но для нашего уровня проекта это оказалось слишком тяжеловесным решением. Мы решили упростить логику и перейти к модели Decompose + MVI прямо в Component-классах, что дало более прозрачный и понятный код без лишних абстракций.
Чтобы помочь Junie работать в контексте проекта, я положил папку со старым кодом прямо в новый репозиторий. Так агент мог анализировать не только текущие файлы, но и весь legacy-код.
Затем я создал новый Compose Multiplatform модуль для планшетов. Именно с него мы начали рефакторинг клиентской части.
Junie помогал и на этом этапе, но не так уверенно, как на бэкенде. Он генерировал базовую структуру экранов, писал компоненты и предлагал упрощения, но в реальной практике это часто требовало ручных доработок. Особенно это было заметно при работе с Decompose и специфичными для KMP задачами — Junie понимал их хуже, чем стандартный Spring Boot код.
Наивно я попробовал попросить Junie перенести весь старый код приложения разом. Для этого я положил в новый репозиторий папку с legacy-проектом и дал агенту следующий промпт:
Результат был, мягко говоря, далёким от ожидаемого:
Junie сгенерировал лишь пустой файл .output.txt и шаблонный build.gradle.kts. Полноценного переноса не произошло.
Я решил, что, возможно, для Junie это слишком большой объём работы за один шаг. Поэтому попросил его продолжить:
Уже что-то, но всё ещё далеко от полноценного рефакторинга. Например, при переносе Ktor-клиента Junie сделал следующий вариант (старый код можно посмотреть здесь):
Глобально изменений немного, но мне понравилось, что Junie вынес обёртку для запросов в отдельный утилитный класс. Тем не менее это всё ещё был не полный перенос legacy-функционала. Я снова попросил его продолжить:
На этот раз Junie перешёл к UI-компонентам. Например, вот как он переписал экран ошибки (предыдущая версия):
Основная проблема здесь — ресурсы. Junie плохо справляется с ресурсами, а ситуация осложнялась ещё и тем, что в старом проекте мы использовали moko-resources, а при рефакторинге решили перейти на нативные ресурсы Compose Multiplatform.
Ещё один показательный случай произошёл, когда Junie попытался перенести Composable-функцию кнопки с иконкой «Крестик». В изначальной реализации мы использовали ресурс изображения, но Junie по какой-то причине решил его не переносить и вместо этого… нарисовал крестик вручную на Canvas.
Таким образом я постепенно переносил проект, подсказывая и уточняя агенту детали реализации на каждом шаге.
В результате удалось добиться того, что одна полноценная фича приложения заработала. Дальше стало проще: контекст у Junie расширялся, появлялось всё больше готовых примеров, и можно было мигрировать новые части проекта по аналогии.
Результат:
При миграции фичи бронирования переговорных Junie перенёс код и применил мои правила.
Например, он отказался от использования библиотеки MVI Kotlin и перенёс весь MVI-код напрямую в класс компонента. Это сэкономило время на рутинной работе.
Junie реализовал компонент на моковых данных, хотя я передал ему полностью рабочий код. Теоретически агент мог бы использовать его, но вместо этого выбрал упрощённый путь.
Исправлять и дорабатывать такие моменты всё равно пришлось вручную, и это еще раз подсвечивает нам, что Junie стоит воспринимать скорее как помощника, а не как полноценного разработчика.
Отдельной задачей стала миграция со старых java.util.Date и java.time API на kotlinx-datetime для поддержки мультиплатформы. Агент помог найти и заменить большинство вызовов, но не учёл некоторые нюансы: например, не всегда применял уже готовые экстеншены или, не учитывая текущую версию библиотеки kotlinx-datetime, использовал старое API.
Результат:
Junie полезен для ускорения рутинных задач, но без внимания со стороны разработчика он легко может завести в тупик.
В итоге я выработал следующий подход к работе с Junie:
- разбивать задачи на маленькие шаги;
- давать простые и точные промпты;
- собирать большую фичу постепенно, контролируя результат на каждом этапе.
Такой метод оказался надёжнее, чем попытка отдать всё и сразу, приводившая к тому, что Junie упрощал реализацию и часто упускал важные детали.
Также я думаю, что восприятие качества работы Junie сильно зависит от профиля разработчика. Мой основной опыт — мобильная разработка, поэтому я вижу все недочёты агента именно в этой области. Возможно, если бы я был backend-разработчиком на Spring, мне бы тоже не понравилось, как Junie пишет серверный код.
Написание документации
Мы сгенерировали README.md с помощью простого промпта:
Безусловно, после генерации мы сделали многочисленные правки. Однако Junie способен взять на себя создание базовой структуры файла и добавление технической информации.
Аналогичным образом мы сгенерировали и другие файлы, например CONTRIBUTING.md, а затем внесли финальные корректировки вручную.
Gradle-скрипты и bash-скрипты
Мы также использовали Junie для автоматизации деплоя бэкенда на наши серверы.
Junie сгенерировал следующие gradle-таски deployDev и deployProd:
Здесь есть ещё несколько примеров, которые сгенерировал Junie. Они, конечно, предельно простые, но хорошо показывают, что Junie подходит для широкого спектра технических задач.
Плюсы и минусы
Плюсы
- Разработка становится почти диалоговой. По моему опыту, процесс работы с Junie во многом сводится к тому, что я продумываю идею и архитектуру, а агент превращает это в код. Конечно, не всегда всё проходит идеально, но с каждым обновлением качество становится всё лучше.
- Интеграция в IntelliJ IDEA. Junie встроен прямо в IDE, что делает его самым удобным AI-агентом для Kotlin-разработки. Больше никаких бесконечных переключений между idea или в браузер с копипастой из ChatGPT.
- Понимание контекста. Junie отлично ориентируется в проекте, учитывает существующую архитектуру и корректно подстраивается под код-стайл.
- Помощь с интеграцией внешних API. Особенно хорошо агент показал себя при работе с Google Calendar API и другими сторонними библиотеками.
- Детальные планы действий. Перед выполнением задачи Junie строит чёткий пошаговый план, а затем следует ему. Можно наблюдать, какие команды он выполняет в терминале, что делает процесс прозрачным и обучающим.
- Пошаговый прогресс. Приятно видеть, как Junie постепенно решает задачи. Это не только удобно, но и полезно для понимания процесса.
- Тонкая настройка. Поддержка файлов .aignore и .guidelines.md позволяет настраивать поведение агента, ограничивать список доступных команд и даже включать brave mode, при котором Junie может выполнять действия без дополнительного подтверждения.
- Отлично работает с Spring Boot. На серверной части Junie помогает особенно сильно: ускоряет настройку Gradle, генерацию boilerplate-кода и конфигурацию проекта.
- Поддержка Community Edition и Android Studio. Изначально Junie был доступен только в Ultimate-версии IDE, но теперь он работает в Community Edition.
Минусы
- Подписка на Junie. Это не столько минус, сколько фактор, который стоит учитывать: перед началом работы рекомендуется изучить тарифные планы и выбрать наиболее подходящий вариант для вас. Есть и пробный период, чтобы оценить инструмент в работе.
- Скорость работы. Не то чтобы Junie был медленным, но иногда хочется быстрее, особенно на больших проектах.
- Kotlin Multiplatform. В KMP-проектах агент ощущается менее полезным. Если в бэкенде соотношение кода Junie к моему примерно 70/30, то в клиентской части всё наоборот.
- Зацикливание в сложных сценариях. Иногда Junie может бесконечно пытаться починить сборку: меняет код, собирает, откатывает изменения и снова пробует. Хотелось бы иметь возможность давать ему подсказки прямо во время выполнения задачи.
- Недоработки в интерфейсе. Некоторые шорткаты в текстовом поле промпта на macOS не работают, функции .aignore и .guidelines.md спрятаны в неочевидное меню, а управление лицензией и настройками могло быть проще. Но это мелочи, которые пофиксят с апдейтами.
Выводы
Я не проводил строгих замеров производительности, поэтому дальше — только личные впечатления.
Ускорение разработки
При правильном использовании Junie действительно способен заметно ускорить работу. Грамотно составленные промпты и команды экономят массу времени на написание boilerplate-кода.
В среднем, по моим ощущениям, ускорение составляет около 30%, а в отдельных случаях — до 50%. Это не математические расчёты, а практический опыт. Например, на моих пет-проектах Junie позволяет реализовать то, на что раньше уходила неделя, всего за 2–3 вечера. Даже с ChatGPT на тех же задачах процесс был бы как минимум вдвое дольше.
Повторное использование паттернов
Если нужно добавить новую фичу по образцу уже существующей, Junie сокращает рутину почти до минимума. Это позволяет сосредоточиться на архитектуре и логике, а не тратить время на ручное написание однотипного кода.
Создание фич с нуля
Разработка новой функциональности с нуля требует большего контекста и более точных промптов, но даже в этом случае процесс ощутимо быстрее, чем писать всё вручную.
Документация без боли
С Junie написание документации стало лёгким и даже увлекательным процессом.
Обучение и ревью
В образовательном контексте Junie — отличный помощник. Он может быстро и понятно объяснить, что происходит в коде, указать на очевидные ошибки и подсветить возможные улучшения. Для junior-разработчиков это может стать чем-то вроде первого автоматического ревью кода.
Junie не волшебная палочка, но инструмент, который помогает разработчикам сосредоточиться на главном и быстрее достигать результата. В нашем случае он сыграл ключевую роль в ускорении разработки и миграции Effective Office.
Мы верим, что это Effective Office может быть полезен не только нам, но и другим компаниям. Если вы хотите:
- упростить управление офисными ресурсами;
- оптимизировать процессы бронирования переговорных;
- интегрировать корпоративный календарь и автоматизировать рутину;
- или просто внести вклад в open-source —
присоединяйтесь к нашему проекту!
Мы открыты для новых контрибьюторов и всегда рады единомышленникам. Вместе мы можем сделать инструмент, который поможет IT-командам по всему миру работать эффективнее!