Статья на cnews

Зайчатки разума

Записная книжка айтишника

Статья на cnews

2023-05-27 14:12:18 — Evgeniy Shumilov

  Почти три года назад у меня родился замечательный сын. Потом я получил должность технического директора в нашей компании, потом случилась ипотека и переезд, который растянулся практически на полгода и, как и любой переезд, сопровождался миллионом дел и забот - одним словом, количество свободного времени устремилось не то что к нулю, а в пространство отрицательных чисел. Это можно заметить и по количеству статей, которые появлялись на моём блоге ранее по нескольку штук в неделю, а теперь раз в год. Это печально, хотелось бы больше времени посвящать и блогу, но пока к сожалению, это нереально.


  А между тем произошло множество событий в моей жизни, о которых я почти забыл, но хотелось бы помнить. Например, я заслужил звание "Руководитель года", а 31го января 2023го года вышла моя статья на cnews, которую я хотел бы привести и тут.


4 сложности переходного периода у стартапа и способы их преодоления

Существует такое понятие: «ошибка выжившего». Оно означает, что, принимая решение, человек опирается только на примеры «выживших», или тех, кто добился успеха, но при этом не учитывает статистику по тем, у кого не получилось прийти к желаемому результату, поскольку данных о них мало или они отсутствуют. О том, как трансформировать стартап в ИТ-компанию, рассуждает Евгений Шумилов, технический директор «Юникорн» (разработчик платформы для умных зданий Ujin).

Плюсы и минусы стартапов

Стартапов существует бессчетное множество, но, как известно, успеха добиваются далеко не все. Обычно мы слышим истории только о тех, что смогли выжить. Мало находится желающих делиться историей своей неудачи. Когда продукт не просто жив, но и развивается на протяжении нескольких лет, это уже говорит о многом. Особенно, если существуют игроки, действующие в том же поле и работающие над сходными или пересекающимися по функционалу продуктами, готовые занять освободившиеся ниши. Живой сапер автоматически может считаться профессионалом своего дела.

Каковы отличительные признаки стартапа? Это всегда быстрое прототипирование, бешеные скорости разработки, не всегда верные с архитектурной точки зрения решения, и это вполне объяснимо. Требуется с помощью минимума ресурсов получить работающий, пусть и неидеально, продукт для проверки своих гипотез нужен ли он рынку в принципе, что в нем необходимо изменить или доработать, чтобы максимально соответствовать запросам потребительской аудитории.

Стартапов существует бессчетное множество, но, как известно, успеха добиваются далеко не все.

Создание продукта в таком режиме это, можно сказать, «разведка боем». Обычно создается каркас проекта, но для оптимизации и детальной проработки нет ни времени, ни ресурсов. И если стартап выжил, то далее он проходит некую стадию стабилизации: продукт обрастает функционалом, учитываются требования и пожелания заказчиков, выстраиваются стратегии развития и т.д. При этом разработка по-прежнему идет в форсированном режиме. В этот период главное — выжить, найти баланс между источниками финансирования, объемом и квалификацией штата, подобрать правильный, соответствующий задаче инструментарий для возможности обработки входящих запросов на развитие функционала.

С одной стороны, хорошо, когда гипотезы подтверждаются, продукт начинает пользоваться спросом и появляется много заказчиков. С другой стороны, каждый заказчик или партнер может иметь свое видение продукта, свои требования и запросы. Два заказчика могут иметь совершенно разные взгляды на то, как должен работать один и тот же функционал, и в этом случае продукт обрастает большим количеством опций. В погоне за скоростью и желанием удовлетворить клиентов разработка под давлением бизнеса неизбежно идет на компромиссы, внедряя решения, которые не всегда идеально вписываются в изначально заложенную архитектуру проекта. Как лебедь, рак и щука, заказчики могут тянуть проект в разные стороны, выдвигая исполнителю порой чуть ли не взаимоисключающие требования.

С одним заказчиком можно договориться и объяснить, почему реализовать функционал определенным образом будет логичнее и лучше для него самого, с другим договориться не удается и приходится применять нетривиальные решения. Задача усложняется, когда заказчиков десятки, и необходима такая реализация функционала, которая удовлетворит всех.

