Как мы спихнули часть рутинных задач на Low-code: в каких местах было «больно»

Продолжаю серию статей о современном инструменте трансформации бизнеса — Low-code-платформе и делюсь нашим новым материалом.

В этой статье мой коллега, Варанкин Анатолий — руководитель группы разработки в ELMA, расскажет с чем столкнулся при внедрении Low-code в ежедневную рутину профессиональных разработчиков. Итак, приступаем.

Опыт №1. Serviсe Desk

В этом случае можно сказать, что наш первый лоукодный проект вышел комом. Сыграло несколько факторов.

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

Во-вторых, это встроенная в браузер IDE. Пришлось пройти через все 5 стадий принятия, чтобы начать писать код. Тут, конечно, вкусовщина и лично моя бага — я очень часто прожимаю комбинацию клавиш Ctrl + S. Так что теперь вид браузерного окна сохранения вызывает у меня неприязнь :). Ну и общая беда — нет дебага для серверной части. Т.е. написал я код, он проходит проверку, публикуется и падает. И вот тут приходится обвешивать всё try-catch, перехватывать ошибку, записывать всё в лог. Даже не в лог, а в отдельную переменную типа string, а затем выводить ее на форме. В защиту веб-IDE все же скажу, что сделано вполне качественно, привыкаешь быстро. Но с отсутствием дебага мы все еще не смирились.

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

Service Desk — на скрине одна из последних версий
Service Desk — на скрине одна из последних версий

В итоге у команды получилось сложить пазл, но какой ценой: порядочное количество потраченных нервов, несколько литров выпитого кофе, поседевшие волосы и потухшие глаза. Несмотря на это, думаю, что проект ServiceDesk идеально подходит для концепции Low-code. Да, первая итерация далась нам не дешево, но такое обучение боем было весьма эффективно. Сейчас этот проект максимально упростили и чистого кода там осталось буквально процентов 5.

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

Опыт №2. Интеграция с внешней системой

Здесь нас ждала приятная неожиданность. Настроить интеграцию с сервисом, который предоставляет доступ через HTTP API оказалось делом нескольких минут. Под капотом — стандартный Fetch API, который закрывает практически все наши запросы. Правда, на другом проекте мы столкнулись с проблемой при работе через прокси. Дело в том, что ELMA365 предоставляет разработчикам для работы Typescript, который крутится на Node.js. Для работы с веб-запросами мы используем fetch, который не умеет в прокси. Есть тикет в Node.js, но пока это пофиксят, и пока оно доберется до нас, пройдет много лет. Первым решением была идея извлечь код из исходников — https://github.com/zjael/simple-proxy-agent. Нам удалось достать всё, чтобы код скомпилировался. Но это не сработало. В итоге мы выбрали путь с решением через отдельный микросервис на .NET Core 5. Микросервис, который принимает в качестве параметров url, method, postdata и данные proxy. На текущий момент fetch с рабочим прокси есть в коробке.

Встроенный в браузер редактор кода. Пример интеграции с внешней системой
Встроенный в браузер редактор кода. Пример интеграции с внешней системой

Вывод: Для работы с проксями и сложными интеграциями Low-code система еще не готова. Нужно писать столько же кода, как и для обычного проекта. В данном проекте Low-code скорее мешал нам, добавляя свои ограничения, это слишком “чистый“ Fetch, который не дает нам использовать прокси, ntlm и наверняка что-то еще всплывет. Еще в список ограничений можно добавить невозможность подружить Saas и свой микросервис, микросервис придется хостить на своем отдельном серваке, поддерживать его и т.д.

Опыт №3. Интеграция с 1С

Чтобы запилить чистую интеграцию с HTTP API, который отдает JSON — никаких проблем. Но если вместо JSON вам приходит XML, то всё — приехали.

Вариант первый. Написать свой монстр-парсер, который будет через Regexp выдергивать нужные данные. Выглядит костыльно, но зато позволяет всё делать в рамках системы. К тому же, он будет работать в SaaS-версии системы.

Вот такой код пришлось написать для xml :

async function sendData(): Promise<void> { const login = Namespace.params.data.login; const password = Namespace.params.data.password; const urlServ = Namespace.params.data.server_adress_1C; const btoaString = btoa(login! + ":" + password!) const url = `${urlServ}/InformationRegister_CRM_Report_N1`; const app = await Context.data.main_app!.fetch() const guid = !app.data.__id ? "" : app.data.__id; const xmlFile = `<?xml version="1.0" encoding="utf-8"?> <entry xmlns="http://www.w3.org/2005/Atom" xmlns:at="http://purl.org/atompub/tombstones/1.0" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xml:base="http://client_api/uh-sf/odata/standard.odata/"> <content type="application/xml"> <m:properties> <d:GUID>${guid}</d:GUID> <d:File_xml>${Context.data.link_xml_file}</d:File_xml> </m:properties> </content> </entry>` await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/xml', 'Authorization': `Basic ${btoaString}`, }, body: xmlFile }) .then((res) => res.text()) .then((res) => { if(res.includes("error")) { throw new Error("Ошибка обработки xml файла на сервере 1С") } Context.data.response_1C = res; }) .catch(err => { if (Context.data.error){ Context.data.error += "error " + err.message } else { Context.data.error = "error " + err.message } }) }

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

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

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

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

Вывод по этому опыту простой — Low-code + JSON + WebAPI = Любовь.

Всё остальное вызывает дополнительные сложности. Можно сделать внешний сервис, который будет делать всю эту работу и не размазывать логику по всей системе. Но с другой стороны, можно написать универсальный сервис и использовать его в нескольких проектах. Не могу здесь выбрать — помог мне тут Low-code или нет)

