Pull to refresh
1
Send message

Ваш пример я понял как "из домена финансов нам надо взять класс в домен заказа".

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

А это значит, что описание класса существует в общем домене, в финансах будет просто создание экземпляра, а в заказах создание и внедрение в этот класс.

Аналогично делается и с композаблами: помните выше я писал про фабрики и функции высшего порядка?

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

Я бы еще понял классы в Vue 2, но в 3...

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

Значит они изменили доменную область и должны находиться в других местах, согласно новым реалиям.

Что так же применимо и к классам

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

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

А, если это запросы API, то вообще интерцепторы используем и catch становится нужен в исчезающе редких случаях, а где нужно, там он скорее всего будет специфичную логику иметь для конкретной реализации и это в дополнение к тому, что прописано в интерцепторе, т.к. логика в нём максимально базовая и агностичная к пользователю вызова.

Композаблы это не про разбиение кода компонента.

Композаблы про создание самодостаточного или служебного кода: про вычисления, про что угодно - зависит лишь от задачи. Это просто фабрика.

Композабл может быть создан как для компонента, так и для других композаблов, а так же и для использования внешним потребителем (экспортируем из ui, например).

Мы в проекте сейчас, например, используем наравне Pinia и композаблы:

  • Pinia удобна для стора, остальное - композаблы

  • Некоторым сторам создали фабрики для создания разных инстансов сторов со своими дополнениями/изменениями, но в базе своей использующих 1 стор - аналог наследования...

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

  • Есть композаблы, которые являются адаптерами - снова что-то из ООП...

Как видим принципы ООП прекрасно ложатся на композаблы.

По вашим ответам/вопросам поясню, что композабл:

  1. Можно передать куда угодно и состояние динамическое: хотите инкапсуляцию и персональное состояние на композабл - пожалуйста, хотите синглтон - пожалуйста

  2. Не надо думать с композаблом об этом - используем где надо и только то что надо. Хоть в композабле, хоть в классе можно написать 100500 методов, которые будут выполнять только console.log, но это не значит что он привязан к конкретному компоненту - всё зависит от того что написать в композабле

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

  4. Про внедрение уже сказал: мы можем хоть паровоз из композаблов построить в 100500 этажей. А если надо где-то что-то взять и сунуть в прототип как в классах, чтобы доступно стало всем, то - спасибо - не хочу искать это место "где-то в проекте", чтобы разгребать почему метод не такой как ожидается

Зачем вы тащите классы в Vue? Что мешает написать композабл? Любой класс можно переписать на композабл и это:

  • Следует парадигме Vue

  • Использовать все возможности Vue

  • Расширяемо

  • Переиспользуемо

  • ООП-эшно, внезапно! Ибо композабл можно использовать в другом композабле, да хоть цепочку устроить в N потомков

  • Повышает комфорт разработки ибо не развивает зоопарка, где часть использует композаблы, а другая, видимо "трушная" часть использует классы и не приходится склеивать 2 системы, а пользуемся тем что даёт фреймворк из-под капота

И да, если цель "не учить новое", то это и не надо, т.к. используются те же возможности, что и в клмпонентах

О чем и речь: any - зло, если только на проекте, которым можно полноценно управлять.

Если мы говорим о внешних зависимостях, то any вполне применим, т.к. типобезопасность ts - миф и легко обходится, да и сам ts тупит нормально и, порой, только костылями его можно заставить думать как хотим мы.

p.s.

хоть речь не о нем, а лишь в качестве примера, тот же cloneDeep, когда я смотрел последний раз, был на js и в jsDoc у него был указан аргумент как * - any

Функция глубокого копирования по аналогии с lodash cloneDeep, блоки catch.

Т.е. речь о ситуациях, когда нам придётся либо обвешиваться type guard, что не гарантирует что все случаи предусмотрели (человеческий фактор / неопытность разработчика), либо как раз создадим головную боль потребителю, которому ts будет ругаться, что его тип не совместим с unknown.

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

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

НО, это должно быть осознанное использование any автором библиотеки, а не "я художник - я так вижу".

"Используй unknown", скажет кто-то, но unknown - головна боль приведения типа каждый раз и не всегда это уместно, поэтому, чтобы этого избежать и пользователи сказали "спасибо", вместо мата в 3 этажа, имеет смысл указать any

Для чего публиковать настройку для 8 версии, если уже надо на 9 бы, т.к. для 8 много инфы.

Какие-то нюансы? Не понятно

Это да, но его можно подключить для 9 версии: у нас в проекте это настроено.

Мучался с конфигом неделю, наверное, чтобы разобраться в Eslint 9, чтобы всё работало, но успех успешен:)

Vue3 + Vite + TS + Eslint 9+

Все плюсы и минусы описаны в доке. Весь проект можно писать на ref и reactive вообще не использовать.

Зато синтакис property.value, в подавляющем большинстве случаев, сразу будет говорить о том, что используется реактивная переменная, а не что-то еще.

Можно, пожалуйста, хотя-бы один аргумент про удобство и почему это - извращение?

Можно:)

Задача:
- Сделать строку поиска
- Введенные значения отправляются на сервер и результаты отдаются на фронт

РЕШЕНИЕ 1. Делать через computed:
- реагировать на изменение значения в поиске
- отправлять запрос на сервер
ТАК НЕЛЬЗЯ делать и это и назвал извращением, потому что computed не для того создан.

РЕШЕНИЕ 2. Делать через computed, но при этом computed - лишь часть логики, которая будет выглядеть как:
- ввели значение в строке поиска: сработала v-model
- среагировали вотчером на изменение значения переменной
- записали полученные с сервера данные в новую переменную
- обработали результаты поиска в computed

