BeanExplorer5

Материал из DevelopmenOnTheEdge
Перейти к: навигация, поиск

Это основная статья о BeanExplorer5.

Поскольку эта основная статья недописана, остальная её часть для тех, кто будет дорабатывать BeanExplorer5, а не использовать.

Концепции и технологии

Основные технологии, которые мы используем - это Java, Java Servlet, OSGi, React, SystemJS, ES2015 через Babel.

Frontend

Основные frontend компоненты написаны на React, но могут быть написаны на чём угодно. Поскольку React - это лишь "V" из MVC, то часть функционала полноценного frontend framework было необходимо реализовать, и этот функционал находится в be5/be5-frontend/src/scripts/be5.js (или просто be5 - далее буду писать имена скриптов кратко). Это покрывает функционал routing, requests, frontend localization. Также полезный базовый функционал находится в be5/bus, be5/createStore, be5/createSimpleStore, be5/ext.

  • bus - сообщения (брокер из паттерна pub/sub); например, bus.fire('DocumentChange', value), bus.listen('DocumentChange', value => ...);
  • ext - расширения;
  • createStore - создание store для управления данными на frontend; позволяет подписаться на его изменения;
  • createSimpleStore - создание store, полным состоянием которого является результат GET запроса.

Необходимые части frontend подгружаются динамически с помощью SystemJS.

JSX+ES2015 скрипты компилируются с помощью Babel при сборке проекта.

Нерешённые проблемы:

  • frontend подготовлен, но не переведён на redux, а это необходимо для упрощения работы с React компонентами (без redux или Flux бывает довольно нетривиально управлять состоянием React компонентов);
  • be5.js требует разделения на небольшие части, также, как выделены bus и ext;
  • невозможно отказаться от компиляции ES2015, даже если она будет поддерживаться всеми браузерами. SystemJS проверяет наличие ES2015 синтаксиса в скриптах, и в случае его наличия пытается использовать транслятор в браузере, даже если явно указано, что транслятора нет.

Tips на будущее:

Backend

Основные части API находятся в com.beanexplorer.enterprise.api. Проще всего начать знакомство с BE5, посмотрев на содержимое этого пакета и его подпакетов. В com.beanexplorer.enterprise.api.experimental.v1 хранятся маленькие полезности. Если они становятся не экспериментальными, а доказавшими полезность, можно переносить их в другие подпакеты api. v1 в названии пакета необходимо для поддержки разного API для одинакового функционала, если невозможно быстро отрефакторить код с экспериментальным функционалом или если хочется проверить, какой подход окажется полезнее.

Сердце всего BE5 - это ServiceProvider. ServiceProvider доступен компонентам, а в конструкторы сервисов инжектируются другие сервисы или сам ServiceProvider.

Good practices:

  • Разделяем модельные элементы на бины без логики, сервисы и репозитории.
  • Презентационный код пишется в компонентах. Если в компоненте много строчек кода, то что-то пошло не так.

Нерешённые проблемы:

  • При написании operation почти любая строчка кода приводит к увеличению зависимости от наличия метаданных в БД, а также ухудшению возможности что либо протестировать, равно как и невозможности переиспользовать написанный код. Необходимо новое API для операций, полагающееся на сервисы - содержимого com.beanexplorer.enterprise.api.experimental и com.beanexplorer.enterprise.api.experimental.v1 недостаточно.
  • Нет предусмотренного сетапа для тестирования.
  • Нет API для запросов из БД, которое покрывает все возможные SQL запросы.
  • Мы не избавились от метаданных в базе данных, поскольку BeanExplorer5 использует legacy код, который полагается на наличие метаданных в базе данных.
  • Нет стандартного способа взять запрос из Query (той, что определена в YAML) и запустить его. Дело в том, что концептуально сейчас Query - это запросы, которые используются как запросы для таблиц, которые может увидеть пользователь. Такие запросы помечаются набором ролей, обладатели которых могут запускать запросы. Однако бывает необходимость описать запрос на BE-SQL и запустить его из Java. На мой взгляд не только роли должны игнорироваться, но и вообще такие запросы должны либо где-то в другом месте лежать (например, namedQueries.yaml), либо быть приписанными к Entity и не находиться в разделе queries, а, например, находиться в разделе "systemQueries" (причём поскольку это новые запросы, они никогда не должны попадать в БД, а быть только в in-memory meta/project; сейчас запустить обычную Query через BE-SQL игнорируя роли можно так:
executorService.createExecutor(meta.getQueryIgnoringRoles("entityName", "queryName"), request).execute())

Tips на будущее:

  • Можно ресширить функционал ServiceProvider добавлением способности обрабатывать аннотированные поля сервисов - это избавит от проблем обхода циклических зависимостей сервисов и написания boilderplate в конструкторах. Также возможно попробовать сэмулировать поведение из Spring Core или Google Guice - это бы позволило просто перйти на них при возможности (см. следующее).
  • Можно даже использовать Google Guice или переиспользовать Spring Core, если найдётся хороший способ регистрации сервисов из разных OSGi модулей (сам BE5 и BE5 приложение - в разных OSGi модулях).
  • В идеальном случае было бы хорошо не писать репозитории, да и сервисы для запросов - для этого есть Hibernate, реализации JPA и другие ORM. А ещё лучше - попробовать переиспользовать Spring Data (объявлять интерфейсы с методами, описывающими запрос, без необходимости писать сам код запроса - как personRepository.findByEmailAndActive("email", true) - вызов метода из интерфейса, реализацию которого подкладывает Spring).
  • Или хотя бы доделать SQL builder (SqlBuilder) и SQL Service (SqlService), потому что они сейчас не позволяют делать запросы с LEFT JOIN и WITH RECURSIVE.
  • В таком случае было бы хорошо реализовывать код репозиториев с использованием одного универсального парсера из ResultSet в бины (при этом он должен работать по принципу fail-fast, а не как Dynamic.assign(Object bean, DynamicPropertySet dynamicProperties), который игнорирует все ошибки).

Сборка BeanExplorer5

См. Сборка BeanExplorer5 проекта.

BeanExplorer5 API

См. BeanExplorer5 API