Сами по себе продукты также имеют крайне разный уровень сложности. Если необходимо написать игру «Крестики-нолики», то на это хватит одного разработчика. Но если у вас есть десятки входящих запросов на реализацию функционала, web-интерфейс, четыре мобильных приложения, более сотни интеграционных модулей и около 250 зависимых друг от друга репозиториев с кодом, в которых что-то ежедневно изменяют более 70 человек, а еще более тысячи связанных таблиц в базе данных, то поддержание продукта такого рода становится похоже на игру в трехмерные шахматы, причем после каждого хода на доске появляются новые фигуры, а сама доска прирастает новыми клетками.

Без правильно построенных бизнес-процессов и без стратегии работа над таким проектом рано или поздно зайдет в тупик. Переход к формированию этих процессов можно назвать стадией взросления программного продукта.

Трудности переходного периода

Итак, каковы основные сложности переходного периода продукта, с которыми нам пришлось столкнуться, и каким образом мы с этим работаем?

В платформе Ujin, как и в любом достаточно масштабном программном продукте, не обходится без сложностей как на этапе проектирования, так и на этапах разработки и эксплуатации. Особенно если кардинальным образом изменяются требования к базовым принципам, заложенным в архитектуру продукта.

Одной из самых больших трудностей, с которыми нам пришлось столкнуться, стала не заложенная изначально в архитектуру платформы возможность горизонтального масштабирования. Платформа не была рассчитана на многократный и быстрый рост нагрузки. Причиной было монолитное ядро продукта, не поддерживающее возможности запустить его части на разных серверах либо запустить его части два и более раз параллельно для распределения нагрузки.

Для понимания приведу простую аналогию. У вас было задание построить легковой автомобиль, и вы с ним успешно справились. Но внезапно оказывается, что пассажиров в этом автомобиле больше ожидаемого числа, и на самом деле заказчику нужен был автобус. Затем оказывается, что, помимо пассажиров, вам нужно еще перевозить несколько грузовых контейнеров, и это скорее задача для тягача, нежели для легкового автомобиля. Напоследок вас предупреждают, что на следующей станции ожидается еще 40 человек и 3 прицепа.

Что же можно сделать в этой ситуации? Очевидный, казалось бы, вариант — начинать делать новую версию продукта с учетом полученного опыта и нового понимания целевого функционала.

Этот вариант оказался неприемлемым в силу целого ряда причин:

  • у текущего продукта есть большое количество заказчиков и пользователей, которых в любом случае требуется поддерживать, так как мы несем перед ними обязательства;
  • заморозить развитие текущего продукта на время разработки новой версии невозможно;
  • поступление новых требований заказчиков и партнеров будет приводить к тому, что один и тот же функционал придется разрабатывать для двух различных версий платформы, что негативно скажется на эффективности;
  • существуют высокие риски, что новая версия продукта не сможет догнать текущую по функционалу, и пользователей невозможно будет перенести на новую версию с сохранением доступного им объема сервисов.

Революционный путь не подошел, и потребовалось некое Соломоново решение, которое и было выработано. Была создана новая версия ядра платформы (Ujin v2), основанная на новой архитектуре, поддерживающей возможность масштабирования и географического распределения модулей платформы, что позволило более эффективно и гибко использовать аппаратные ресурсы, а также существенно повысило уровень отказоустойчивости решения в целом. Новая версия платформы способна все запросы к функционалу либо выполнять собственными силами, либо, если этот функционал на новой платформе еще не реализован, перенаправлять запросы на ядро старой платформы, а результат выполнения таким же образом возвращать пользователю.

Это позволило:

  • не терять функционал и обойтись без переноса данных;
  • получить возможность внедрения принципиально новых архитектурных решений, несовместимых ранее с текущей версии платформы и тем самым решить ряд принципиальных проблем;
  • получить возможность точечной переработки и оптимизации функционала с постепенным переносом его на новую версию платформы;
  • получить возможность тестирования и отката на старую версию функционала, если в новой обнаружились недочеты;
  • получить возможность масштабирования и более эффективного использования ресурсов (части ядра новой версии платформы могут быть запущены на множестве серверов);
  • получить возможность реализации нового функционала сразу на новой версии платформы, что позволяет избежать дополнительных работ по дальнейшему переносу.

