Комментарии 18
https://www.npmjs.com/package/vue3-native-decorators
похоже =) ... и это прикольно, честно. Я рад видеть похожие паттерны, это значит я (мы) попали туда, куда нужно. Это значит, что есть "боль", которую хочется закрыть.
Но я не хочу учить декораторы, когда shallowReactive сделает все свойтва объекта, кроме приватных, реактивнымыми. Я хочу минимум нововведений.
После создания модели - все свойства, кроме приватных будут реактивными без всяких декораторов.
Я не хочу помнить о том, что нужно где-то вызвать destructor. И я не думаю, я просто использую контенер.
@alexey_ym, но это круто
Круто, что показали ООП-подход на реальном примере. А как библиотека ведёт себя в больших приложениях — нет ли проблем с отладкой реактивности внутри классов?
Понимаю, что это только пример, но зачем watch за юзером в счетчик? Можно же проверить в момент клика, и я бы даже сказал, что и с watch стоит проверять состояние залогиненности юзера на момент клика.
Можно и так. Здесь нужно смотреть и разбираться с контекстом.
Например, что если логин не только по кнопке, а по событию из другой вкладки или микрофронта?
В примере, я создал связь на уровне моделей в слое приложения. Потому что она существует в бизнес-домене. Мне не нужно думать о том, что это событие должно быть где-то в другом месте проверено, обработано и вызвана загрузка. И таких мест может быть несколько. В компоненте(ах) я просто отображаю состояние и не парюсь .
Зачем вы тащите классы в Vue? Что мешает написать композабл? Любой класс можно переписать на композабл и это:
Следует парадигме Vue
Использовать все возможности Vue
Расширяемо
Переиспользуемо
ООП-эшно, внезапно! Ибо композабл можно использовать в другом композабле, да хоть цепочку устроить в N потомков
Повышает комфорт разработки ибо не развивает зоопарка, где часть использует композаблы, а другая, видимо "трушная" часть использует классы и не приходится склеивать 2 системы, а пользуемся тем что даёт фреймворк из-под капота
И да, если цель "не учить новое", то это и не надо, т.к. используются те же возможности, что и в клмпонентах
Одна из задач , это создать модели с поведением и изменением состояния динамические и передавать куда угодно.
Вторая — брать в любом месте модель и не думать о иерархии и структуре компонентов внутри слоя представления.
Третья - перестать писать шаблонный код, перепишите пример из статьи на composable или pinia, так чтобы он обрабатывал все ошибки и состояния, мог отменять или блокировать выполнение. И кода будет больше чем в 2 раза.
А как вы внедряете зависимости в composable ?
Коспозаблы это не про модель , это про разбиение компонента на части и лучшая организация кода, по сравнению с миксинами. Это переиспользование в слое представления.
Скажу честно, не читал статью и исходный код, сразу пошел к комментам
Все-таки композаблы как концепт полностью самодостаточны и вообще не обязаны быть примитивным "распилом компонента".
1. Все что может ООП работает и на композаблах (исключение, это наследование и проверки на instanceof что в обычном коде нужно примерно никогда), зато КОМПОЗИЦИЯ работает значительно проще и удобнее вместо наследования, а вот с классами с ней несколько больнее
2. Вместо наследования можно применять композицию. Никто не запрещает создать функцию высшего порядка. Например твой DI я достаточно давно в рамках эксперимента реализовывал как раз в рамках sharedComposable не ломая начальную концепцию с композаблами
3. Это все еще несколько отдельное знание которое надо учить. Композабла вообще не обязаны иметь связанность с компонентами. Их можно просто воспринимать как фабрику и все.
4. Классы имеют достаточно много избыточной семантики и функционала. А еще нужно суметь выстроить все правильно чтобы не получить утечку памяти. Я сходу могу сказать, что вам понадобился деструктор за которым теперь нужно слеедить в ручном режиме, чтобы очищать effecScope, либо полагаться только на поведение sharedComposable.. но тогда классы приобретают определенную семантику и мы можем их создавать только в рамках того когда трекинг возможен. Композаблы используемые как генераторы объектов таких же тоже склонны к такой проблеме (так как в базовом сценарии scope имеет родительский который сам проследит за очисткой)
В общем и целом классы создают гораздо больше проблем чем решают, а семантическую разница между фабрикой и классом не сильно велика
Ну вот вы зря не читали, не нужно следить за деструктором. И дело вообще не в классах.
Одна из причин — устранение частого повторяющегося одинакового кода.
Перепишите это на композабл, обработайте все ошибки в каждом действии, добавьте возможность отмены и блокировки. И просто посмотрите объём кода.
После этого посмотрите как этот пример сделает ваш коллега. Он точно сделает что-то не так как вы в обработке ошибок и именовании переменных. Теперь умножьте это на 10.
Сейчас вы скажете можно создать свою библиотеку и сделать служебные функции, что бы избежать повторении. И так в каждом проекте , и вот у нас набор служебных функций типа useVue, или nuxt. И это не остановить
Композаблы это не про разбиение кода компонента.
Композаблы про создание самодостаточного или служебного кода: про вычисления, про что угодно - зависит лишь от задачи. Это просто фабрика.
Композабл может быть создан как для компонента, так и для других композаблов, а так же и для использования внешним потребителем (экспортируем из ui, например).
Мы в проекте сейчас, например, используем наравне Pinia и композаблы:
Pinia удобна для стора, остальное - композаблы
Некоторым сторам создали фабрики для создания разных инстансов сторов со своими дополнениями/изменениями, но в базе своей использующих 1 стор - аналог наследования...
Есть совсем базовые композаблы, которые используются композаблами, которые используются композаблами и даже компонентами, которые используют композаблы, которые используют композаблы - снова наследование...
Есть композаблы, которые являются адаптерами - снова что-то из ООП...
Как видим принципы ООП прекрасно ложатся на композаблы.
По вашим ответам/вопросам поясню, что композабл:
Можно передать куда угодно и состояние динамическое: хотите инкапсуляцию и персональное состояние на композабл - пожалуйста, хотите синглтон - пожалуйста
Не надо думать с композаблом об этом - используем где надо и только то что надо. Хоть в композабле, хоть в классе можно написать 100500 методов, которые будут выполнять только console.log, но это не значит что он привязан к конкретному компоненту - всё зависит от того что написать в композабле
Кода будет не драмматически больше, а иногда и меньше, ибо мы так же будем использовать другой композабл и, что более полезно, мы будем явно видеть откуда у нас та или иная сущность взялась и при больших цепочках наследования защищены от возможности что-то сломать или изменить поведение, как это при наследовании может произойти, т.к. мы явно видим что используем и при6имаем решение осознанно
Про внедрение уже сказал: мы можем хоть паровоз из композаблов построить в 100500 этажей. А если надо где-то что-то взять и сунуть в прототип как в классах, чтобы доступно стало всем, то - спасибо - не хочу искать это место "где-то в проекте", чтобы разгребать почему метод не такой как ожидается
Не буду спорить про компосабл, в оф. документации всё написано.
У вас просто на уровне определения свойств количество кода увеличится. Не говоря про обработку ошибок и отслеживание состояния выполнения. Придётся копировать одно и тоже. Везде будет isloading или ispending, try catch похожие друг на друга.
Я говорю это, потому что я также писал. Я прошел этот путь. Всё было прям как у вас.
Я даже хочу поднять старый код на компосаблах и просто визуально показать разницу.
Видимо придётся переписать самому пример на комплзаблах и опубликовать сравнение
Про кол-во определения свойств такое может быть, но зависит от того как написать композабл и от преследуемой цели. Это может быть как портянка свойств, так и 1 свойство, это может быть функция, извлекающая нужные свойства и вот мы уже 20 строк перечисления свойств родительского композабла превратили в 1 строку.
А чтобы не обмазываться проверками дополнительными, мы же можем создать функцию высшего порядка, которая за нас это будет делать? Определить в любом композабле её можно, да хоть как хелпер отдельный - вот уже и решили эту проблему.
А, если это запросы API, то вообще интерцепторы используем и catch становится нужен в исчезающе редких случаях, а где нужно, там он скорее всего будет специфичную логику иметь для конкретной реализации и это в дополнение к тому, что прописано в интерцепторе, т.к. логика в нём максимально базовая и агностичная к пользователю вызова.
А чтобы не обмазываться проверками дополнительными, мы же можем создать функцию высшего порядка, которая за нас это будет делать?
об этом написано во втором абзатце, я хочу уйти от создания функций. И создания своей библиотеки функций. В каждой компании уже по такой библиотеке. Еще намешано с другими.
Не понять, где композабле для модели, а где служебный. Или тут всё в перемешку? что же делать? Ну... сделаем еще один. Да..ю это же просто. Просто функция.
я не хочу что бы мой коллега помнил, что нужно вызвать где-то там какуюто функцию.
Я хочу помнить максимум 3 вещи: унаследовать от Protomodel, action для асинхроных мутаций и регистрация в контейнере. Остальное должна подсказывать IDE.
А, если это запросы API, то вообще интерцепторы используем и catch становится нужен в исчезающе редких случаях,
везёт вам...
А ещё когда вы импортируете один компосабл на прямую в другой, особенно если они из разных бизнес доменов , вы жестко связываете доменные области, с вытекающими последствиями
Значит они изменили доменную область и должны находиться в других местах, согласно новым реалиям.
Что так же применимо и к классам
Нет , совсем не применимо , потому что композиция в классах, это внедрение, построенное на интерфейсах. А наследования там почти нет.
Ваш пример я понял как "из домена финансов нам надо взять класс в домен заказа".
Если вы берете класс из финансов и в заказах делаете внедрение, то в этом случае я бы предпочел вынести из финансов класс в общий домен, условный shared, и тогда домены не будут иметь связи друг с другом.
А это значит, что описание класса существует в общем домене, в финансах будет просто создание экземпляра, а в заказах создание и внедрение в этот класс.
Аналогично делается и с композаблами: помните выше я писал про фабрики и функции высшего порядка?
Если уж так хочется, то и в композабл можно сделать внедрение как в класс (таким же механизмом), но тогда мы снова возвращаемся к вопросу: зачем?
Я бы еще понял классы в Vue 2, но в 3...
Полного аналога внедрения как в классе у композабла нет, конечно, но есть другие механизмы для реализации и причина, по которой вами выбраны классы, скорее в привычке использования классов, а не в том что описано в статье и в комментариях.

ООП для управления состоянием во Vue