Привет, Хабромир! Последний год мы с командой провели, создавая свой стартап «Конструктор чат-ботов для бизнеса Botlify», и я хотел бы поделиться с аудиторией небольшой историей проекта и о принятых технических решениях. В этом посте я постараюсь максимально сконцентрироваться на технических деталях и меньше углубляться в продукт и бизнес, несмотря на то, что в этом проекте моя роль намного меньше связана с разработкой и технологиями. Данный материал основан на моем личном опыте, я не стартап-коуч и не претендую на звание хорошего программиста, менеджера, архитектора или предпринимателя. Мы относительно молодой стартап, у которого не много пользователей, так что тут не будет ничего про нагрузки и проблемы больших проектов. Под катом я расскажу как начинался мой проект, на какие разработческие грабли мы наступали и какие выводы делали.
Меня зовут Андрей, какое-то время я работал разработчиком, в основном на PHP, потом тимлидом, а потом и техническим директором в нескольких небольших стартапах, где полюбил NodeJS. Но так сложилось, что последнее время я скорее предприниматель. Это не первый стартап, который я основал, и уж тем более не первый стартап, в котором я участвовал. Мне довелось поработать в нескольких успешных проектах и массе провальных. Еще больше провальных проектов основал я сам. Каждый раз причины неудач абсолютно разные, также как и стадии, на которых я проваливался, но так или иначе я использовал этот опыт и в этом проекте.
Цели
Перед началом повествования о проекте, хотелось бы рассказать о том, какие цели мы преследовали изначально затевая эту авантюру. По сути наш конструктор начинался как пет-проджект для изучения основ product management, customer development, приобретению новых управленческих навыков и опыта в стартапах. Я много раз слышал и пробовал применять подходы LEAN Startup и каждый раз получалось совершенно по-разному. Конечно, мы мечтали построить на этом бизнес и неплохо зарабатывать, но не тешили себя иллюзиями о том, что это простой и короткий путь. И тем более мы не пытались сделать какую-то WOW!-инновацию. У меня и сооснователя была постоянная фуллтайм работа и мы понимали, что времени особо много уделять не сможем. Основным мотиватором была именно возможность освоения совершенно новых для себя областей IT-индустрии и применения новых знаний на практике и при этом еще и заработать.
Идея
Будучи программистом я очень любил рисовать диаграммы классов, последовательностей, блок-схемы. Для меня сам по себе процесс визуализации являлся этапом осмысления проблем и решений, позволял получать большую картину происходящего. Работая над очередным проектом, я в который раз столкнулся с необходимостью вставить виджет с онлайн-чатом на сайт и посмотреть, какие готовые решения есть в этой области. Так, среди того что я искал, я наткнулся на платформы, которые позволяли не просто создавать виджеты с онлайн-чатом для сайта, но и встраивать в них чат-боты. Я пообщался с одним из таких ботов и он оставил у меня приятное впечатление. И тут же я начал пробовать придумывать разные сценарии чат-ботов, которые могли бы быть полезны в моих проектах. Фантазия просто полилась на стол: запись на прием в маникюрный салон, помочь определиться с выбором в интернет-магазине, указать нужное место в документации, принять запрос в службу поддержки. Чего я только не навыдумывал.
Потом я полез смотреть различные конструкторы и почти все мне предлагали заполнять формы, а потом заполнять формы, а потом снова заполнять формы. В общем — создавать ботов через заполнение форм. В итоге мне было крайне неудобно, я постоянно терял контекст происходящего, приходилось возвращаться на предыдущие шаги, чтобы восстановить контекст, а об удобном продумывании логики и проектировании сценариев не было и речи. Ну, думаю, попробую-ка я сначала «спроектировать» своих ботов во внешнем инструменте, а потом уже перенесу на нужную платформу.
И здесь я столкнулся с первой проблемой: Как описать диалог с ботом таким образом, чтобы было понятно что и почему отвечает бот и при этом иметь перед собой всю последовательность действий? На первых порах я пробовал использовать xmind и другие инструменты для создания mind map. Получалось что-то вроде этого.
В последствии стало понятно, что чат-боты в целом довольно неплохо укладываются в концепцию описания состояний и переходов между ними, получается довольно удобно ориентироваться в ветках диалогов даже там, где их много.
Было найдено всего несколько конкурентов, предоставляющих визуальный конструктор ботов. У кого-то он был более интуитивный, у кого-то менее, но в целом, такие конструкторы мне показались куда более user-friendly. Нам стало интересно попробовать сделать что-то похожее, мы захотели создать инструмент, при помощи которого можно создать чат-бота без навыков программирования, просто описывая его в виде диаграммы. Конечно, определенные технические навыки все же потребуются, но это не многим сложнее создания mind map.
Боты — довольно сложная и большая тема, а наши ресурсы очень ограничены. Поэтому нам было жизненно необходимо максимально упростить свое решение, чтобы оно хоть когда-нибудь увидело рынок. "Чем раньше — тем лучше" — эту мантру в контексте стартапов я не устану повторять.
AI & ML
Вопрос об искусственном интеллекте в чат-ботах для меня до сих пор открыт. Но сейчас мы исходим из того, что мы ранний стартап, компетенций в AI и ML у нас внутри команды нет и мы уже условились, что хотим просто рисовать диаграммы, а не готовить датасеты, обучать нейросети и вот это вот все. На данный момент мы не используем искусственный интеллект и машинное обучение в наших ботах. Быть может, когда-нибудь, в будущем, когда будут на это деньги.
Важно понимать, что одних и тех же по своей сути ботов можно сделать очень по-разному. Грубо говоря, может быть бот, который пишет: "Чего изволите?" и ожидает от пользователя произвольного ответа в духе: "Узнать о борще", "Хочу заказать борщ", "Который сейчас час?". Получив ответ, бот пытается его распознать, определить намерение и выбрать нужную ветку развития диалога. Стоит ли говорить о том, что учитывая опечатки, разнообразие форм и выражений это может быть дороговато.
С другой стороны, мы можем использовать закрытые вопросы, когда речь идет о выборе, например, бот может написать: "Чего изволите?" и предложить варианты выбора: "Узнать о борще", "Заказать борщ", "Узнать время". С одной стороны, пользователь теряет свободу действий, но с другой мы не только значительно упрощаем вычисления, но и легче можем управлять контекстом диалога, поворачивая его в нужное русло. Открытые же вопросы мы предпочитаем использовать в контексте сбора текстовых данных пользователя: введи email, телефон, напишите Ваш вопрос поддержке и т.п.
Чат-бот vs человек
Еще одним аргументом против того, чтобы давать пользователю общаться с ботом в свободной форме была убежденность в том, что чат-бот не должен «играть» в человека. По моему мнению, при общении с ботом человек должен четко понимать что общается именно с ботом, знать какие у него есть возможности и как их использовать. А если человек понимает, что общается с ботом — какой смысл в свободном текстовом общении? Гораздо лучше, когда чат-бот становится помощником человека, а не заменителем и не стесняется этого, а человек отчетливо понимает, что общается с чат-ботом и какие у него функции. В таком случае коммуникация получается заметно более эффективной.
Процесс
Я фанат удаленки. Меня хлебом не корми — дай собрать удаленную команду и начать работать с ней. Мне комфортно работать удаленно самому, я знаю, как организовать работу и найти людей, которые могут так же эффективно и комфортно работать самостоятельно. Я прекрасно понимаю, что это подходит далеко не всем, полностью с этим согласен, но считаю, что в светлом будущем удаленки будет все больше и больше. Просто экономика — ничего личного. Поскольку это мой проект и музыку для него заказывал я — тут тоже удаленка, это накладывает определенный отпечаток.
В самом начале работы над любым проектом я считаю очень важным стараться максимально формализовать свои идеи. Пока идея не обрела свою форму на бумаге, в виде текста, заметок, рисунков никакой идеи не существует вовсе. При этом, все процессы внутри команды должны быть максимально простыми, естественными и быстрыми, коммуникация эффективной. Не стоит использовать большие тяжелые инструменты для управления командой, наподобие Jira или Redmine, если вся ваша команды это вы и ваш друг. Но и не использовать ничего тоже не выдет, иначе все очень быстро выходит из под контроля и возникнет хаос, обуздать который намного труднее, чем просто не допустить. Даже в голове одного человека может образовываться такой бардак по проекту, не мне вам рассказывать, чего уж говорить о команде, пусть и всего в 2-3 человека.
Мы, как настоящие стартаперы использовали Trello для организации задач и хранения важных ссылок по проекту, туда же набрасывали идеи. Для бизнесовой документации Google Docs, а техническая вполне себе неплохо создается в markdown и кладется в соответствующий репозиторий. Общение в течение дня — Telegram, а для ежедненвых стендапов Google Hangouts. Ежедневные стендапы — один из краеугольных камней существования удаленных команд. Если этого нет — нет и команды, кто-то обязательно начинает чувствовать себя одиноким, уставшим, копится недопонимание и недовольство, теряется не только контроль над ситуацией но и отношения в коллективе.
С точки зрения процесса разработки Америку открывать тоже не пришлось. Определяем длину спринта, планируем спринт исходя из целей стартапа. Берем задачки и начинаем колбасить. Новая задача — новая ветка в любимой системе контроля версий. Готово? Оформляем Pull request, ждем пока кто-то снизойдет до ревью. Ревью прошел? CI отработал нормально? Ну тогда можно все помержить в develop ветку, дождаться зеленого света от сборки develop и обновить тестовый сервак. Код мы храним на GitHub. До появления первого платящего клиента это были публично открытые репозитории. Как человек, пытавшийся продвинуть несколько open source решений в прошлом, я искренне негодую каждый раз, когда стартап начинает трястись за сохранность своего кода до того, как начал зарабатывать какие-то деньги. Если вас будут пытаться копировать — это однозначный бизнес-успех. Ничего не стоит позже закрыть репозиторий. Да и бизнес, знаете ли, зарыт, как правило, далеко не в коде. У меня есть доступ к коду многих, в том числе очень успешных продуктов, но стоит ли говорить о том, что обладая ими я даже близко не повторю их успех? Для сборки Docker-контейнеров и прогона автотестов мы решили опробовать GitHub Actions, благо, они дали предварительный доступ. В целом, впечателения остались вполне себе приятные, скорость сборки удовлетворительная. Единственное что было неприятно, это обновления с потерей совместимости с прошлыми версиями. Пару раз они довольно серьезно меняли схему описания действий и приходилось все переконфигурировать. Но мы знали на что шли, когда соглашались попробовать продукт в статусе Beta.
С самых первых дней, буквально, с разработки лендинга для тестирования спроса мы старались выпускать релизы минимум раз в неделю и проверять хотя бы одну гипотезу. Сначала гипотезы были более глобальными, мы пробовали нащупать разные проблемы, целевую аудиторию, выработать предложение. Но чем дальше развивался продукт, тем менее глобальными они становились и сама суть уже была реже подвержена изменениям. Проект начинался с нуля, с обычного landing page, потом на коленке создали демо клиента чат-бота, который до сих пор висит на нашей главной странице. Это демо могло воспроизводить строго запрограммированный диалог и служил нам демонстрацией того, что можно будет делать на нашем конструкторе — результат его работы, а не сам конструктор. Хитрость была в том, что мы предполагали, что бизнес придет к нам не за конструктором ботов, а за каким-то итогом, преимуществом, который он даст. Мы хотели налить нашим клиентам чашечку кофе, сделанного нашей кофемашиной, вместо того, чтобы показывать саму кофемашину. Нетрудно догадаться, что сделать чашку кофе значительно быстрее и дешевле, чем собирать кофемашину. Руководствуясь этим принципом мы и решили сделать сначала демо клиента, тем более, что при наличии ряда готовых инструментов это заняло у нас не больше двух вечеров, включая разработку сценариев диалогов.
Когда мы увидели интерес со стороны посетителей лендинга и дополнительные конверсии, сгенерированные нашим же демо, мы решили, что пойдем дальше. Помню, что нашим первым релизом конструктора была форма регистрации с формой входа, после которой пользователь попадал на страницу с извинениями и обещанием сообщить когда заработает что-то еще. Я делал формы входа и регистрации добрую сотню раз в своей жизни и даже подумать не мог, что тут мы сразу обнаружим массу проблем. Порядка 60% первых пользователей банально не могли завершить процесс регистрации. У кого кнопка не работает, у кого email не приходит, у кого еще что-то. Сначала, я воспринимал идею релизить только пару форм весьма скептически, но первый же взгляд в Яндекс.Метрику дал понять, что это было скорее верное решение. Осознание того, что пользователи ведут себя не так, как тебе бы хотелось, а иногда так, как ты даже и подумать не мог сильно повлияло на все, что мы делали дальше. В качестве хобби я несколько раз в неделю тратил по паре часов в вебвизоре просто наблюдая за тем, как же юзеры пользуются нашей поделкой.
Так, мало-помалу, мы добавляли функциональность нашему детищу и пришли к продукту, который все-таки обладает ценностью не только для нас, но и для наших пользователей, некоторые из которых даже платят нам деньги. В долгосрочной перспективе мы не понимали к чему мы хотим придти, как будет выглядеть наш продукт. Единственное что мы понимали тогда это то, что мы ничего не понимаем и находимся в состоянии неопределенности.
Результат
Этот эксперимент довел меня и мою команду до ангельских инвестиций из категории «friends, family, fools», построенного MVP, первых продаж, получения огромного опыта, множества радостей и разочарований. Мы еще не настоящий бизнес, но очень стремимся им стать. И когда я говорю это, я подразумеваю что мы все еще в поисках устойчивой бизнес-модели и product-market fit. Мы снова планируем искать верную концепцию продукта, своего клиента, свой рынок.
Первоначальные цели были достигнуты далеко не все, но проект вырос из домашнего хобби и превратился в фуллтайм работу, появилась ответственность перед инвесторами, пользователями, сотрудниками. Конечно, у проекта существует масса проблем, как концептуальных, так и технических, но нет ничего не решаемого и мы планируем продолжать работу.
Перед тем, как приступить к более технической части моего опуса, стоит, наверное вкратце рассказать о том, что продукт позволяет делать.
- Управлять чат-ботами в аккаунте
- Визуальный редактор чат-ботов
- Управление доступом к чат-ботам(доступ для редактирования, публичный доступ)
- Возможность публикации чат-ботов в web(widget, embedded, fullscreen)
- Настройки чат-ботов(дизайн, названия, метрики, позиция виджета и прочее)
- Поддержка интеграций чат-ботов с внешними сервисами через GET и POST запросы
- Анализ диалогов ботв
- Управление аккаунтом
- Подписочная модель, управление подпиской
Архитектура
Теперь, зная предысторию, цели, идею и принципы, которыми мы руководствовались при разработке, я могу приступить к общему описанию того, как же это все работает. Поскольку изначально наш выбор пал на создание чат-ботов для сайтов и fullscreen чат-ботов, наподобие app.botlify.io/bot/5de53dbf9b9bae002b319600 было ясно, что большая часть работы будет на стороне frontend. В итоге фронт работ на клиенте сформировался в осмысленный список задач и хотелок:
- Создать/найти клиентскую библиотеку, эдакий «движок» для чат-ботов в браузере, который понимает полученные json-инструкции и ведет диалог с пользователем.
- Сделать приложение для редактирования узлов ботов, которое будет сохранять список узлов и связей между ними в какой-нибудь json-объект(на основании которого клиентская библиотека будет вести диалоги).
- Для того, чтобы можно было регистрироваться, входить, управлять ботами и аккаунтом нужен какой-то кабинет пользователя. Тут же мы хотели учесть то, что у ботов могут быть более широкие настройки, нежели узлы, описывающие диалог. Например, настройки публикации, позиция виджета, текст кнопки виджета и т.п.
- Нужен вебмодуль, который будут запрашивать наши клиенты, вставляя скрипт на свои страницы. Зная id бота, вебмодуль инициализирует клиентскую библиотеку с нужными параметрами:
<script defer src="https://app.botlify.io/botlify.min.js" onload="Botlify({ bot: '5de53dbf9b9bae002b319600', type: 'widget'})" </script>
- Совсем неплохо было бы иметь возможность всем этим управлять, а значит, нужна админка(на самом деле не очень пока она нужна)
Всю логику диалогов от создания чат-ботов(узлов и соединений), до непосредственной работы с ними в веб клиенте обрабатывает frontend. Роль бекенда больше сводится к управлению доступами, подписками, рассылками, уведомлениями и хранению данных переданных с множества веб-клиентов.
Frontend
Для фронта мы используем Reactjs. Пакуем все в Docker(делаем build и пихаем его в nginx контейнер), код на Github в приватных репозиториях, для CI используем Github Actions. Контейнеры запускаем на обычных
- Web Клиент — клиентская javascript библиотека, обеспечивающая работу чат-бота в браузере. Принимает json с инструкциями и настройками чат-бота, на основании которых ведет диалог. Клиент также отвечает за отображение веб чат-ботов(виджет, окно, полноэкранный режим, размеры шрифтов, кнопочек, фон и т.п).
- Web модуль — клиентский javascript для встраивания. Наши клиенты передают в этот скрипт id бота и нужный режим отображения, модуль загружает бота с бекенда, проверяет настройки и инициализирует Web-клиент подходящим образом.
- Редактор ботов — визуальный редактор, который позволяет пользователям создавать сценарии диалогов. Этот модуль по сути работает только с json, описывающим логику чат-ботов. Если быть точнее, то этот модуль отображает некий редактор «узлов» и в принципе даже не подозревает о том, что результат — логика чат-бота.
- Кабинет пользователя — веб-приложение для управления аккаунтом, подпиской и ботами.
- Административная панель — веб-приложение для администраторов. Управление юзерами, ботами, подписками, дашборд с аналитикой.
На схеме ниже изображены компоненты фронтенда и как они взаимодействуют друг с другом. Webclient и редактор ботов используются только в контексте других приложений, при этом, если editor используется только в наших приложениях, то веб-клиент может быть использован еще и нашими клиентами в виде вебмодуля. При сборке проекта в приложения Dashboard и Admin добавляются пакеты с Webclient и Editor. Помимо этого происходит сборка вебмодуля при помощи webpack для поставки пользователям.
MVP 1. Web-клиент
Как стартап, мы всегда стремимся добиться максимального результата, используя минимум ресурсов. Как мне кажется, довольно логичным шагом для первого MVP было именно создание веб-клиента с той точки зрения, что он представлял «товар лицом», показывал результат работы конструктора, а не процесс создания бота — чашка кофе, а не кофемашина. Чтобы минимизировать время разработки решения мы решили поискать подходящие под наши запросы библиотеки и, внезапно, нашли! lucasbassetti.com.br/react-simple-chatbot — react-компонент, который покрывал практически все наши потребности!
Данный компонент предлагал описывать логику чат-бота в виде массива шагов(steps), читать значения, введенные пользователям, кастомизировать внешний вид, валидировать даннные и выглядил достаточно гибким для начала. Простейшее описание шагов выглядит примерно так:
<ChatBot
steps={[
{
id: '1',
message: 'What is your name?',
trigger: '2',
},
{
id: '2',
user: true,
trigger: '3',
},
{
id: '3',
message: 'Hi {previousValue}, nice to meet you!',
end: true,
},
]}
/>
Начали мы с того, что попробовали таким образом составить чат-бота, презентующего наш проект, mind map которого был на скрине в начале статьи. Конечно, описывать вручную такой json оказалось довольно неудобно, да и приходилось писать много кастомных функций, но в целом этот процесс дал понимание того, как работает компонент, как с помощью него добиться нужного результата.
Дальше мой коллега кастомизировал внешний вид, сделал несколько вариантов отображения и мы состряпали пример с барбершопом и выставкой Ван Гога. Можно даже заметить, что мы тогда даже не подумали об оптимизации изображений. Да оно было и не нужно. В процессе работы у нас сформировалось примерное виденье того, как будет работать клиент и мы начали искать решения для самого конструктора, чтобы как можно скорее воспользоваться преимуществами визуального редактирования.
MVP 2. Конструктор
Исходя из того, что мы увидели при работе с клиентом мы сделали общий вывод о том, что у бота может быть несколько видов действий: отправить что-то, подождать действия пользователя, отправить запрос внешнему сервису. Для минимально жизнеспособного редактора ботов мы решили ограничится блоками:
- Старт — технический блок, который начинает новую сессию
- Конец — блок завершающий сессию
- Сообщение — по достижению блока бот отправляет указанное в теле блока сообщение
- Ввод с клавиатуры — бот ожидает пользовательского ввода с клавиатуры. При получении сохраняет полученное значение в переменную, которую потом можно использовать в сообщениях
Предполагалось, что блоки будут соединяться между собой стрелками, или линиями. У всех блоков, кроме блока «Старт» есть один входной порт(сокет). Во входной порт может вести множество линий, соединяющий блок с другими. Все блоки, кроме блока «Конец» имеют от одного до нескольких выходных портов. Выходные порты определяют какому блоку передается управление после того, как отработает логика текущего блока.
После непродолжительного осмотра доступных решений мы остановились на Rete.js(https://rete.js.org). Я ознакомился с документацией, примерами и нашел в них все что нам было нужно для старта. У них даже был пример как раз с чат-ботом, что стало последним триггером
Движок Rete позволяет обрабатывать данные на основе потоков в узлах и передавать их из выходных данных во входные. Движок не зависит от других компонентов редактора. Все, что ему нужно — это идентификатор, воркеры Компонентов и JSON данные
Все узлы могут содержать имя, входы, выходы и контролы. Входы и выходы должны быть расположены слева и справа от узла соответственно (для кастомных узлов могут быть исключения). Они представлены сокетом и могут иметь имена. Для входов мы разрешили неограниченное количество подключений(попасть в узел можно многими способами), для выхода ограничились только одним подключением, однако, в отличии от сокетов входа, некоторые блоки имеют множество сокетов выхода.
Rete.js построен так, что его функционал расширяется при помощи создания кастомных узлов, контролов, компонентов, что позволило нам довольно быстро получить именно ту картину, которую мы хотели видеть, за что создателям Rete отдельное спасибо! Конечно же, одно из самого важного — готовый редактор!
Как написано в документации:
Редактор представляет собой область с узлами и соединениями между их сокетами. Доступны следующие возможности:
- Взаимодействие с рабочей областью (перемещение, масштабирование) и управление узлами (перемещение, добавление, удаление)
- Отображение соединений, узлов, их входов/выходов и контролов
- Обработка событий редактора
- Импорт/экспорт схемы в JSON формате
- Расширение функционала с помощью плагинов
- Кастомизация рабочей области, узлов и соединений
Поколдовав немного с Rete и изучив подробнее примеры нам удалось построить нечто, что позволяло создавать и удалять блоки «старт», «конец», «сообщение», «ввод с клавиатуры». На выходе мы получали json с описанием нод, сокетов и соединяющих их линий.
Уже что-то, но этого еще не достаточно, ведь наш web-клиент не понимает этот json. Ему нужен какой-то свой, именно с описанием шагов(steps). Решено было встроить в клиент конвертер из одного json-формата в другой.
JSON трансформер
Утилита получает на вход NodesMap, составленный редактором, а возвращает понятный для клиента StepsMap. Код всего трансформера занимает чуть больше 100 строк, в зависимости от типа ноды и данных в ней создается подходящий step, функции triggers, и набор инструкций(actions), который надо выполнить в этом шаге. Бывают инструкции, которые сохраняют переменную в состояние чат-бота, бывают и те, которые подставляют переменную в текст, или отправляют шлют запрос на наш сервер.
Увязав компоненты вместе мы начали тестировать полученные инструменты. Даже без бекенда это было очень увлекательно. Мы составляли диалоги в редакторе и через dev tools вставляли json в клиент, а в резултате получали бота, который говорит как нам нужно! Да еще и умеет сохранять переменные и использовать их, черт возьми! Прекрасные ощущения первых побед… Мозаика устройства нашего приложения уже практически сложилась в голове, мы получили нечто работающее на тех принципах, которые мы хотим использовать в дальнейшем. Получили некий скелет, вокруг которого оставалось наращивать «мясо». И самое главное — стало понятно как это делать:
- Изменяем редактор, добавляем нужный тип ноды
- Учим json-трансформер трансформировать новую ноду в новый step
- Учим клиент работать с новым step
С другой стороны, нужно было начать заниматься личным кабинетом пользователя, чтобы можно было создавать ботов, сохранять их, управлять и мы решили сконцентрироваться на этом, чтобы быстрее показать пользователям не концепции, а продукт.
Кабинет пользователя
Вышеперечисленные библиотеки выполняли те или иные функции связанные с созданием логики чат-ботов(редактор), ее интерпретацией или ее воспроизведением(клиент). Вопросы хранения данных, возможности загружать созданных ботов, управления ими и настройки свойств не связанных с логикой оставались открытыми и решить их должно было приложение для пользователей. Вооружившись blueprintJS мы набросали прототип личного кабинета в котором можно было зарегистрироваться и создавать несколько ботов. При нажатии на создание бота человек должен был провалиться в редактор с новым ботом, а при клике по карточке бота в редактор с этим ботом. Функции загрузки и сохранения бота через API нашего бекенда мы решили поручить этому слою, дабы оставить редактор ботов независимым от бекенда.
Приложение кабинета пользователя умеет загружать пакет редактора и передает в него готовые данные для отображения. Также это приложение управляет формами для настройки свойств бота(название, api ключи, аватар, настройки публикации), позволяет просматривать статистику. Для того, чтобы пользователи могли сразу увидеть результат работы редактора, мы добавили в кабинет пользователя веб-клиент, которому отдаем json схему бота, он интерпретирует ее в шаги и воспроизводит на вкладке «предпросмотр». По большому счету это вполне классическая админка с парой интересных компонентов(редактор ботов и веб-клиент), думаю, многие такие делали. Но именно на этом этапе стало заметно неудобно разрабатывать наше приложение.
Изначально нам показалось хорошей идеей содержать компоненты продукта в разных репозиториях и мы не видели в этом особо никакой проблемы. Однако, уже очень быстро стало ясно, что поддерживать множество репозиториев в актуальном состоянии проблематично, не говоря уже о необходимости плясать с бубном при разработке, ведь они в какой-то степени созависимы. А учитывая, что фулл-тайм разработчик у нас и вовсе был один, такой подход был огромным шилом в заднице. Да и любой деплой превращался в филиал ада на земле из-за разницы в сборке и публикации библиотек, приложений, проблемами обратной совместимости. Отсюда банальный, но не самый бесполезный вывод: преждевременное выделение модулей может навредить сильнее, чем помочь Я уже много раз убеждался в этом на бекенде, а тут наступил опять, но на фронте. Да и на бекенде я случай не упустил :=)
Один из коллег собрал волю в кулак и объединил все в монорепозиторий, управляемый при помощи lerna. Теперь наш единственный фронт репозиторий разделен на пакеты: admin, client, common, dashboard, editor, web-module. У них внутри может быть разная сборка, но lerna позволяет их между собой залинковать и обновлять зависимости между пакетами. После этого разработка и деплой фронтенда стали значительно быстрее и легче, все сразу под рукой, но все же разделено.
После создания кабинета какое-то время мы потратили на новые блоки в редакторе и их обработку клиентом:
- Опции — позволяет собеседнику выбрать один из вариантов ответа. В редакторе для этого мы сделали возможность динамически добавлять возможные варианты(и сокеты), а клиент отрисовывает кнопочки с вариантами и переходит на нужную ветку в зависимости от выбора пользователя
- Вебхук — позволяет отправлять данные из чат-бота на сервер
- Email — отправляет email на указанный адрес
Про админку и вебмодуль мне особо нечего рассказывать, там все очень стандартно. Позволю себе только отметить, что админку тоже не стоит делать раньше времени. Она у нас есть, но ей никто не пользуется, поскольку лично мне не составляет труда посмотреть все, что меня интересует сразу в БД. Никакого гуманитария, которому нужна была бы наша админка в команде нет, а поддерживать ее в актуальном состоянии по сути немногим менее затратно, чем поддерживать кабинет пользователя. Со временем туда добавился простенький дашборд, отображающий платежи, новые регистрации и визиты приложения, но вряд ли эта информация на самом деле стоила разработки целой админ. панели с таблицами, формами и отдельной аутентификацией
Итоги?
Нам удалось очень быстро построить прототипы и лендинги. Да, это было совсем не то, что многие себе представляют под видом MVP. Но буквально через пару вечеров после возникновения идеи мы могли начать ее показывать людям и тестировать. Разные лендинги, рекламные объявления, тексты в боте — мы могли тестировать и искать. Я крайне рекомендую всем, кто занимается разработкой в стартапах думать о том, как сделать так, чтобы максимально быстро добиться результата. Первый продукт, позволяющий извлечь ценность мы сделали примерно за три месяца, а дальше начался более постепенный процесс регулярного улучшения. Конечно, теперь у нас внутри конструктора больше блоков, добавили валидацию, типы данных, GET и POST запросы, много всяких настроек дизайна и отображения, но начинать можно было без всего этого, что мы и сделали.
Со временем, система стала усложняться и эволюционировать и мне не удалось даже близко описать все, что сейчас на самом деле происходит. Начинайте с малого, все усложниться само собой со временем, когда будет необходимо. Любой лишний компонент может вылиться в очень высокую стоимость ведь его мало того, что нужно создать и интегрировать, но и поддерживать, тестировать, документировать, деплоить, мониторить, знакомить с ним других членов команды. Вероятно не стоит заморачиваться с очередями на RabbitMQ, если до этого в вашем приложении не было ни одной очереди. Скорее всего для начала хватит решения на технологиях, которые уже есть. Любой новый компонент это дополнительные расходы на интеграцию, эксплуатацию, тестирование, поддержку, документацию, деплой и т.д и т.п.
Я надеюсь, мой опыт окажется полезным хоть кому-то. Я долго пытался понять, в какой хаб это определить, но так и не понял. Дайте знать, если стоит писать вторую часть, в которой я хотел рассказать немного о бекенде, внешних сервисах и планах развития
Автор: hlogeon