Вернемся к аналогии с автомобилями. Пойдя по второму пути, мы построили платформу автопоезда, к которой в случае необходимости всегда можно добавить дополнительный тягач или прицеп, которая движется параллельным курсом и на которую постепенно переносят грузы и пассажиров, в то же время дорабатывая ее прямо на ходу.

Конечно, за все годы существования платформы было реализовано великое множество самого разного функционала, и процесс его переноса просто не может быть быстрым, но наиболее критичные сервисы и функционал уже перенесены. Главное — есть инструмент, который сделал это возможным.

Вторая по значимости сложность — это использование «под капотом» платформы реляционной базы данных. В нашем случае используется PostgreSQL. И если для чтения из базы можно создать столько репликаций, сколько нужно, то с Master-сервером и записью сложнее.

Производительность любой базы данных постепенно снижается в зависимости от количества запросов, их специфики, объема обрабатываемых данных, и с какого-то момента сервер перестанет справляться с нагрузкой.

Для минимизации этих рисков специфические данные, работа с которыми генерировала бо́льшую часть нагрузки (например, сигналы устройств, push-уведомления, события) частично были вынесены в отдельные базы. Проблема уже не стоит остро. Сегодня наша цель — снизить нагрузку на базу на 90%, для чего производится переход на другие инструменты работы с данными, более подходящие для сигналов устройств и событий — Kafka, KeyDB, Prometheus, что в совокупности с сегментированием данных по различным базам позволит закрыть данный вопрос окончательно.

Третья сложность заключается в большом количестве составных частей платформы. Данные «размазаны» в базе более чем по 1000 таблиц, и эти таблицы имеют явные и неявные логические связи между собой.

В хранилище около 250 репозиториев с кодом, которые также имеют перекрестные зависимости. Все это в целом не влияет на работу продукта, но усложняет его поддержку, увеличивает временные затраты на рефакторинг и внедрение нового функционала.

Сегодня уже составлен список репозиториев и таблиц, создан отдел технических писателей, проработана архитектура централизованного хранилища документации. Репозиторий каждой составляющей части продукта и каждая таблица будут последовательно должным образом описаны, снабжены номером версии, если это будет необходимо, и занесены в матрицу зависимостей. Нам еще предстоит написать дополнительные внутренние инструменты для контроля над этими зависимостями.

Решение этой проблемы также потребовало формирования и внедрения четких бизнес-процессов разработки продукта.

Четвертая сложность — это необходимость использовать продукт как On-Premise решение, хотя изначально он проектировался как SaaS.

У нас уже был опыт запуска нашей платформы в отдельном изолированном окружении на мощностях заказчика. На тот момент мы не были в полной мере готовы к подобному запуску, поэтому не обошлось без сложных моментов.

Например, процесс создания чистой базы не был проработан полностью, и впоследствии в базе партнера мы находили «хвосты» данных других партнеров. Конечно, никаких персональных или иных критичных данных там не было, но, скажем, индексы нескольких сотен зданий, которых нет у партнера, или сигналы устройств, которые у него отсутствуют, или таблицы с данными для кастомного функционала, разработанного для других заказчиков, встречались постоянно.

Теперь же нам необходимо будет не только развернуть, но и одновременно поддерживать несколько экземпляров платформы. Для этого составлены списки обязательных и опциональных модулей платформы, сервисы контейнеризируются, пишутся инструменты, которые будут автоматизировать и облегчать пусконаладку отдельных экземпляров ПО.

Подводя итоги, можно сказать, что мы видим места, где нам еще требуется приложить усилия. Мы понимаем, что это не будет легко, как не может быть легкой разработка любого масштабного продукта. Но в 2022 году мы сделали очень многое, чтобы снизить риски и не закрыть себе возможности роста и развития. Уверен, что в 2023 году мы достигнем еще большего прогресса в отношении развития внутренней инфраструктуры и подходов к разработке.

Теги: work

comments powered by Disqus