Опыт №4. Микросервисы

Для взаимодействия с микросервисами нам доступны три подхода.

Первый способ — использовать чистый докер, который стоит на отдельном хосте и умеет запускать наш образ.

Второй — встроить сервис в оркестратор системы, чтобы он следил за состоянием, мог перезапускать инстансы и т.д. При этом мы не имеем доступ к системным микросервисам. Однако вещь удобная, не нужно отдельно следить за состоянием сервиса. Он работает весьма стабильно. Но есть недостаток — доступен только в версии onPremises.

Третий способ — самый удобный для разработчика. Через систему расширений создаем модуль, указываем адрес нашего образа, настраиваем переменные окружения — и всё, имеем под рукой готовый сервис. К тому же он еще и встраивается во внутренний SDK, так что работать с ним становится приятно. Не хватает пока работы с Volumes, но вендор уже что-то придумывает по этому поводу, а мы ждем и надеемся. Поскольку мы используем докер-образы, то сам микросервис можно создать на любом языке. Пока мы активно используем .NET и GOLANG.

Добавление микросервиса во встроенный контейнер
Добавление микросервиса во встроенный контейнер

Вывод: для работы с микросервисами система готова на все 99.99%. Подружить Low-code и сервис можно в несколько кликов. Проверять гипотезы, смотреть нагрузки и просто тестировать логику сервиса — всё делается легко и быстро.

Опыт №5. Телефония

Здесь мы развернулись на всю мощь. Перед нами был список провайдеров — Астериск, Октелл, Билайн, Манго, Sipuni и другие, с которыми мы должны были законнектиться. Работа закипела, и мы довольно быстро сделали поддержку нескольких провайдеров: Астериск, Октелл, Манго, Sipuni. Билайн и остальные провайдеры тоже технически быстро, но в организационной части — созвониться, заключить договор, получить доступы — это заняло несколько недель.

Высокая скорость разработки тут связана с двумя причинами:

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

Для некоторых провайдеров не получилось закрыть все функции с помощью http, тогда мы запустили микросервис, который выполнял какую-то небольшую функцию. Например для Астериска, это был сервис, который отслеживал начало звонка, время ответа и завершения. Затем отправлял эту информацию в нашу систему. Параллельно отправляли запрос вендору, что в определенном месте системы нам не хватило конкретного функционала. Спустя несколько месяцев накопили несколько фиксов и фич и сделали еще небольшой рефакторинг — избавились от микросервисов (не везде), где-то убрали костыли с веб-сокетами.

Вывод: удобный интерфейс для провайдера — это хорошо. Разработчик набивает руку на первом провайдере, на втором — оттачивает мастерство. И в качестве итога: мы можем штамповать эти телефонии как пирожки.

Опыт №6. Хакатон

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

Система предоставляет для расширения возможность использовать JavaScript/Typescript + DOM.

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

Вывод: не использовать для игр. Задержки большие, красивый и кастомный интерфейс настраивать сложно, также были конфликты с системными JavaScript и CSS. Для html-игр проще создавать какой-то бэк на ноде и делать простенький визуал в обычной верстке, можно даже без фреймворков.

<p>Морской бой в Low-code системе ELMA365</p>

Морской бой в Low-code системе ELMA365

Выводы

Недостатки системы:

  • Дебаг для северных сценариев/скриптов. Приходится придумывать какие-то хитрости через отдельную debug-переменную. В целом работать можно, но не так комфортно. Современные IDE уже приучили, что дебаг есть везде.
  • Возможности использовать npm-модули в системе. Сейчас приходится нести с собой чужой велосипед и следить за его версиями. Кроме того, обновление таких зависимостей пока затруднительно.

Достоинства:

  • Готовая платформа, которая забрала на себя большую часть рутинных операций — справочники, права, CRUD, организация WebAPI.
  • Возможности для интеграций с внешними системами — это правда легко и быстро. При адекватном апи со стороны внешней системы можно действительно обойтись без разработчика.
  • Возможность расширения функционала — можно добавить свои виджеты, активити для процессов, свои методы WebAPI, прозрачная работа с микросервисами.
44
5 комментариев

Со спойлером прикольная фича))) Интересная статья

1
Ответить

Здорово, что отмечаете не только положительные моменты, которые удалось улучшить с помощью Low-code, но и уделяете внимание сложным моментам, когда тот же Low-code несовместим с прокси, ntlm

1
Ответить

Да, для нас важно донести в массы мысль о том, что Low-code инструмент позволяет автоматизировать бизнес-процессы оперативно, с минимальным количеством кода. Но и нужно понимать, что Low-code не может решить все задачи.

1
Ответить

5% чистого кода в проекте ServiceDesk — это прекрасный результат. Видно, что проделана колоссальная работа. Но сам результат удивляет! Видимо, Low-code творит чудеса

1
Ответить

Спасибо за обратную связь!

Ответить