Поток: как работать с объектами, которые генерируют другие зависимые объекты

#javascript #reactjs #flux

#javascript #reactjs #поток

Вопрос:

Контекст: мы создаем сложное 3D-веб-приложение, похожее на Sims, с React/Alt.js . Пользователи могут добавлять простые объекты в 3D-сцену (куб), но чаще они добавляют то, что мы называем «сборкой», которая представляет собой сборку из нескольких простых объектов (15 кубов образуют структуру) на основе некоторых пользовательских параметров (длина, высота, …).

Итак, у нас есть ObjectStore со всеми простыми объектами и PrefabStore (которые содержат только параметры пользователя для создания сборного).

Мы могли бы сгенерировать этот сборный элемент и его объекты только на уровне React (таким образом, рендеринг сборного элемента всегда синхронизирован с параметрами сборного элемента в хранилище), но по техническим причинам нам нужно, чтобы все эти простые объекты сборного элемента действительно существовали на уровне хранилища. Другими словами, нам нужно сгенерировать объекты сборного объекта в хранилище (ObjectStore, поскольку в нем хранятся простые объекты).

Вопрос в том, где (на уровне хранилища), когда и как генерировать сборку и все ее зависимые объекты, и где мы должны хранить сгенерированные объекты, зная, что:

  1. Когда параметры prefab обновляются, нам необходимо повторно генерировать и обновлять объекты (существующие объекты могут быть перемещены, повернуты, полностью удалены).
  2. Мы не можем вычислить сгенерированные объекты prefab на уровне представления React, поскольку нам нужны эти сгенерированные объекты на уровне хранилища (поскольку эти объекты могут взаимодействовать с другими, они также нужны нам при создании файла со всеми существующими объектами).
  3. Создание сборного объекта и его зависимых объектов — сложная и медленная задача: мы не можем вызывать эту функцию генерации каждый раз, когда нам нужно отобразить сборный объект. Кроме того, как я уже упоминал в предыдущем пункте, нам нужна ссылка на сгенерированные объекты, чтобы они существовали в хранилище.

Чтобы помочь понять, что такое сборный и простой объект, и почему нам нужно, чтобы объекты сборного объекта существовали на уровне хранилища, вот скриншот нашего приложения: введите описание изображения здесь

Мои решения:

  1. Создание сборных и зависимых объектов в компоненте React «на лету».

Плюсы: объекты рендеринга сборных и зависимых объектов всегда синхронизированы с данными сборных. Когда параметры prefab обновляются, React автоматически визуализирует prefab и снова генерирует объекты.

Минусы: объекты на самом деле не существуют. Их нет в ObjectStore, поэтому я не могу с ними взаимодействовать (отображать список объектов, генерировать файл со всеми объектами, …).

  1. Создайте сборные и зависимые объекты один раз в действии, затем заполните зависимые хранилища (ObjectStore, PrefabStore) сгенерированными объектами.

Плюсы: все объекты хранятся в собственном хранилище.

Минусы: когда вы обновляете сборку (перемещение / поворот / изменение размера), сложно обновить все зависимые сгенерированные объекты, и вам нужна куча сохранений в хранилище объектов, чтобы убедиться, что объекты синхронизированы с сборкой, к которой они принадлежат.

  1. Создавайте сборные и зависимые объекты «на лету», но в хранилище с запоминанием. Плюсы: зависимые объекты всегда синхронизированы объекты действительно существуют на уровне хранилища (не уверен, как справиться с этим запоминанием в двух разных хранилищах: PrefabStore и ObjectStore).

Минусы: я не знаю, как обрабатывать запоминание в двух разных хранилищах: сборном хранилище для сборного объекта (который все еще имеет свойства положения / поворота) и ObjectStore для сгенерированных объектов.

Комментарии:

1. Я не уверен в вашей реализации flux, но если вы используете Redux (и даже если вы этого не делаете), запоминаемые селекторы Reselect являются общим шаблоном для эффективной обработки вычисленных данных (в частности, в ответ на пункт 3). Везде, где вам нужна ссылка на объект, вы можете import использовать селектор. Это упрощает ваше состояние и оптимизирует вычисления.

Ответ №1:

Сложно ответить на подобные архитектурные вопросы — вы эксперт в своей собственной системе и домене, но здесь все равно идет:

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

Одним из вариантов может быть:

  1. Какой-то объект сборных моделей, который знает о параметрах одного сборного «шаблона» и имеет метод генерации для создания и возврата соответствующих объектов (возможно, метод генерации должен принимать некоторую информацию о местоположении или что-то в качестве параметров). Сборная модель может быть отделена от любых хранилищ в отдельном модуле кода. Метод generate может быть чистой функцией в своем собственном модуле, если хотите.

  2. Хранилище сборных может напрямую хранить сборные модели (возможно, самые простые) или просто данные, необходимые для их создания.

  3. Хранилище объектов имеет обработчик для действия ADD_FROM_PREFAB, который запрашивает в хранилище сборных данных соответствующие данные / экземпляр сборных моделей, вызывает для него generate и, наконец, добавляет возвращенные объекты в свое состояние.

  4. Затем пользовательский интерфейс просто отображает сцену из ObjectStore, а не из сборного хранилища (хотя, предположительно, сборное хранилище также используется для пользовательского интерфейса сборных библиотек?)

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

Комментарии:

1. Спасибо за ваш ответ. На самом деле я использую эту опцию прямо сейчас (ну, почти то же самое, см. Решение 2) в моем исходном сообщении): у меня есть сборная модель, которая генерирует все зависимые объекты, затем все зависимые хранилища (ObjectStore) прослушивают действие «PREFAB_GENERATED», извлекают сгенерированные объекты и помещают их в свое собственное хранилище. Я недоволен этим решением, потому что, когда я обновляю свой сборный (параметры, положение, …), Мне нужно обновить все зависимые объекты (переместить / изменить размер / УДАЛИТЬ полностью), иначе заново сгенерировать мой сборный. Как убедиться, что объекты всегда синхронизированы с параметрами сборных?

2. Один из вариантов — сохранить индекс готовых-> сгенерированных объектов в ObjectStore. Затем вы можете прослушать соответствующие действия, связанные с обновлениями сборного элемента в ObjectStore, и у вас есть возможность обновлять объекты на месте на основе изменений, а не повторно генерировать их, что может значительно повысить производительность. Код для обработки этого может быть в сборном модуле (например, он принимает массив объектов и возвращает обновленный массив, потенциально обновляя на месте).

3. Что касается альтернативы запоминания, поскольку вы, по-видимому, не используете неизменяемое состояние, вы можете хранить в ObjectStore ссылки только на предварительные файлы. Когда представление запрашивает хранилище объектов для предварительных объектов, в этот момент хранилище объектов генерирует объекты и кэширует их вместе с предварительным объектом, как это было тогда (я думаю, вам нужно будет скопировать его, если он изменяемый). Если у него есть кэшированный список объектов с одинаковым префиксом, вы можете просто повторно использовать его, в противном случае замените его восстановленным списком. Не нужно ничего запускать, чтобы сказать, что ваше хранилище объектов обновлено, поскольку это просто кэширование, а не изменения состояния.