Как-то много телодвижений...

РЕШЕНИЕ 3. Метод на событие input элемента / компонента строки поиска:
- ввели значение в строке поиска
- среагировали на событие элемента / компонента - отправили запрос (1 функция)
- обработали данные в методе и записали в переменную результата (2-ая функция внутри первой функции)

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

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

Если вам это очевидно - ну ок :) Из-за таких "это же очевидно" потом и возникают "а я думал вы поняли / имели это в виду". Нет, не очевидно, если об этом не сказано прямо. Да и косвенных тому намёков нет. Если вы угадали, что это про валидацию, могу только порадоваться вашей догадливости.

Вероятнее валидировать придется на событии change, либо в режиме realtime, раз уж на то пошло.

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

очевидно у вас возникнут проблемы с перфом из-за валидации формы

всё зависит от конкретной ситуации, ведь это может быть как форма на 2 инпута, так и форма, состоящая из десятков, а то и сотен полей (привет no-code / low-code конструкторы) и вот получили тормозного монстра, потому что computed обсчитывает валидацию на каждый чих в форме, поэтому каждой задаче своё решение и постулировать "В реальной жизни, к счастью, никто не следит на событиями элементов формы в vue, особенно в рамках валидации полей " не стоит. Как уже видно из примеров выше, следим когда это требуется.

Не было контекста про валидацию, равно как и был пример в статье про поиск. Это уже ваше сообщение про валидацию и, если говорить только о валидации или чем-то другом - уход от общего к частному, что вы и делаете. Речь же о более широком использовании.

И да, я не против computed для обработки валидации, но опять же это не всегда уместно - зависит от требований: вероятно валидировать нужно всего 1 раз при нажатии на сабмит и тогда предпочтительней будет метод, а не вычисляемое свойство, которое запускается на каждое изменение, ведь computed не бесплатен.

"Не валидацией единой живем"

Согласен с предыдущим оратором, т.к. не валидацией единой живем. Тот же запрос при вводе в поле поиска удобнее сделать через событие элемента, а не через вотчеры. И computed тут вообще никак не поможет.

p.s. при желании можно и через него сделать, но это извращение

Нет проблем: вызываем файл в PowerShell (./createPage.sh) или через терминал гита.

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

Можно писать на js так же: с подсветкой ошибок и выводом их в консоль, + подсказки работают в ide, только не будет крашиться приложение, если тип ошибочен.

Это достигается связкой Ts + jsdock + включенная валидация js в vs code

Но! При этом мы пишем js, а не ts и не имеем той массы условностей и многословности, которые заставляет нас делать ts

Ts установлен в dev dep и служит для того для чего и нужен: сопоставляет типы

Пожалуйста, старайтесь использовать shallowmount и только потом mount, когда он реально нужен или без него никак не получается, т.к. это убережет от кучи проблем, связанных с mount, аля "сломалось что-то на 3-4 уровня вниз, а падает именно этот тест и теперь ищи и разбирайся почему".

Не понятна проблема стабать состояние компонента ui? Он же по дефолту имеет значения пропсов и в тестируемом компоненте он маунтится именно с дефолтным состоянием изначально. Если же нет, то надо понимать откуда берется это состояние:
- если из глобального стейта, то перед выполнение теста установить нужное значение в стейте
- если в ходе работы логики тестируемого компонента - вообще не стоит переживать, т.к. это поведение компонента и это даже можно протестировать
- если хардкодом прописано значение пропса - можно стабать вручную

Но, в любом случае, по возможности, надо стараться по минимуму стабать руками компоненты, т.к. это несет много банальных рисков: "добавили фичу / исправили баг в компоненте, а тест не обновили".

Несколько моментов за которые зацепился глаз:

  • Зачем стабать вручную дочерние компоненты, если это уже сделал shallowmount? Если это только из-за слота, так дефолтный слот можно рендерить с помощью renderStubDefaultSlot

    Без явной необходимости не стоит стабать вручную дочерний компонент и не будет (почти) проблем в будущем при измении их контрактов, потому что тест будет смотреть на реальную реализацию компонента, а не его ручной стаб в тесте.

    Имхо. Очень мало ситуаций когда надо стабать вручную компоненты. Как пример на скорую мысль, приходит только: у тестируемой сущности нет четкого шаблона (тесты в ядре vue) или надо настабать не дефолтные слоты, что может решиться использованием mount, а не shallowmount.

  • Сброс моков: для примера это ок, чтобы наглядно было, но в проекте это можно вынести в глобальную область, т.к., когда 1 компонент, это всё интересно и прикольно, но, когда из раза в раз приходится писать, утомляет. Это вкусовщина, на самом деле. Упоминаю на всякий случай: вдруг не в курсе возможности и это можно описать отдельным абзацем на самом деле.

  • Часть импортов из vitest можно не делать: работает по дефолту, т.к. всегда доступно в тестах, если настроить vite.config

Мы решили это так: если есть какой-то компонент локальный для сущности слоя, то структура будет, например: entities/parent-component/components/child-component, где child-component, в свою очередь, будет иметь свои папки (utils, store, styles и т.д.). Таким образом получается, что сущности, которые точно не переиспользуемые, не размазываются по приложению.

Да, это не чистый fsd, но и в доке написано, что её может потребоваться модифицировать. Зато это даёт как свободу и переиспользуемость fsd, а также снижает порог входа для новых разработчиков (или старых тех кто с каким-то модулем столкнётся впервые).

1

Information

Rating
6,269-th
Registered
Activity