Как стать автором
Поиск
Написать публикацию
Обновить

Bubble Tea — TUI-фреймворк для Go. Мои открытия и ошибки

Время на прочтение3 мин
Количество просмотров888

Недавно я наткнулся на Bubble Tea — терминальный UI-фреймворк для Go, и буквально влюбился в то, как он отрисовывает интерфейсы в консоли. В репозитории есть множество примеров — и выглядят они действительно красиво.

Пример возможностей Bubble Tea
Пример возможностей Bubble Tea

Я никак не связан с разработчиками — просто захотел поделиться личным опытом.

Первое открытие: низкоуровневое управление и архитектура ELM

С первого взгляда Bubble Tea выглядит как высокоуровневый фреймворк с красивой абстракцией. Но под капотом он довольно низкоуровневый в плане контроля, и построен на архитектуре, вдохновлённой ELM.

Она основана на трёх основных концепциях:

  • Model — структура, содержащая всё состояние приложения (например, позицию курсора, список элементов, ввод пользователя и т. д.).

  • Update(msg) — функция, в которой можно изменять модель. Принимает сообщение (пользовательское действие или внутреннее событие), возвращает обновлённую модель и (опционально) команду.

  • View(model) — рендеринг интерфейса на основе текущей модели.

Что такое команды?

Команды — это события, которые мы можем генерировать и отправлять сами. Это может быть как пользовательское действие (например, нажатие клавиши), так и произвольная внутренняя структура. В Update они обрабатываются через type switch.

Пример: бесконечный спиннер загрузки

Допустим, нам нужен спиннер с тремя кадрами, которые циклично меняются каждую секунду. Вот как это реализуется в Bubble Tea:

  1. В модели храним текущий индекс кадра и список кадров.

  2. Объявляем кастомную команду type nextFrame struct {}.

  3. При инициализации модели вызываем первую команду nextFrame.

  4. В Update, при получении команды nextFrame, увеличиваем индекс и планируем следующую команду с задержкой в 1 секунду (с помощью утилит из фреймворка).

  5. Фреймворк сам вызывает View при изменениях, а мы в View просто показываем нужный кадр по индексу.

В результате — плавно анимированный спиннер, без явных таймеров и горутин.

Второе открытие: простая параллельность через команды

Команды оказались удивительно мощным инструментом. Например, предположим, нам нужно загрузить 10 изображений с помощью 3 воркеров. В обычном Go мы бы использовали каналы и горутины, но в Bubble Tea можно обойтись всего одной командой:

  • Команда проверяет: есть ли ещё изображения в очереди. Если да — загружает, сохраняет результат, вызывает себя снова.

  • При старте запускаем 3 таких команды — и получаем 3 параллельно работающих воркера.

  • Когда очередь заканчивается, команды просто перестают запускаться.

Это не "классическая" конкурентность Go, но она естественно вписывается в архитектуру UI-приложения, и позволяет сохранять отзывчивость интерфейса.

Третье открытие: вся архитектура — это ELM, и с этим надо смириться

Как только вы начнёте писать что-то чуть сложнее Hello World, всё ваше приложение станет ELM-подобным. Другого пути нет: либо вы принимаете архитектуру, либо постоянно боретесь с ней. Вот что помогло мне на этом пути:

  • Не полагайтесь на нейросети для генерации кода. Большинство LLM плохо справляются с архитектурой Bubble Tea. Код получается нечитаемым. Лучше продумать архитектуру, модель и структуру проекта самостоятельно, а LLM подключать точечно — например, для генерации вспомогательных функций или отладки.

  • Разделяйте ответственность. Выносите ViewUpdate и Model в отдельные файлы. Даже официальные примеры временами тяжело читать без этого.

  • Следите за читаемостью Update. Он быстро может превратиться в 300 строк кода. Используйте вспомогательные методы и выносите обработку отдельных команд.

  • Выносите стили в отдельный файл. Цвета, отступы, рамки — всё это лучше оформить централизованно.

  • Обязательно проводите рефакторинг. Написали рабочую реализацию — сделайте её читаемой. Иначе завтра вы сами себя не поймёте.

Эти советы в целом универсальны, но именно в Bubble Tea их игнорирование быстро делает поддержку невозможной.

Что я сделал на Bubble Tea

Я реализовал визуальный менеджер зависимостей для go.mod, который сканирует зависимости и показывает, какие можно и нужно обновить. Это может быть полезно, потому что стандартный go get -u просто обновляет всё подряд, и часто приводит к тому, что проект перестаёт собираться.

Проект здесь: chaindead/modup

Отдельная статья по проекту

Если у вас был опыт с Bubble Tea — расскажите, как оно? Какие архитектурные приёмы вам помогли?

Теги:
Хабы:
+6
Комментарии2

Публикации

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