Всем привет, меня зовут Саша, я нашёл себя в backend-разработке в возрасте за 30. После 6 лет коммерческой разработки у меня, наконец, хватило всего, чтобы дотолкать свой пет-проект до продакшена. Я сделал Telegram-бота для ведения бюджета за пару месяцев. Мне было интересно сделать продукт полезный себе и другим, руководствоваться подходом business first и использовать любые инструменты для сокращения time-to-market. Читайте что из этого получилось и что нет.
Вступление
У меня экономическое образование и я веду бюджет около 10 лет – в Excel таблицах, приложениях. Мне это не раз помогало вовремя менять работу и так же вовремя перейти в IT. Так что по моему опыту это хороший инструмент для принятия решений в жизни, корректировок трат и выбора времени для поиска дополнительного дохода. В первую очередь я хотел выпустить этот проект в свет, поэтому нужно было успеть это сделать пока есть запал, не углубляться в clean code и свой перфекционизм, использовать все доступные инструменты – ИИ, open source решения, книги, статьи, готовый frontend. Поделюсь своим подходом, решениями и ошибками – от проработки идеи до развёртывания приложения на сервере. Первая часть статьи больше бизнесовая, вторая – техническая. Кому не интересно про бизнес, переходите сразу к главе «Инструменты».
Идея и жизнеспособность
Чтобы не писать мёртворождённое приложение начал с аналитики. Я планировал написать приложение для совместного ведения бюджета семьёй. То есть технически это чат со мной, супругой и ботом, который реагирует на команды. Каждый пользователь может добавить транзакцию, удалить, просмотреть, запросить отчёты. Ведение совместного бюджета в будущем можно развивать в сторону работы с бизнес проектом для совместного ведения смет в небольшой компании. Вторая киллер-фича это автоматическое разбиение позиций чека по категориям. Отправляешь в чат бота электронный чек и он раскидывает все позиции по категориям за тебя. Это потенциально интересные функции, которые выделяют бота на фоне конкурентов и за которые я бы сам платил.
В целом рынок бюджетных приложений сейчас есть, хоть и небольшой. Больше это актуально для семей и людей со сложной системой доходов, расходов, кто любит контролировать свои финансовые потоки, а не пускать на самотёк.
Из конкурентов в этой сфере в основном приложения. Каких-то внятных и удобных Telegram-ботов я на тот момент не нашёл.
Провёл поверхностный анализ, пару вечеров прорабатывал бизнес-модель и риски с ИИ. В итоге получил примерно, что хотел. В лучшем случае я сделаю бота и со временем смогу зарабатывать небольшие деньги на платной подписке. В худшем потрачу своё время, но получу опыт создания цифрового продукта от А до Я. Каждая ошибка – в копилку опыта.
На этапе анализа конкурентов я сильно был воодушевлён своей идеей, что понизило критичность мышления. Люди и так подвержены confirmation bias (предвзятости подтверждения), а я на этом этапе использовал ИИ для подтверждения своей идеи, а не для её краш-теста. Я не оптимально использовал этот инструмент, не прошёлся глубоко по конкурентам в Telegram, не сравнивал фичи и не попользовался ими прежде чем продумывать MVP. Перед следующим релизом я выделил для себя пару ботов и пару Android-приложений помимо того которым пользуюсь сам. Попользуюсь ими, посмотрю фичи и реализации, чтобы закрыть ошибку этого этапа.
Позиционирование и монетизация
У меня уже был опыт создания и продвижения паблика ВК около 10 лет назад. Брендинг, узнаваемый стиль, оформление. Развил его с 0 до 10 тыс. подписчиков где-то за полтора года и в итоге продал (себе в минус, но это опыт). Позиционирование бота я вижу следующим: это приветливый антропоморфный робот, ваш личный помощник для ведения бюджета. Люди в целом больше доверяют человекоподобным персонажам. Робот должен располагать к себе и подсознательно внушать человеку, что вести бюджет просто. Сгенерировал промт через лингвистическую модель для генерирующей изображения модели. Перепробовал много разных вариаций, но прямо в точку ничего не попало. Вспомнил пелевинский Random Code Programming – когда пытаются получить что-то валидное запросу путём множества повторений. Реальность догнала литературу. Нынешний образ робота-помощника получил побочным продуктом, когда создавал изображение для build in public канала.
Мысли по названию крутились вокруг отсылки к фильму «Где моя тачка, чувак», звучало как Where is my money, mate? Это концептуально подходит для приложения по ведению бюджета. По поиску в Telegram узнал, что я не один такой оригинальный. Поиграл с аббревиатурой и смягчающими суффиксами – остановился на Wimme.
Сразу в общих чертах прикинул монетизацию. Самое очевидное – freemium подписка. Базовый функционал бесплатно, а фичи для удобства и автоматизации – за деньги. Тут главное сразу разделить фичи по подпискам, чтобы избежать ситуации, когда бесплатная функция становится платной. Психологически пользователи это плохо воспринимают, будто ты что-то забрал у них. В их сознании ты уже сформировал ценность фичи и обычно такие решения сопровождаются негативом.
Для названия оптимально, чтобы оно отражало суть проекта. Иногда лучше без креатива, но понятно. Но я выбрал вариант с персонажем бренда, из минусов – пришлось в шапке добавлять разъяснение, что это про ведение бюджета. Перед тем как брать в работу название лучше пробежаться по интернету – скорей всего до вас уже кто-то это придумал. Я изначально думал назвать бота WIMMly, даже завёл бота с таким названием @wimmly_bot. Оказалось есть такая IT-компания.
Помимо этого, с фичами я пожадничал и обделил MVP уникальностью. Хотел сберечь совместное ведение бюджета для платной подписки, в итоге сейчас бота ничто не выделяет среди конкурентов. Бесплатно сделаю совместный бюджет на двоих в одном чате, а больше участников можно будет добавлять в платной подписке. Иначе зачем людям бот без добавочной ценности?
Инструменты
Использовал знакомый мне стек из Kotlin, Spring Boot, Spring Data JPA, миграции на liquibase, Postgres – чтобы не тратить время на изучение нового.
В качестве прослойки между бизнес-логикой и Telegram взял open source решение из этой статьи на Хабре. Адаптер тоже написан на Kotlin+Spring Boot, но добавляет неоднородности стека за счёт JOOQ и flyway миграции. Тут я жертвую единообразием технологий в пользу скорости – такова плата за использование чужих решений.
Чаты с ИИ-агентами (Deepseek, ChatGpt) – не так удобно, как встроенные в IDE решения, но работает из коробки, хоть и не с первого раза получаешь желаемое. Deepseek генерирует тонны кода, а ChatGpt в последнее время выдаёт просто реализацию методов, игнорируя классы и внедрение зависимостей. Поэтому приходится лавировать между ними.
В проработке архитектуры я руководствовался подходами из книги Криса Ричардсона «Микросервисы. Паттерны разработки и рефакторинга» – взял на вооружение проработку доменной модели и системных операций, подробнее в следующей главе.
Про business first подход уже писал – стараюсь компромиссно уменьшить time-to-market: жертвую чистым кодом и best practice, затаскиваю небольшой зоопарк пересекающихся технологий (миграции flyway и liquibase, Hibernate и JOOQ). Позже можно привести миграции к одному виду, а пока коплю техдолг.
Архитектура
Крупными мазками набросал доменную модель (основные сущности) будущего бота и системные операции (как они будут между собой взаимодействовать):
1. User – базовая сущность пользователя, из под неё происходят все бизнес-операции. В качестве идентификатора пользователя на этапе MVP использую chatId Telegram, на который завязаны транзакции и контекст диалога.
2. Transaction – домен-ядро любого приложения для бюджета. Большая часть системных операций завязаны на транзакциях. От базового CRUD до отчётов по периодам.
3. Category – категории доходов и расходов. Использую при создании и отображении транзакций, в отчётах для детализации по категориям.
4. Dashboard – главное меню, не отдельный домен, а скорей точка входа в приложение.
Это не финальная модель, а рабочая схема для MVP, позволяющая определить основные сценарии и границы ответственности. Да и разрабатывать проще по такой схеме, чем вообще без неё.
Приложение разделил на два сервиса: Telegram-адаптер (tg-bot) и сервис бизнес-логики (budget). В коде это монорепозиторий с двумя модулями на базе форка telegram-bot-kotlin-template. Архитектура приложения сейчас – распределённый монолит из-за высокой связанности и созависимой эволюции контрактов. Изменение API всегда затрагивает оба модуля. Но создал задел на микросервисы – разделение ответственности, отдельные модули, независимые БД, раздельный деплой.
Telegram-адаптер выступает как слой взаимодействия с пользователем и оркестрации диалога, а business-logic сервис – как точка выполнения бизнес-операций и хранения данных. База данных адаптера запоминает контекст диалога с пользователем и очищает таблицы после передачи данных в БД сервиса бизнес-логики. Обмен данными происходит по REST. Пока модель упрощённая, без ретраев и гарантий доставки.
Обработка пользовательских команд реализована как пошаговый сценарий (state machine): адаптер хранит состояние диалога и управляет переходами между шагами, а бизнес-логика выполняется в отдельном сервисе. Это позволяет управлять сложными сценариями и получать данные от пользователя последовательно, а не одним сообщением со сложным парсингом.
Про адаптер уже есть статья автора, так что тут опишу только вкратце. Сервис взаимодействует с Telegram по long-polling. После получения апдейта от Telegram адаптер формирует событие и передаёт его в обработчик, где определяется текущий шаг сценария и вызывается соответствующая логика. Простые команды сразу совершают действие – например, команда /help выдаёт информацию как пользоваться ботом. Сложные команды состоят из нескольких шагов, на которых собираю данные в контекст-таблице перед отправкой запроса в budget-сервис.
Фичи MVP
Как выглядит итоговый прототип:
1. Работа с пользователем
-
Регистрация
-
/help команда (онбординг)
-
/info команда (канал обратной связи, о разработчике, build in public канал про разработку бота и ведение бюджета)
-
/commands — список команд
2. Работа с транзакциями
-
Добавление дохода\расхода
-
Поиск
-
Удаление
3. Отчёты
-
Баланс
-
Отчёты по периодам – сегодня, текущие неделя, месяц, год
Ключевым моментом было соблюсти баланс функционала и сроков разработки. Честно говоря, по прошлым пет-проектам боялся просто забросить всё, если слишком затяну с реализацией. Поэтому сделал самый минимум и не усложнял, чтобы в следующих релизах добавлять новые фичи, перерабатывать функционал, UX/UI. К тому же, хотел протестировать гипотезу на реальных пользователях, собрать обратную связь, чтобы понимать куда дальше развивать бота.
Даже то, что сделал в MVP сильно урезано. Редактирования как отдельной команды нет, вместо него удаление и создание новой транзакции. Поиск по транзакциям упрощённый – только последние 10 по категории. Руководствовался тем, что чаще всего он используется при поиске номера транзакции для удаления и обычно удалить нужно последнюю транзакцию с опечаткой.
Отчёты по периодам только текущие – за текущий день, неделю, месяц, год. Иначе пришлось бы добавлять парсинг интервала дат. Отчёты по конкретным категориям тоже обошёл – в отчёте за период выдаю детализацию по категориям в абсолютных (руб.) и относительных (%) показателях.
Важный и неочевидный момент, который я в процессе оценил выше чем update транзакции – обработка ошибок и проброс сообщений пользователю. Без этого пользователь при невалидном вводе даже не понимал, что произошла ошибка и что от него требуется дальше. В итоговом варианте пользователь получает сообщение с описанием ошибки и остаётся на текущем шаге пока не введёт валидное значение. Это звучит просто при вызове с клиента API бэкенда, но я взял адаптер со state machine и вписать туда шаг с обработкой ошибки оказалось сложнее. Для пользователя молчаливые ошибки гораздо больнее, чем update через delete+create.
Что я сейчас сделал бы по-другому. Чётко обозначил список доработок и старался бы придерживаться его. У меня было примерное представление, что я хочу видеть в прототипе. Я что-то добавлял, что-то убирал, упрощал, когда начинал буксовать. В итоге бэклог рос, а MVP ужималась в процессе разработки. В следующем релизе я уже закладываю больше времени на подбор и анализ фич, личного опыта использования бота, обратной связи от пользователей и анализа конкурентов. Лучше уделю время планированию, чем по ходу разработки буду хаотично выкидывать или упрощать функционал. Такие моменты всё равно будут, но цель именно минимизировать их.
В сухом остатке текущий вид бота – утилитарный прототип без уникальности на фоне конкурентов, «это то, что должно превзойти» словами Ницше. Некий путь до развилки, от которого можно отталкиваться.
Реализация
Проработка доменной модели и системных операций позволила мне за пару вечеров промтинга в Deepseek написать стартовый функционал бизнес логики (budget-service) и покрыть его тестами. API и их логика соответствуют схеме доменной модели – работа с пользователем, транзакциями, категориями и слой агрегации данных для отчётов. Я опустил в MVP только меню с кнопками, т.к. его аналог даёт сам Telegram (кнопка меню с выпадающими командами у строки ввода).
Было самому интересно насколько справится ИИ-инструмент с такой задачей, плюс рассчитывал ускорить разработку. Где-то приходилось направлять Deepseek в нужное русло, где-то проще было исправить руками. Для CRUD, простых операций и шаблонного кода в самый раз, но под человеческим контролем. Качество работы ИИ во многом зависит от самой модели и точности промта, но повлиять я как пользователь мог только на второе.
Что сразу не учёл и пришлось дописать позже – логика формирования числовой последовательности при нумерации транзакций. Она нужна для их удаления и в будущем для редактирования. Поэтому у транзакции помимо id (UUID), user_id (Telegram chat_id) есть ещё display_id – порядковый номер транзакции для выдачи пользователю. Это более user friendly, чем UUID. В будущем думаю отказаться от UUID вообще в пользу составного ключа userId+displayId. Чтобы порядковые номера транзакции изолировать между пользователями пришлось завести таблицу для хранения по user_id его текущего значения порядкового номера транзакции. Номер всегда идёт только вперёд, не уменьшается даже после удаления транзакции. Потенциальные гонки при параллельных апдейтах я для MVP не обрабатывал – сценарий добавления транзакции линейный, и вероятность конфликта минимальна за счёт многошаговых процессов.
Вот и вся бизнес логика базового бота по ведению бюджета – пара абзацев, да и только. В этой части ИИ нормально справился с простым кодом, а проработка доменной модели на предыдущих этапах позволила дать ему более чёткое техническое задание.
Несколько вечеров заняла проработка бизнес-модели, пара вечеров на продумывание архитектуры и реализация бизнес логики. Откуда взялись 2 месяца разработки? Всё остальное время ушло на изучение как работает open source адаптер для Telegram бота и накручивание своей логики на него. Как работает ядро логики сервиса Telegram адаптера описано в статье его создателя, я рассмотрю его больше со стороны готового решения для использования в своём проекте – что оно дало мне и какие ограничения наложило.
Про то, как создать своего Telegram бота через @BotFather можно почитать в официальной документации по ботам, а тут про Telegram Bot API.
Сервис-адаптер – это finite state machine. Я не сталкивался раньше с FSM, пришлось разбираться отдельно. Это модель с фиксированными состояниями и переходами между ними по событиям, в моменте она может находиться только в одном из состояний. Такой подход отлично ложится во взаимодействие пользователя с Telegram-ботом. В отличие от REST, пользователь вводит данные последовательно, и система должна помнить контекст диалога. Каждый шаг (Step-класс) определяет следующий, а состояние пользователя хранится в базе (таблицах контекста диалога). Это позволяет реализовывать сложные сценарии (создание транзакции, поиск по фильтрам) без парсинга одного длинного сообщения.
Внешним инициатором запуска логики выступает long-polling update от Telegram, но внутри адаптера переключение шагов работает через Spring-events.
С точки зрения расширяемости, это удобно – добавляешь новую команду, нужные шаги, их последовательность – дальше всё делает state machine. Как и пишет автор адаптера – нужно только продумать и добавить свою бизнес-логику. Из того, о чём не пишет – нужно время на понимание работы FSM и архитектуры адаптера.
Сервис tg-bot (адаптер) использует Template Method, базовая логика задаётся в абстрактном родительском классе, а нюансы поведения потомков определяются либо переопределением этих методов, либо реализаций методов-хуков. Такой подход я использовал и для решения проблемы вызова бизнес-команд до регистрации пользователя через команду /start. Это неочевидный сценарий – запрос баланса до регистрации, но фактически я ловил этот баг при тестировании. К тому же система должна быть устойчива к неправильному порядку действий пользователя. Вынес проверку существования пользователя в обеих базах данных в AbstractCommand, от которой должны наследоваться все команды сервиса и запретил переопределение этой логики. Для реализации своего поведения потомкам оставил хук doPrepare().
Вообще Command-классы отвечают за оркестрацию в сервисе, Step – за управление состоянием, а Chooser – за обработку пользовательского ввода. Для генерацию сообщений пользователю отвечают Message-классы. Через шаблонизатор Freemarker и ftl файлы обеспечивается их вёрстка. Я оценил это решение для больших сообщений с динамическими данными. Благодаря нему в коде нет многострочных строковых шаблонов, разделён код и UI-сообщения. Для однострочных сообщений при этом можно использовать простые Java строки, чтобы избежать оверхеда.
Open source решение сильно сократило мне time-to-market, но и досталось не бесплатно по времени. Сама статья автора это не step by step гайд, поэтому пришлось добавлять много логов, загружать целые классы в Deepseek, чтобы разобраться с движением данных в сервисе. ИИ как инструмент разбора чужого кода неплохо справился, но мелкие нюансы от него ускользали, приходилось додумывать биологическим мозгом.
В итоге, адаптер со state machine усложняет код и отладку, требует хранить контекст, но упрощает добавление бизнес-команд. Такой подход окупается на большом количестве сценариев и при переиспользовании шагов в них. Для простого бота это точно будет излишняя сложность. Как раз из-за сложной отладки я оставил на потом DSL-тестирование сценариев (тестирование в формате user stories, как в Cucumber). По мере изучения кода адаптера я писал себе пошаговые инструкции по добавлению новых сущностей – команд, шагов с кнопками и без, что позже мне помогало быстро вспомнить как их добавить. Это заняло не мало времени, но сам бы я точно потратил больше на реализацию прослойки между Telegram и бизнес-логикой. И вышло бы более костыльно, так что по итогу это оказалось правильным решением, хоть и не полностью из коробки.
UX/UI решения
В MVP отказался от меню, которое было на схеме с доменной моделью. Решил пока достаточно будет просто вызова Telegram команд через слэш (/start, /balance, /help). Но спустя месяц использования бота уже чувствую, что меню удобнее. При базовом вызове списка команд пользователь сразу видит только 4 их 13 доступных. Я вынес вверх часто используемые, но всё равно на виду только около 30% команд. О нижних командах пользователь может и не знать, хотя при первом старте я выдаю онбординг сообщение по пользованию ботом. Я даже получал такую обратную связь – пользователь удивился, когда узнал про отчёты за период. И тут даже проблема не в боте, а в обобщённом решении платформы в этом аспекте. И это уже моя задача придумать решение, как показать пользователю весь функционал своего продукта. Если пользователь не знает о фиче – для него её нет. Меню поможет на одном экране показать весь доступный функционал с разбивкой по разделам.
Статические данные вынес в кнопки. Например, пока предоставляю готовый список категорий – это помогает стандартизировать их, унифицировать этот шаг для всех пользователей и избежать валидации кастомных пользовательских категорий. Исключаю опечатки на этом шаге и избегаю большого количества разношёрстных названий. К тому же ускоряет добавление транзакции – быстрее тапнуть по кнопке, чем каждый раз вводить категорию вручную. Я часто на ходу добавляю расходы, поэтому стремлюсь максимально упростить и ускорить этот процесс.
Предусмотрел возможность пропустить необязательные шаги при создании транзакции. В этом процессе обязательно нужен тип (доход/расход), категория и сумма. В большинстве случаев подходит текущая дата, но бывает необходимо добавить прошлую трату. Комментарий на логику не влияет, но иногда нужен пользователю, чтобы отличать их между собой.
После активного пользования ботом решил пересмотреть подход к необязательным шагам в сторону builder-a. После введения обязательных шагов предлагать кнопки на выбор:
|ввести дату|ввести комментарий|готово|
Это уберёт 2 лишних клика и создать транзакцию можно будет всего в 3. Так я перейду от линейного сценария к смешанному – обязательные шаги останутся линейными, а глубину ввода необязательных данных пользователь определит сам. Я, например, комментариями пользуюсь часто, но вот вводом даты почти никогда.
В отчётах за период добавил детализацию по категориям, но скрыл её под Telegram-спойлер. Так я даю общие данные по доходам и расходам сразу, а более подробные не создают инфо-шум. Сейчас у меня 4 категории дохода, 14 расхода и они будут пополняться. То есть больше 20 строк со сложными данными (название, сумма, доля в процентах), которые не нужны тебе каждый раз. Но когда нужны – они в одном тапе от тебя.
Валидацию пользовательского ввода (суммы, даты, длины комментария) решил гармонично вписать в существующую архитектуру адаптера и сделал отдельным Step-классом. Суть его работы в том, чтобы сообщить пользователю об ошибке и запросить данные заново. Пользователь должен знать о самом факте ошибки, понимать в чём она, сценарий не должен ломаться.
Некоторые мои первоначальные гипотезы подтвердились, некоторые нет. Но негативный результат тоже приносит пользу. На основании своего опыта и обратной связи пользователей я добавил в бэклог ряд улучшений и новых гипотез по UX/UI. Например, билдер для необязательных шагов, да/нет кнопки в один ряд, попробовать разместить кнопки категорий по 3 в ряд, весь текст в UI перевести на русский, добавить возможность ввода суммы как математической операций в калькуляторе (1+2-5*4). Самые важные на мой взгляд возьму в ближайший релиз.
Ошибки и грабли
Не все решения в процессе разработки были удачными. От некоторых я вовремя отказался, зафиксировав убытки по времени, некоторые оставил в компромиссном варианте, а какие-то решения вообще вышли за рамки кода и архитектуры. Подробнее остановлюсь на них.
Ушёл в оверинжиниринг. Разрабатывал по доменной модели CRUD транзакций и решил объединить в команду /manage_transactions поиск, редактирование и удаление. Все три затрагивают поиск. Сначала это выглядело хорошо – вместо трёх команд сделаю одну, смогу переиспользовать логику поиска. Да, с нарушением единичной ответственности, но зато пользователю удобнее. Реализация этой команды требовала сразу затащить в проект карточки транзакций с кнопками редактирования/удаления у каждой и постраничный вывод из-за ограничения Telegram около 100 inline-кнопок на сообщение. Убил на реализацию несколько вечеров, но в итоге пока решил отказаться от этого. Взамен сделал /search_transactions, /delete_transaction, а редактирование оставил не user friendly – через удаление транзакции и создание новой. Поплатился временем за попытку перескочить с прототипирования на production ready уровень продукта. Так что, если фича слишком сложная в реализации – скорей всего она не для MVP, либо её нужно разбить на несколько итераций.
Молчаливое проглатывание ошибок. В адаптере изначально не было функционала обработки ошибок и информирования о них пользователя. Я описал как частично это решил для предусмотренных мной ошибок валидации. Но непредвиденные серверные ошибки всё ещё остаются молчаливыми. Со стороны пользователя такая ошибка выглядит как сломанный продукт. В будущих релизах решу это через общий перехватчик ошибок.
Удаление транзакции по номеру. Текущий процесс удаления транзакций кривой – пользователь не должен запоминать данные между командами. Сейчас нужно найти транзакцию через /search_transactions, запомнить её номер и затем ввести в /delete_transaction. Я постарался минимизировать боль от этого процесса – удалять по порядковому номеру транзакции, а не по UUID. Но это всё равно технический костыль плохого процесса.
UI на двух языках. На бэта-тестах мне каждый пользователь указал на кнопки на английском. Я понимал нарушение консистентности интерфейса, но не придавал этому такого значения в прототипе. Считал функционал и время важнее. В итоге сэкономил на парсинге enum категорий при генерации кнопок, но пропустил в MVP то, что врезается в глаз каждому пользователю.
Open source решения не такие быстрые. Хотя telegram-bot-kotlin-template архитектурно хорошо продуман и основное взаимодействие с Telegram берёт на себя, всё равно ты тратишь время на reverse engineering, потому что пользоваться таким open source ты можешь только после понимания внутренней модели и процессов.
Человеческий фактор. На разработку ушло 2 месяца, но по календарю прошло 4. Половину из них я не открывал проект. И дело даже не в лени, а в отсутствии внешнего давления. Дедлайны я не ставил, никому кроме себя не обещал довести проект до развёртывания. Мои предыдущие pet-проекты скорее всего поэтому и остались недописанными – не было для кого я их делаю, не было конкретных use case. Чтобы избежать такого в будущем, я начал вести build in public (дневник разработки) в Telegram канале. Взял на себя социальную ответственность за проект, чтобы забросить бота было сложней. Так я искусственно ставлю себя в такую ситуацию, когда моя неудача (отказ от проекта) станет публичной. Это подстёгивает меня писать код и тексты о создании продукта.
В момент принятия этих решений они казались приемлемыми, но в итоге сейчас они стоят первыми в списке на доработку. В большинстве случаев ошибка была в выборе компромисса между скоростью разработки, сложностью и UX.
Тестирование
Unit-тесты в основном генерировал через ИИ и дорабатывал вручную. Их основной целью была фиксация контрактов и проверка базовой логики, чтобы при изменениях быстро локализовать проблему.
Интеграционные тесты для MVP положил в бэклог. Планирую писать полноценные DSL-сценарии в формате user story, чтобы тестировать команды end-to-end. По трудозатратам сопоставимо с отдельным модулем, так что не стал из-за тестов откладывать релиз. Пока их заменил ручным тестированием сценариев, на это ушёл отдельный вечер.
Бэта-тестирование шло около месяца. Я рассчитывал на 20 пользователей, 7-10 из которых будут вести учёт в боте хотя бы неделю. Но по факту активно пользуюсь только я, ещё несколько человек протестировали отдельные сценарии и дали обратную связь. Основная нагрузка в тестировании и использовании продукта пока остаётся на мне, как видно по количеству транзакций за месяц.
Деплой
Для развёртывания бота рассматривал VPS и managed cloud сервисы, взял виртуальный сервер за 4,49 евро/мес. с 2 RAM, 1 CPU и 30 Гб HDD. Основная причина – ниже стоимость. Да, облачные решения упрощают деплой и эксплуатацию, дают сконцентрироваться на продукте. Но на раннем этапе это повышенные регулярные расходы без подтверждённой ценности. Виртуальный сервер потребовал больше времени на настройку, но дал больше контроля и снизил ежемесячные расходы. Чтобы компенсировать отказ от managed-инфраструктуры, упростил процесс развёртывания:
1. сборка java-модулей
2. создание из них докер образов и пуш в docker hub
3. подготовка docker-compose файла с этими образами + по бд на сервис + указываю ENV файлы
4. подготовка ENV файлов для чувствительных данных (хранятся не в Git)
5. переношу по ssh на сервер docker-compose и ENV файлы, делаю «docker compose up -d»
Из текущих компромиссов – публичные GitHub репозиторий и Docker Hub. Пока бот бесплатный – это допустимо. На текущем уровне развития продукта CI/CD был бы оверинжинирингом, поэтому сконцентрировался на удобном процессе развёртывания. Из плюсов – деплой полностью завязан на Docker, не нужно переносить артефакты на сервер, независимое развёртывание сервисов. Базовая изоляция тоже есть – сервисы и БД общаются внутри docker-сети и не доступны извне. Обратная сторона – это всё ещё ручной деплой и отсутствие удобного мониторинга, логи и данные приходится смотреть через консоль.
Заключение
Изначально я рассматривал бота как продукт, поэтому постарался примерно оценить во сколько мне обошлась разработка MVP.
Оценивать по количеству коммитов или строкам кода неправильно, т.к. вес коммита «upd README» и «add balance command» разный, как и вес строк кода DTO и бизнес-логики. Самый близкий подход это тот самый «мифический человек-месяц». Взял диапазон зарплат 250-300 тыс.руб./мес. – думаю разработчик на такой вилке вполне справится с реализацией подобного бота. Беру 22 рабочих дня по 8 часов и получаю 1421-1705 руб./час. Опущу тут как я проходился по каждому коммиту и примерно оценивал сколько у меня ушло времени на него, а также на проработку бизнес составляющих и архитектуры. По моим подсчётам за 2 месяца разработки я потратил около 113ч. Добавлю тут ещё пару дней для корректировки погрешности и округлю до 130ч. Итого стоимость MVP в диапазоне 185-222 тыс. руб. – примерно месяц full-time разработки. Такая оценка даёт осязаемость инвестиций времени и ресурсов и закладывает базу для расчётов окупаемости в будущем.
Реализация бизнес-логики бота заняла 10% от всего времени разработки и 90% инфраструктура вокруг неё – адаптер, UX, сценарии взаимодействия и отладка. Все доработки и сложность содержатся в сервисе адаптера, а budget сервис по сути является поставщиком данных и их агрегации. Часть этого времени ушла не на написание кода, а на reverse engineering выбранного open source решения. Такое решение действительно ускорило выпуск продукта, но не так сильно, как я ожидал. То есть ценность с одной стороны содержится в бизнес-логике, но сложность в организации взаимодействия с пользователем и интеграциях.
ИИ как инструмент в этом проекте снял с меня написание большого количества шаблонного кода и ускорил разработку. Я даже обсуждал некоторые архитектурные решения, но всё равно окончательное решение и ответственность за них остаётся на мне. Тут важно сохранять критичность мышления. С более сложными процессами ИИ чаще не справлялся – тогда от него я брал базовый уровень и на более продвинутом уже докручивал сам. То есть пользоваться как инструментом с пониманием его ограничений можно и даже получать профит.
Этот проект показал мне, что в первую очередь на пользовательский опыт влияют недоработки на этапе анализа конкурентов, планирования фич и UX, а не технические решения. Ошибки на этих этапах бросаются в глаза сразу, а реализация остаётся под капотом.
Сейчас бот решает базовые задачи учёта расходов, в нём есть технические костыли, компромиссы в UX и недоработки продуктовой части. Но именно в этом и состоит задача прототипа – на раннем этапе обнаружить критичные ошибки, протестировать гипотезы, собрать реальную обратную связь. Дальше фокус смещается на улучшения: довести UX до удобного состояния, добавить совместное ведение бюджета и постепенно превратить прототип в полноценный продукт.
ссылка на оригинал статьи https://habr.com/ru/articles/1031128/