PepsiCo: как мигрировать систему складского учёта с 2 млн транзакциями бесшовно
У компании PepsiCo была внедрена автоматизированная система учёта оборудования, однако она устарела: содержала много избыточных функций, работала медленно, а интерфейс не отличался удобством. Кроме того, legacy-код существенно усложнял её обновление.
Поскольку бесперебойная работа системы критически важна для предприятия, клиент попросил нас модернизировать её. Под модернизацией в нашем случае фактически подразумевалось создание программного обеспечения с нуля.
Делимся подробностями, как мы выстроили процессы по проекту и какую пользу новое решение принесло клиенту.
О клиенте
Компания PepsiCo — крупнейший производитель продуктов питания и напитков, работающий более чем в 200 странах. В России холдинг имеет более 70 филиалов и подразделений, заводов и складских комплексов. Оборудование, установленное в торговых сетях клиента, насчитывает сотни тысяч единиц, включая более 200 000 холодильных витрин для прохладительных напитков. Годовой объём продаж каждого бренда, которым владеет ретейлер, приносит более 1 миллиарда долларов.
О запросе
На момент знакомства с нами клиент пользовался устаревшей системой для учёта торгового оборудования. Она существенно снижала производительность сотрудников, при этом без неё процессы предприятия представить невозможно.
Останавливать систему нельзя ни на секунду — и для клиента этот фактор значительно усложнял принятие решения о разработке нового веб-приложения. Когда необходимость создания такого программного обеспечения стала ещё более очевидной, клиент решил запустить проект и привлёк нас как подрядчика.
Основная задача — разработать веб-приложение, которое позволило бы сотрудникам компании PepsiCo:
- оперативно получать и обмениваться достоверными данными об оборудовании;
- точно распределять и обеспечивать перемещение оборудования;
- прогнозировать потребности в оборудовании в конкретных филиалах и планировать бюджет;
- вовремя выявлять и устранять проблемы, возникающие в ходе эксплуатации оборудования.
Вызовы проекта
- Разработать масштабную систему для управления и учёта оборудования на предприятии с сотнями филиалов по всему миру.
- Выстроить проект таким образом, чтобы новое решение можно было ввести в работу предприятия бесшовно, без остановки процессов.
Наши решения
Верхнеуровнево мы разбили работу по проекту на три составляющие:
- Анализ данных и пересмотр процесса их сбора. Частая ситуация, с которой мы сталкиваемся, приходя в проекты и начиная анализировать данные — неконсистентность. Это значит, данные изначально собирались некорректно и противоречили друг другу. Чтобы разработать систему, обеспечивающую точную обработку данных и правильно отвечающую на запросы пользователя, мы перестроили процесс сбора данных, и только после этого пошли дальше.
- Непосредственно разработка. По сути, под модернизацией имеющейся системы в данном проекте подразумевалась разработка с нуля. Нам предстояло спроектировать архитектуру (продумать, как будут работать компоненты системы и как они будут взаимосвязаны); предложить более отзывчивый и удобный дизайн интерфейса; разработать серверную часть, отвечающую за процессы внутри приложения, обработку данных, распределение прав и весь функционал, доступный пользователю; разработать пользовательскую часть — то, что позволяет сотрудникам работать с системой и эффективно выполнять свои задачи с её помощью. Кроме того, мы взяли на себя риск-менеджмент.
- Настройка интеграций. Клиент пользовался приложением iSales, где хранились данные о миллионах транзакций, и важно было, с одной стороны, не потерять то, что уже собрано, с другой — обеспечить возможность беспрерывной работы с приложением в дальнейшем.
Ниже продемонстрируем вам, как работали над задачами проекта на более глубоком уровне.
Синхронизировались с клиентом по процессам и сформировали проектную команду
Клиент выделил отдельный модуль, который нужно было перепроектировать с учётом новых требований в первую очередь. Компания предоставила очень подробное техническое задание, обозначив своё видение по процессам, сроки реализации проекта и свои ожидания по итогам.
Работа над проектом велась совместно, с вовлечением технических специалистов PepsiCo в процессы и с чётким соблюдением производственного графика.
На каждом этапе проводилось многоступенчатое тестирование: сначала проверка той или иной функции была на стороне разработчика, затем шло тестирование со стороны аналитиков клиента и в конце обратную связь давали конечные пользователи.
По итогам ревью и озвучивания дополнительных пожеланий клиента мы вносили необходимые доработки, и клиент видел, как программное решение последовательно «обрастает» новыми функциями. Весь процесс разработки выстроили максимально прозрачно, чтобы клиент не был в стрессе.
Основной состав команды:
- тимлид отдела разработки;
- архитектор решений;
- UI/UX-дизайнер;
- 2 аналитика;
- 8 разработчиков разных профилей;
- тестировщик;
- DevOps-инженер.
Сроки проекта: 11,5 месяцев.
Разработали архитектуру
Архитектура приложения определяет, из каких компонентов (частей) оно состоит и как эти компоненты взаимодействуют друг с другом. На архитектуру ориентируется вся команда разработчиков, создавая приложение.
Мы представили архитектуру многослойным монолитом с включением микросервисных модулей. Это позволило упростить процессы написания и тестирования программного кода, а также обеспечить надёжность и оптимальную производительность системы.
Архитектура построена по модели «клиент-сервер» и обладает такими особенностями, как:
- Разделение функций: позволяет наиболее выгодно использовать вычислительные мощности серверов и обеспечивает более эффективную обработку запросов.
- Наличие базы данных: позволяет серверу хранить, организовывать и качественно извлекать информацию по запросу клиента.
- Отказоустойчивость: надёжность системы повышается за счёт распределения нагрузки между несколькими серверами — даже если некоторые из них выйдут из строя, это не навредит предприятию.
- Масштабируемость: благодаря использованию микросервисов, архитектура отличается масштабируемостью — если у клиента возникнет потребность модифицировать систему и расширить функционал, он сможет легко это сделать, не приостанавливая работу производства и никак не влияя на работу других компонентов системы. Если бы мы использовали только монолит, этого не удалось бы достичь.
- Централизованное управление: сервер выполняет управление и контроль за ресурсами — это упрощает процессы обеспечения безопасности и позволяет контролировать доступы к данным быстро и просто.
Архитектура монолитного приложения разбита на три уровня (слоя):
- слой доступа данных: отвечает за работу с базами данных;
- интерфейс: отвечает за всё, что видит обычный пользователь системы — таблицы, окна ввода, кнопки, формы;
- бизнес-слой: инкапсулирует всю бизнес-логику приложения, а также является связующим звеном между слоями данных и представления.
Скорость и простоту разработки микросервисов получили за счёт программной платформы Docker (упрощает процесс переезда старой системы на новую благодаря оптимизации использования ресурсов) и Kubernetes (обеспечивает быстрые процессы развёртывания, масштабирования и поддержки программного обеспечения).
- Для интеграции с приложением iSales, которым пользуется клиент, использовали микросервис, а также API для взаимодействия с внешними сервисами. По итогам проекта импортировали в онлайн-сервис около двух миллионов транзакций.
- Построение отчётов также представлено отдельным микросервисом. При этом мы синхронизировали базы данных для создания аналитики, обеспечили целостность данных и предотвратили их потерю в случае возникновения сбоев.
В качестве языка программирования для реализации этой части выбрали JavaScript, с его помощью можно делать приложение интерактивным: добавлять всплывающие окна, анимацию, кнопки и формы для отправки информации.
Разработали дизайн интерфейса
Поскольку у проекта, при большом объёме задач, были сжатые сроки, мы решили оптимизировать и удешевить процесс разработки дизайна интерфейса.
Оперативно нашли UI-фреймворк, который идеально подошёл под задачи клиента и обеспечил для нас лёгкость миграции, кастомизировали его под потребности пользователей системы и на его основе реализовали новый удобный интерфейс всего за неделю (разработка с нуля могла бы занять месяц и более, но мы помогли клиенту сэкономить время и деньги на данном этапе, при этом не потерять в качестве и удобстве).
На иллюстрации ниже показали, как выглядела карточка оборудования раньше и как выглядит сейчас, после модернизации системы.
А так выглядит справочник оборудования (старый и новый вариант):
На этапе кастомизации мы добавили изменения в макете экрана и правила применения фильтра, изменили структуры таблиц, подход к области видимости склада, и многое другое.
Решением для разработки дизайна стала библиотека на основе Material UI.
Разработали пользовательскую часть (frontend)
Фронтенд — это часть приложения, с которой напрямую взаимодействует пользователь. Например, когда вы открываете приложение интернет-магазина, хотите перейти в корзину и добавить товар, вы нажимаете различные иконки, кнопки и другие элементы интерфейса — в этот момент вы взаимодействуете с фронтендом. И за счёт такого взаимодействия отправляете запросы в бэкенд, серверную часть, которая отвечает за то, чтобы выбранные товары были добавлены в корзину и ушли в заказ.
Фронтенд был разработан на базе Next.js. Выбрав этот фреймворк, мы смогли обеспечить баланс между разнообразием функций и оптимальной производительностью, а также масштабируемость по количеству запросов в минуту (что было очень важно для клиента, поскольку нагрузка на систему обычно колоссальная, и она должна выдерживать, не теряя в скорости и не «зависая»). В старой системе скорость реакции на вводимые пользователем данные была низкой, а переходы внутри системы осуществлялись с задержкой. Теперь же отклик на команды от пользователя моментальный.
Компонентный подход к разработке предоставил возможность создавать повторно используемые функциональные компоненты без написания нового кода, что сильно облегчает разработку и поддержку приложения, снижая стоимость работ.
В процессе разработки мы реализовали механизм для работы с сессией пользователя, при котором логика всех событий и действий любого пользователя хранится в одном большом контексте и связана с авторизацией. Каждый раз, когда нужно было реализовать какую-нибудь фичу, либо поправить ошибку, разработчики знали, что нужно обратиться именно к этому контексту. Такой подход сэкономил много времени при разработке и тестировании.
Ещё одной задачей стало создание легко масштабируемого решения для обработки документов. В системе консолидировано много разных типов документов, и без единого решения дорого добавлять новые. Мы описали общую логику, разделённую по функционалу. Модули отвечали за отображение таблиц, фильтров, форм. Каждый раз, когда нужно добавить новый тип документа, требуется просто пройтись по набору этих модулей, и декларативно описать, как должен выглядеть и работать пользовательский интерфейс. Разрабатывать заново ничего не нужно.
Разработали серверную часть (backend)
Бэкенд отвечает за взаимодействие пользователя с внутренними данными и функционалом приложения. Это «сердце» приложения, благодаря которому оно способно обрабатывать запросы и выполнять команды пользователя. Возвращаясь к примеру с интернет-магазином, именно благодаря бэкенду ваш заказ отправляется в магазин после того, как вы его добавили в корзину и оформили.
Так как задачей стало создание многопользовательского бизнес-приложения со множеством функций уровня Enterprise, был выбран Java-фреймворк Spring: у нас большой опыт работы с Java для разработки решений уровня Enterprise, и наш подход полностью откликался задачам клиента, поэтому не стали от него отходить.
Spring предоставляет большой базовый функционал из коробки (кэш, сообщения, слой Rest API и пр.), имеет встроенный контейнер для регистрации зависимостей и обеспечивает удобную интеграцию с библиотеками. Кроме того, мы выбрали его как инструмент для обеспечения безопасности доступа в зависимости от привилегий пользователя.
Основной базой данных стала Oracle BD, востребованная на мировом рынке. Её преимущество — в расширенных функциях автоматического партицирования больших таблиц. В аналогичных продуктах такой удобной фичи нет. Вручную это делать сложно и долго.
Бэкенд содержит бизнес-логику и состоит из модулей (Common, Data, нескольких доменных модулей, модулей инфраструктуры), а также из трёх сервисов:
- Rest – Rest API: отвечает за обработку запросов с фронтенда.
- SyncIsales: запускает фоновые задания импорта/экспорта для интеграции с iSales.
- Reports: инструмент для построения отчётов.
Принцип модульности позволяет масштабировать и добавлять новый функционал без рефакторинга (переработки) существующего функционала.
Поскольку бэкенд работает сущностями, в приложение были добавлены:
- справочник оборудования;
- справочник клиентов;
- справочник складов.
Ниже продемонстрировали, как сейчас выглядит справочник складов.
По многим процессам в качестве ядра мы использовали библиотеку Quartz, эта технология позволяет создавать сложные графики для выполнения любых работ и синхронизировать запуск задачи между планировщиками. Например, ставить задачи в очередь или выполнять их по расписанию, и делать это асинхронно. Таким образом мы устранили имеющиеся в старой системе сложности со скоростью выполнения операций, команд пользователей. За счёт этого механизма сервер поддерживает связь с пользователем и не «выкидывает» его из сессии, несмотря на ожидание обработки запроса. Пользователь может работать в системе, не прерываясь на сбои.
На базе Quartz Scheduler мы создали сервис отчётов для пользователей:
- о первичном складировании оборудования;
- по движению оборудования;
- о наличии оборудования;
- о списании оборудования.
В качестве библиотеки для создания хранилищ данных выбрали MobX: он предоставляет набор функций и инструментов, которые упрощают работу с данными.
В приложении код генерируется на основании таблиц в базе данных. Так, чтобы на самых ранних этапах сборки приложения отлавливать баги и устранять их моментально, мы применили ещё один фреймворк – Query DSL. Он позволяет избежать необходимости переделывания работ, исключая любые «шероховатости» системы и позволяя разработчику предоставить компании PepsiCo не просто хороший, а бесперебойно и безошибочно работающий продукт.
Обеспечили качество системы (QA)
Тестирование позволяет проиграть как можно больше типичных и нетипичных пользовательских сценариев, найти и устранить сложности, с которыми может сталкиваться человек при работе с системой. Как бы качественно ни работала команда программистов, этот этап необходим — с ним мы можем быть на 100 % уверены, что продукт готов к запуску в предприятие.
Чем сложнее программное обеспечение, тем больше тестов разных типов нужно провести.
Так, в случае масштабной системы учёта оборудования, всего в набор вошло более 14 видов тестов. Рассмотрим, какие именно и для чего они были нужны.
Функциональное тестирование. Без функциональности приложение невозможно использовать, поэтому данная проверка всегда на первом месте. Нужно протестировать, корректно ли работает каждая кнопка и функция приложения, а именно:
- просмотр данных;
- создание оборудования;
- изменение оборудования;
- перемещение оборудования;
- создание отчётов;
- обратная интеграция с системой клиента.
Тестирование удобства использования. Фактически мы шаг за шагом прошли путь пользователя, чтобы понять, насколько просто ориентироваться в приложении, достаточно ли интуитивно понятны действия кнопок и с какими затруднениями можно столкнуться, чтобы устранить любые потенциальные барьеры.
Тестирование пользовательского интерфейса. Мы протестировали интерфейс, с которым взаимодействует пользователь, на соответствие макетам.
Кроме того, по запросу клиента, приложение должно быть адаптировано под разные ОС и устройства и одинаково удобно отображаться на экранах смартфонов, планшетов, ноутбуков и больших мониторов. Для этого мы также убедились в адаптивности вёрстки.
Кроссбраузерное тестирование. Проверили, как отображается интерфейс приложения и как действуют разные элементы в браузерах Chrome и Edge.
Тестирование локализации. По требованию клиента приложение должно поддерживать два языка: русский и английский. Чтобы убедиться в том, что нужный пользователю перевод реализован везде, где требуется, мы тщательно проверили все тексты: названия полей, кнопок, подсказок, уведомлений и т. д.
Тестирование производительности (нагрузочное). По прогнозам клиента, в приложении одновременно могут работать 20 пользователей. С помощью специальной утилиты мы провели нагрузочное тестирование, чтобы убедиться в бесперебойной работе приложения при указанной нагрузке.
Кроме того, мы эмулировали нагрузку в несколько миллионов сущностей. Таким образом проверили, как будет вести себя приложение, например, через 5 лет, когда накопится большое количество данных. Такой подход позволяет снизить риски деградации системы в долгосрочной перспективе. Если не убедиться заранее в устойчивости разработки, вовремя не диагностировать и не устранить факторы, ведущие к разрушению программного обеспечения, со временем в приложении могут появиться уязвимости, система начнёт работать медленнее или вовсе перестанет загружаться.
Ручное и автоматизированное тестирование. Для коротких проектов не нужна полная автоматизация, так как расходы на автоматизацию не окупаются. Тестирование нагрузки без автоматизации не выполнить, но данный вид тестирования был необходим.
Тестирование API. В целях ранней диагностики и выявления ошибок на бэкенде провели тестирование запросов API.
Регрессионное тестирование всего функционала приложения. Этот вид проверки подразумевает тестирование после исправления ошибок, чтобы подтвердить, что после внесения изменений работоспособность других функций приложения не утрачена.
Повторное тестирование после исправления дефектов (багов). После того как разработчик исправил баг, необходимо было проверить и убедиться, что ошибка исправлена.
Позитивное и негативное тестирование. С помощью этого вида тестирования мы проверили все функции приложения. Позитивное тестирование предполагает, что пользователь не ошибается и делает все действия правильно, и приложение на верные действия должно реагировать соответствующим образом. Негативное тестирование предполагает, что пользователь делает ошибки, но приложение всё равно должно работать корректно и делать подсказки тестировщику, как исправить ошибки.
Сценарное и исследовательское тестирование. Проверили все функции приложения. Сценарное тестирование предполагает, что тестирование проходит по определённым сценариям конкретных бизнес-процессов. Исследовательское тестирование предполагает тестирование функционала без сценариев на скрытые проблемы.
Системное и модульное тестирование. Системное тестирование помогает найти проблемы общения модулей приложения, а модульное – в отдельных модулях приложения.
Приёмочное тестирование. Проверяет соответствие системы потребностям, требованиям и бизнес-процессам пользователя.
Прежде чем влить ветку с реализованной функциональностью в ветвь разработки (develop), завершённый функционал проходит детальное тестирование. Для этого мы провели тестирование части функциональности на соответствие требованиям перед передачей готового решения клиенту.
Результаты проекта
Сотрудники PepsiCo получили инструмент, который помог автоматизировать процессы учёта оборудования, и пользуются им каждый день. Хотя холдинг имеет собственное ИТ-подразделение, по итогам проекта клиент подтвердил свои предположения, что разработка подобного приложения силами внешней команды гораздо выгоднее и проще.
Подытоживая, вот основные работы, которые мы провели в рамках проекта для достижения этих целей:
- Разработали пользовательскую часть (фронтенд) и серверную часть (бэкенд).
- Обновили интерфейс, сделав его удобным для пользователя.
- Интегрировали решения с уже существующей системой клиента.
- Выбрали монолитную архитектуру как наиболее подходящую для веб-приложения. Включили микросервисы (iSales, Отчёты) для упрощения процесса масштабирования.
- Подобрали технологии, которые наилучшим образом подходят для веб-приложения, и в сочетании дают максимальную производительность продукта и быстрый отклик. Например, мы взяли в работу не самые гибкие, но максимально подходящие в нашем случае решения для организации фронтенд слоя.
- Использовали фреймворки, что позволило быстро развернуть приложение.
- Обеспечили безопасность, надёжность и отказоустойчивость приложения.
- Протестировали все приложение в целом и каждый модуль в отдельности, используя набор из 14+ видов тестов.
- Разработали решение таким образом, чтобы на его поддержку уходило минимум времени. В целом, это наш единый верхнеуровневый подход ко всем проектам, что нечасто встречается на рынке и отличает нас от других ИТ-компаний.
- Передали проект на поддержку и дальнейшее масштабирование команде разработки клиента, предварительно проведя обучение технических специалистов.
За счёт высокой вовлечённости наших тимлидов и оперативного найма новых сотрудников под проект, мы существенно ускорили процессы и добились высочайшего качества продукта. И клиент это оценил. Если изначально на проект закладывали 7 месяцев, после разработки продукта в рамках плана требования были существенно расширены. Клиент убедился, что с нами взаимодействовать комфортно, и это дешевле, чем разрабатывать систему силами своих сотрудников. Поэтому дозаказал дополнительный функционал. В итоге мы сотрудничали 11,5 месяцев и до сих пор остаёмся на связи.
После того как система была разработана полностью, компания PepsiCo заказала у нас разработку курса по Java и JavaScript. В течение двух недель сотрудники его компании ежедневно посещали наш офис, где были организованы первые уроки курса по Java и JavaScript. Для проведения курсов в офисе NLABTEAM в Санкт-Петербурге есть отдельная площадка, где созданы все условия для комфортного обучения.
В завершение все участники проекта познакомились лично, во время предновогодней встречи, где были подведены итоги проекта и состоялось общение в неформальной обстановке.
Сейчас наше сотрудничество продолжается: мы проводим уроки по Java/JS для аналитиков со стороны клиента уже более полугода, и получаем положительную обратную связь.
Команда NLABTEAM выражает благодарность команде PepsiCo и каждому специалисту, который принял участие в разработке системы!