Все статьи

Простота и целесообразность серверной разработки веб-интерфейса

Быть full-stack разработчиком в наши дни нелегко, хотя так было не всегда. Есть различные причины, по которым эта работа стала сложнее. Одна из них — это растущее количество обязанностей (взять хотя бы DevSecOps). Другая состоит в том, что разные элементы технологического стека становятся все более сложными.

В числе усложнившихся за последнее время технологий можно назвать и способы разработки UI. На это повлияло несколько факторов, и основной - это расцвет SPA (Single Page Application) фреймворков. Фронтенд на JavaScript, который использует вызовы API для отображения данных или выполнения каких-либо действий, требует создания HTTP API для любых взаимодействий с интерфейсом. Во многих бэкофисных приложениях эти API могут добавлять “побочную сложность” (accidental complexity).

Jmix, будучи full-stack фреймворком для создания корпоративных приложений, использует серверный подход к разработке интерфейса на основе технологии Vaadin. Давайте разберемся, как это работает и каким образом размытие границы между фронтендом и бэкендом помогает справиться со многими трудностями.

Что такое серверная разработка веб-UI в рамках Jmix и Vaadin?

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

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

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

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

С серверным подходом к UI код фронтенда и бэкенда обычно пишется на одном и том же языке.

Раньше для веб-приложений это было возможно только в случае серверной обработки HTML. В экосистеме Java такой подход к созданию интерфейса использовали, например, JSP и Thymeleaf. Иногда применялись специфичные DSL/API, но в целом язык оставался тем же. Тем не менее, разработчикам приходилось учить и основы веб-технологий — HTML и CSS.

С развитием JavaScript и в частности SPA, в которых все больше логики сосредотачивалось в рамках веб-браузера, использование одного и того же языка теряло популярность. Однако сейчас появились мощные фреймворки, которые снова сделали возможным создание UI со стороны сервера, например, Phoenix Liveview, Blazor для C# или Vaadin в экосистеме Java.

Их концепция следует все тому же принципу: разработчик пишет UI-логику на том языке, который использует для создания бэкенда, например, Elixir, C# или Java. Фреймворк производит некоторые преобразования для работы UI в браузере. Таким образом, отсутствие технологических ограничений позволяет разработчику работать над фронтендом и бэкендом не по отдельности, а как над единым целым.

Как работает Vaadin

Vaadin (точнее, Vaadin Flow) — это набор веб-компонентов и Java API. Разработчик может написать компоновку элементов интерфейса на Java. Vaadin использует эти данные для создания соответствующих компонентов UI в браузере.

Когда пользователь взаимодействует с этими компонентами (например, кликает по кнопке), создается обращение к серверу, которое вызывает соответствующий метод Java, объявленный слушателем событий (event listener).

Фреймворк берет на себя обработку взаимодействия между браузером и сервером, так что для соединения UI и бэкенда никакого отдельно заданного API не требуется.

Он также отслеживает каждую пользовательскую сессию и состояние на сервере для соответствующей диспетчеризации вызовов методов.

При явном разделении на фронтенд и бэкенд клиентский код на JavaScript обычно реализует API-вызовы, необходимые для запуска события на сервере. Так как большая часть взаимодействий находится в клиенте, требуется не так много ручных вызовов API. Vaadin, с другой стороны, передает большинство взаимодействий с интерфейсом на сервер.

Давайте рассмотрим пример такого взаимодействия. В демо-приложении Jmix Petclinic есть календарь, в котором представлено расписание приемов у ветеринара на месяц:

Мы видим две кнопки для смены отображаемого месяца. Когда мы нажимаем на кнопку, запускается Java-код (см. фрагмент кода ниже), и в интерфейсе браузера обновляется информация о визитах за предыдущий месяц:

@UiController("petclinic_Visit.browse")
@Route(value = "visits")
public class VisitBrowse extends StandardLookup<Visit> {
    //...
    @Subscribe("navigatorPrevious")
    protected void onNavigatorPreviousClick(Button.ClickEvent event) {
        calendarNavigators
                .forMode(
                        CalendarScreenAdjustment.of(calendar, calendarNavigator, calendarTitle),
                        datatypeFormatter,
                        calendarMode.getValue()
                )
                .navigate(PREVIOUS, calendarNavigator.getValue());
        loadEvents();
    }
}

Vaadin выполняет взаимодействие следующим образом:

