Skip to content

Введение

Vue Modeler — комплексное решение для управления состоянием в Vue.js приложениях, состоящее из двух взаимодополняющих библиотек:

  • @vue-modeler/dc — контейнер зависимостей.
  • @vue-modeler/model — библиотека для создания моделей (реактивных объектов с состоянием)

Ключевые концепции

  • Модель вместо хранилища. Нет глобального хранилища состояния. Нет хранилища — нет проблем. Состояние инкапсулировано в модели и является реактивным. Вне модели оно доступно только для чтения и наблюдения. Уничтожение модели равно уничтожению состояния.

  • Действие — объект с реактивным состоянием и поведением. Внутри класса модели Действие — это асинхронный метод меняющий состояние, снаружи (в компонентах и других моделях) — это реактивный объект с состоянием и поведением.

  • Зависимости через внедрение и контейнер зависимостей

    • Модель принимает зависимости как аргументы конструктора. Нет прямых импортов из других модулей. Это позволяет легко извлекать связанные по смыслу модели в отдельные модули и использовать в других проектах.

    • Не нужно думать как создать, получить или удалить модель после использования — за это отвечает контейнер.

Ключевые особенности

  • В основе ООП. Модель определяется как стандартный класс. Наследование, инкапсуляция, полиморфизм, деструктор доступны по умолчанию.

  • Сохраняет типобезопасность. Все подсказки автодополнения будут работать как внутри, так и вне контекста класса.

  • Реактивность Vue. Всё работает на основе реактивности Vue. Не нужно изучать дополнительные API или подходы для создания реактивных объектов.

  • Простота тестирования. @vue-modeler/model позволяет писать меньше кода, это значит нужно меньше тестов. Тестирование моделей не отличается от тестирования экземпляров обычных классов.


Причины создания

Шаблонный код в действиях

Проблема: Действия часто сопровождаются повторяющимся кодом для отслеживания состояния выполнения через дополнительные переменные: isLoading, isPending. В этом коде нет ценности для бизнес-логики, но он раздувает кодовую базу.

Решение: Действие — это объект с реактивными свойствами, отражающими статус его выполнения: ready, pending, lock, abort, error. Дополнительный код не нужен.

Отмена или блокировка действия

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

Решение: Действие содержит методы lock и abort для блокировки и отмены выполнения. Не нужно писать дополнительный код и поддерживать его.

Обработка исключений

Проблема: Обработка исключений дополнительный источник проблем:

  • разработчики забывают о ней;
  • каждый разработчик обрабатывает её по-своему;
  • регламенты не гарантируют, что исключения будет обработано как нужно;
  • обработка требует всегда внимательного ревью кода.

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

Устаревшие паттерны

Проблема: Pinia использует устаревший паттерн фабричной функции для создания хранилища. Такое решение "тянет" за собой дополнительные шаблоны для эмуляции наследования и полиморфизма.

Решение: Поддержка классов и ООП из коробки.

Слишком много реактивности

Проблема: Хранилище Pinia — это объект с реактивными свойствами. Но внутри фабричной функции это реактивные переменные, созданные с помощью Reactivity API Vue. Получаем двойную реактивность и разные интерфейсы взаимодействия на одних и тех же данных.

Решение: Модели — это shallow reactive объекты из коробки. Публичные и защищенные свойства будут реактивны снаружи и внутри без явного применения АПИ реактивности Vue.

Released under the MIT License.