В предыдущих статьях я уже разобрал личный опыт вхождения в IT, когда это еще не было мейнстримом, а также привел советы по увеличению откликов на ваше резюме. Всего я запланировал 7 статей в серии помощи поиска работы в IT для начинающих специалистов.
Собесбот — это Telegram-бот для подготовки к собеседованиям для специалистов уровня Junior, Middle, а также для тех, у кого нет коммерческого опыта в IT. В этой статье я разберу принцип работы бота, почему я решил его сделать, и трудности, с которыми я столкнулся при разработке.
На данный момент есть оценка и рекомендации по: C#, Java, Kotlin и JavaScript. В целях добавить Python, конечно же.
Зачем?
Количество выпускников онлайн-школ продолжает расти, однако многие сталкиваются с трудностями при поиске первой работы в IT. Да и джунам, у которых есть небольшой опыт приходится несладко (статистики у меня нет, просто по общим наблюдениям в соц. сетях). У них встает резонный вопрос: Как подготовиться к собеседованию в IT? Хотелось сделать продукт, от которого будет польза при подготовки к собесам, но который бы обходился для меня минимумом затрат.
Кроме того, хотелось разработать свой продукт от идеи и до запуска. В итоге, в ходе разработки я испытал все, даже хайринг людей в команду.
Почему именно бот в Telegram?
Как любой разработчик с опытом, я наслышан о кладбище пет-проектов. Люди начинают писать пет-проекты, которые так и остаются незаконченными. У меня таких есть тоже. Именно поэтому я какое-то время вообще избегал разработки своих проектов. Основная проблема, с которой я сталкиваюсь при разработке проектов — склонность к усложнению, углубление в детали, что в итоге приводит к потере мотивации. В этот раз мне очень хотелось углубиться в разработку. Но я решил пойти по пути наименьшего сопротивления. Один из моих страхов — это фронтенд-разработка. Поэтому я решил делать frontendless решение. К тому же, Telegram бот — удобный формат для пользователей. Не нужно скачивать мобильное приложение или открывать сайт. И с точки зрения разработки меньше шансов на оверинжинирить. К тому же опыт разработки Telegram ботов и желание применить AWS в реальном продукте также повлияли на мой выбор.
Все начиналось со скрипта
В 2021 году я сделал мини-курс по подготовке к собеседованиям. Это были 4 насыщенных вебинара, каждый из которых включал практические задания для закрепления материала. Мой первый продукт, в который я вложил много души. Возможно, именно после него я и выгорел. Запустил курс один раз, но дальше дело не пошло. В этом году я пересмотрел материалы курса и понял, что многие концепции остаются актуальными и полезными даже сейчас. В курсе был скрипт для генерации квизов с вопросами для собеседований на Google Forms. Он случайным образом собирал вопросы из большой базы вопросов с группировкой по областям. Готовые формы я скидывал участникам. У каждого был уникальный набор вопросов и на основании результата можно было определить какие области и навыки стоит подтянуть. На основе этого скрипта и родилась идея создания бота в Telegram для подготовки к собесам.
Принцип работы
-
Пользователь регистрируется в боте, указывает свою специализацию и уровень.
-
У него есть возможность определить свой уровень с помощью скринингов (доступно 9 специальностей).
-
Скрининг — это серия тестов в Google Forms. Обычно это от 14 до 17 тестов с 4-11 вопросами каждый. Вопросы охватывают определенную область знаний. Например, это может быть LINQ для C# .NET или Firebase для Android. Пользователю нужно ответить на вопросы, которые бывают разного типа: одиночный выбор, множественный выбор, сопоставление, или вопросы с коротким текстом.
-
После прохождения каждого теста пользователь возвращается в бот и переходит к следующему шагу. Можно пропустить тест или остановить скрининг. Прохождение скрининга можно завершить только один раз, без временных ограничений.
-
По итогам скрининга бот создает разбивку по навыкам, показывая, какие области нужно подтянуть. Главная фича для новичков — это персональные рекомендации на основе результатов. Они включают статьи, видео, бесплатные курсы, код и документацию.
-
Также можно запросить мок-собеседование (пока доступно только по .NET) и карьерную консультацию. Я выступаю в роли ментора.
-
С прогрессом и прохождением нескольких скринингов профиль пользователя наполняется новыми навыками, и рекомендации становятся более точными.
-
Навигация в боте происходит через inline-кнопки, и все взаимодействие строится по принципу «одно сообщение в момент времени». Это очень похоже на обычный SPA или мобильный клиент. Есть текущее View и мы можем переходить из него на другие.
Выбор стека
Для начала оговорюсь, что это мой первый бот в Telegram. Я никогда раньше работал с AWS. И первый раз нанял разработчика для совместной работы над своим проектом. Что оказалось не такой плохой идеей. Ну и в заключении, я выбрал Shift-right testing, чтобы не тратить время на интеграционные тесты и поскорее зарелизить бота.
Самый близкий мне язык и фреймворк это C# и ASP.NET Core. При выборе инфраструктуры руководствовался минимизацией затрат и масштабированием. Для взаимодействия с ботом выбрал вебхуки. Каждый Update обрабатывает ASP.NET Core приложение задеплоеное на AWS Lambda. В качестве БД Amazon DynamoDB. Выбор пал в пользу этих сервисов в силу больших лимитов во Free Tier и желания написать свой пет-проект на AWS. Выбрал GitHub как систему контроля версий и Notion в качестве трекера задач. Деплоил со своей машины.
Итого внешних зависимостей:
-
AWS Lambda
-
DynamoDB
-
Google Forms
-
Telegram API
Разработка
Разработка началась в мае 2024-го года. На протяжении всего лета я посвящал свободное время разработке этого бота. Первый бот был готов уже через 3 дня. Он повторял логику скрипта по генерации опросника . Как человек, в первый раз написавший бота в Telegram, да еще и в первый раз слепил что-то в AWS я безумно радовался.
Интеграция с Google Forms
Однако, потом я начал думать над следующими шагами и пришел к цепочке неприятных рассуждений.
Проблема №1
Если мы генерируем тесты в Google Forms из базы, то как избежать дублирования вопросов и при этом обеспечить откалиброванную подборку по сложности?
Решение: Я понимал, что риску попасть в ловушку усложнения. Решил не генерить тесты на лету, а заранее создавать наборы, сгруппированные по специализации. Но это пораждает новую проблему — по какому принципу группировать вопросы в тесте?
Также встал вопрос, насколько будет удобно пользователю переключаться между Google Forms и Telegram? Вместе с этим следующая проблема:
Проблема / Вопрос №2
А почему Google Forms, если Telegram дает возможность создавать квизы?
Ответ: К сожалению, в квизах можно использовать только вопросы с одиночным выбором. Нет сопоставлений, короткого текста и множественного выбора. Google Forms дает возможность удобного хранения и управления вопросами, их быструю и легку правку, а также просмотра статистики ответов. Отвечает принципам frontendless.
Ничего не оставалось как смириться с потенциальными неудобствами для пользователей. Конечно же, такое сомнение толкает к следующему вопросу:
Проблема / Вопрос №3
Почему бы не сделать веб или мобильное приложение, где нет ограничений?
Ответ: Я старался избегать фронтенд-разработки, чтобы минимизировать риск попадания в ловушку избыточной сложности. Я решил не изучать новую технологию, чтобы не растягивать сроки разработки. К тому же, Telegram бот довольно удобный формат для пользователей — всегда под рукой и не надо скачивать.
Казалось, что разработка бота с использованием внешней зависимости в виде Google Forms — это гиблое дело. Но, следуя принципам frontendless приложений, чтобы не увеличивать срок разработки на изучение фронтенда и дизайн сайта, а быстрее выпустить MVP — я решил рискнуть.
Многие пользователи, особенно из мира IT любят оставлять минимум информации о себе. Соответственно,лучше не запрашивать дополнительные данные, например логин в Google аккаунт при ответе на вопросы в квизе. Скорее всего, это не самый приоритетный запрос, который стоило брать в разработку. Но я его взял.
Проблема №4
Как сопоставить ответы пользователя в форме без аутентификации в Google Forms?
Решение A: Копировать квиз для каждого пользователя и отдавать ссылку на уникальный квиз. Это решение полностью решает проблему. Однако это дополнительный запрос к API Google Forms для создания дубликата формы. Со временем бесполезных форм становится все больше и нужна будет периодическая чистка Google Drive.
Решение Б: Использовать prefillLink с предзаполненным поле в форме. Это текстовое поле содержит идентификатор квиза в базе данных, по которому мы сопоставляем ответы пользователя и квиз. Тоже решает проблему, однако не создает лишних форм, уменьшает запрос к Google Forms API, а еще мы получаем статистику ответов. Минус такого подхода: лишнее поле, очистив которое бот не сможет сопоставить ответы и придется проходить квиз заново.
Слоистая архитектура
Для своих сервисов я выбрал трехслойную архитектуру, основывающуюся на DAO, DTO и Rich Domain Model. Однако, несмотря на преимущества такого подхода, он добавил значительный оверхед, что привело к усложнению разработки. Каждый раз после нового запуска бота я тратил по несколько дней на его отладку. Одной из главных причин ошибок оказался некорректный маппинг, для которого я использовал Mapperly. Эта отличная библиотека значительно сэкономила мне время. Но из-за частых изменений в моделях и множества слоев — конечно я постоянно наступал на грабли.
Переход на микросервисы
Еще одной слабостью, перед которой я не смог устоять это разделение функциональности на микросервисы. В итоге их получилось 4:
-
Сам бот (там же сейчас и управление пользователями),
-
Сервис работы с квизами через Google Forms
-
Сервис оценки результатов скринингов
-
Сервис рекомендаций
Да, это добавило сложности и увеличило время разработки. При этом это упростило процесс тестирования и ввода данных. Можно было легко протестировать каждый сервис по отдельности, пусть даже и вручную. Большая часть ошибок было конечно же в сервисе бота. Но он и спроектирован с 2-мя ответственностями, вместо одной. Это тоже записал в технический долг.
Работа в паре
Это было действительно нестандартное решение. Я понимал, что несмотря на мои усилия по самоконтролю сложность бота растет и он рискует никогда не выйти в публичный доступ. Хотелось технически подкованного человека с горящими глазами, который бы разделил ответственность и владение ботом.
Денег у меня не было. Я не надеялся, что кто-то откликнется на работу без оплаты, но все-таки выложил объявление о поиске разработчика в чатики с вакансиями. Отозвались 10 человек, из которых 3 согласились работать без оплаты. Провел со всеми собеседования. Было особенно волнительно, в итоге отобрал одного джуна. Он не мог найти работу разработчиком больше года и готов был посвящать все свое время проекту. Круто, подумал я, хотя понимал, что как только он найдет работу его желание вкладываться куда-то еще упадет.
Мы проводили ежедневные звонки и синхронизировали статус задач. Вели задачи в Notion. В основном на звонках я рассказывал и объяснял скоуп задач. Для меня это был своеобразный метод утенка, а для него по сути менторская сессия и работа над проектом. Кроме того, даже сам факт присутствия у тебя в команде другого человека, с которым вы периодически созваниваетесь — хороший мотиватор (Accountability partner). Однако,
Проблема №5
Напарнику не хватает опыта быстро уловить суть, проще сделать самому, чем объяснить.
Решение: Дать один из второстепенных компонентов под полную ответственность. У него будет больше времени и больше автономии. И это сработало… частично. После череды юнит-тестов он переключился на один из сервисов, который был дальше по плану. Однако после первого ревью стало очевидно, что он не понял структуру данных и ему нужна более подробная задача.
Несомненно, работа в паре приносит пользу — появляется какая-то скрытая ответственность перед человеком, не хочется подводить. Но пользы будет больше для джуна, чем для лида. А еще через месяц после совместной работы над ботом мой напарник получил оффер.
Трекинг задач в Notion
В Notion мы вели трехуровневую систему задач с разделением на эпики, фичи и что-то похожее на юзер стори. Использовали Kanban доску.
Проблема №6
Нужна приоритезация. Но в Notion нельзя легким кликом отправить задачу вверх колонки на доске.
Решение: реализовать приоритезацию на основе собственного приоритета задачи и ее родителя. Например, если эпик имеет приоритет 1. После умножения его приоритета на 100 все его задачи получают приоритет 100. Внутри этого эпика могут быть фичи и их приоритеты умножаются на 10. Это то, что пришло в голову и получилось слепить на коленке. Подход имеет свои минусы, но в большинстве случаев рабочий.
Библиотека для обработки событий от Telegram бота
Первые пару недель я изучал возможности Telegram API и разные решения для работы через вебхуки.
Взаимодействие Telegram-бота через вебхуки происходит следующим образом: бот регистрирует URL вебхука, на который Telegram отправляет каждое новое событие (объект update), например, сообщение пользователя или нажатие кнопки. Объект update содержит всю информацию о событии (ID чата, текст сообщения, данные о пользователе и т.д.).
К сожалению, не нашел готовых библиотек, упрощающих разработку с бота на .NET через вебхуки. Пришлось делать свою. Долго разбирался, какие существуют подходы, в итоге бросил, и реализовал следующую связку:
Любое взаимодействие с ботом, кроме /start происходит через нажатие кнопки из встроенного в сообщение меню и передачи callbackData. При этом слой View — это текст и кнопки у каждой из который свой callbackData. Команды содержат примитивные параметры, а их обработчики основную логику бота. Вроде бы рабочая схема, но на этапе отладки я узнал, что:
Проблема №7
В callbackData можно засунуть максимум 64 символа.
Решение: В качестве костыля я хэшировал данные, для уменьшения объема данных. По-хорошему можно сопоставить команду записи в БД через идентификатор, который умещается в callbackData. Но я решил взять это в технический долг.
Разобравшись с Telegram API я написал небольшую библиотеку, реализующую вышеуказанный процесс обработкий апдейтов от бота. Туда же добавил отображение сообщения об ошибке вместо зависания и подсчет запросов на нереализованные фичи. Если в боте, есть какая-либо нереализованная фича, то пользователь может “записаться” в лист ожидания и проголосовать за эту фичу. Самые популярные фичи можно в последующем приоритезировать. С этим проблем не было, но как правильно разработать навигацию?
Проблема №8
Если в callbackData нельзя хранить большие команды, то как реализовать команду “Назад”?
Решение: Здесь уже пришлось хранить команду в БД. После такой реализации усилилось желание переделать предыдущий костыль. Но смиренно я сдержался.
Первые версии бота со скринингами на базе этой библиотеки появились уже через полтора месяца. Удивительно, но при полном отсутствии интеграционных тестов тогда я не так много потратил времени на отладку. Мне понравилось — работает как ожидал. Анимация удаления и создания сообщения выглядит красиво. Но через пару дней мой напарник заметил, что бот стал зависать. Полез в логи и увидел, что почему-то Telegram ругается на удаление сообщения. Кое-как нашел информацию про максимальный срок для удаления сообщений бота в Telegram.
Проблема №9
Telegram API не дает удалить сообщения старше 48 часов отправленные ботом
Решение: Вместо удаления реализовал редактирование последнего сообщения. Идентификатор сообщения храню в базе данных.
Забегая вперед, скажу, что через пару месяцев это решение породило следующую проблему.
Проблема №10
С течением времени бот сползает вниз в списке чатов в Telegram, так как используется только одно сообщение для взаимодействия с пользователем и оно было создано давно.
Решение: Вернуть удаление. Но сделать его умнее. Если сообщение младше 48 часов, но старше 24 часов, то у нас еще есть окно для удаления и создания сообщения. Если же сообщение старше 48 часов — то заменяем текущее сообщение следующим текстом и добавляем новое. Этот метод я назвал мягким удалением.
Больше проблем при работе с Telegram API я не припомню. Разве что странный markdown, но будем считать это особенностью.
Метрики и воронки
Перед запуском бота и публикацией его в различные Telegram каналы и сообщества я сделал небольшой сервис для подсчета основных метрик. Мне было интересно сколько всего пользователей их разбивки по грейдам и специализациям. Самая важная для меня метрика — это количество завершенных скринингов, потому что завершенный скрининг приносит наибольшую ценность для того, кто готовиться к собеседованию в IT. Там и разбивка по скиллам и рекомендации. Для того, чтобы мотивировать людей на начало нового скрининга или прохождение уже начатого я реализовал небольшой сервис для “продвижения” людей в воронке.
Заключение
Через 4 месяца я уже достаточно подустал от разработки. Мне хотелось скорее его запустить. Я получил очень ценный опыт разработки своего MVP. И пусть он не монетизируется, но зато приносит людям пользу даже пока я сплю.
Через пару недель после выпуска Собесбота я также решил создать группу в Telegram для джунов и стажеров, которые готовятся к собеседованиям в IT.
Вступайте в нашу группу в Telegram — там обсуждаем вопросы, связанные с подготовкой к собеседованиям, даем обратную связь и помогаем друг другу.
ссылка на оригинал статьи https://habr.com/ru/articles/850826/
Добавить комментарий