Часть Vaadin, работающая с JavaScript (Vaadin Client), обрабатывает нажатие кнопки в браузере и передает запрос в бэкенд-часть Vaadin (Vaadin Server). В бэкенде проверяется контекст и состояние текущей пользовательской сессии. После этого Vaadin отправляет событие (нажатие кнопки) в код Java UI на стороне сервера.

UI-код обновляет календарь и данные в нем. Это реализуется через взаимодействие с Vaadin Java API для обновления Vaadin-компонентов. Vaadin Server подбирает компоненты для обновления и передает новое состояние компонентов в Vaadin Client в браузере. Таким образом изменения, запрошенные через браузер, отображаются у пользователя, и он видит данные за предыдущий месяц.

Что добавляет к этому Jmix

Jmix — это фреймворк для быстрой разработки корпоративных приложений, ориентированных на данные. В его основе лежит в том числе Vaadin, который отвечает за рендеринг UI. Jmix позволяет декларативно создавать компоновку UI с помощью XML, что гораздо проще, чем программирование UI на Java, как это происходит в чистом Vaadin. XML-компоновку можно редактировать вручную или с помощью визуального дизайнера, предоставляемого в составе Jmix Studio — инструмента на основе IntelliJ IDEA.

Jmix также предоставляет возможности, нацеленные именно на корпоративные приложения. Например, он содержит обширный набор UI-компонентов для работы с данными, который расширяет библиотеку Vaadin. Примером такого компонента является продвинутый фильтр, в котором пользователи могут настраивать свои условия поиска данных.

Кроме того, Jmix имеет набор модулей с дополнительными функциями: от контроля доступа и аудита данных до формирования отчетности и управления бизнес-процессами. Многие модули Jmix содержат пользовательский интерфейс, который легко интегрируется в создаваемое full-stack приложение. Такой UI довольно просто настраивается в приложении благодаря серверной модели программирования Vaadin и настраиваемой компоновке Jmix UI на XML.

Преимущества серверной разработки UI

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

Меньшая сложность

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

С другой стороны, абстракция — это палка о двух концах. Она хороша до тех пор, пока не потребуется заглянуть “под капот” приложения. Поэтому в некоторых случаях просто необходимо иметь доступ ко всей экосистеме JavaScript. А это не так-то просто, если вместо JavaScript SPA использовать Vaadin.

Еще одно техническое преимущество заключается в том, что снижается количество дублированного кода, что снижает и общую сложность системы. В Jmix / Vaadin вы используете одну и ту же доменную модель для бизнес-логики и UI. Логика валидации данных хранится в одном месте, и ее не нужно дублировать в коде UI и коде API бэкенда.

Безопасность

С точки зрения безопасности архитектура Vaadin также имеет несколько преимуществ. Она никогда не открывает внутренности браузеру, вместо этого в браузер передаются только те данные, которые необходимы для обновления UI. Это принципиально более безопасный подход по сравнению с тем, в котором разработчику нужно самому определять корректные данные для передачи в UI для каждого действия, что может привести к раскрытию лишних данных в JavaScript через конечные точки API.

Full-stack команды

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

Full-stack разработчики же могут предугадать, какие проблемы или преимущества появятся в UI от того или иного решения в реализации модели данных. Vaadin в каком-то смысле продвигает эту модель работы, так как она снижает порог вхождения бэкенд-разработчиков в задачи, связанные с фронтендом.

Из этого вытекает еще одно преимущество. Если у вас небольшая команда, разработка на едином языке позволяет создать полноценное веб-приложение минимальными силами, без привлечения фронтенд-специалистов.

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

Ограничения подхода к UI на Vaadin

Архитектурный подход Vaadin — это не “серебряная пуля”. Отражение каждой пользовательской сессии на сервере дает существенную нагрузку по памяти на бэкенде. Это нормально для тех бизнес-приложений, где количество одновременных пользователей не превышает десятки тысяч. А вот приложение с миллионами одновременных пользователей, работающих с UI, потребовало бы нереалистичного объема памяти.

Когда вы работаете с Jmix и создаете бизнес-приложения, это ограничение не проблема. Но есть приложения, где помимо бэк-офиса есть открытая часть для внешних клиентов, которая и станет источником повышенной нагрузки. В этом случае лучше применить гибридный подход: использование REST API для публичного фронтенда в сочетании с дополнительным SPA поможет обойти это ограничение.

Jmix - это open-source платфора быстрой разработки бизнес-приложений на Java