Vue-FAQ
919 subscribers
556 photos
90 videos
548 links
Канал сайта https://vue-faq.org
Информация о Vue.js, фронтенд разработке и не только

Contacts: @RuslanMakarov
Download Telegram
Во Vue 3 есть важная и нередко используемая конструкция, у которой нет имени. Это то, что обычно называют "композабл с глобальными рефами".

Но:
1. Это не композабл по определению
2. Там не обязательно рефы
3. Они не "глобальны"

В общем случае структура данного объекта - экспортируемые из ES модуля реактивные данные и функции для работы с ними.

Функционально они заменяют "сторы" Pinia. Называть их тоже stores двусмысленно и нелогично. Вообще, молиться на "глобальный стейт" после появления идеи JavaScript signals и их всевозможных реализаций, включая Vue Reactivity API, архаично.

Мне кажется, самое подходящее название для данной конструкции - [реактивный] бизнес объект (РБО). В них инкапсулируется логика предметной области и приложения, они не привязаны к конкретным компонентам, и по аналогии с другими языками и фреймворками, этот паттерн - Business Object - выглядит вполне подходящим.

Кроме того, позиционирование именно как "бизнес объект" будет требовать явного отделения от него инфраструктурного слоя - работы с Backend API, например. То есть, стимулировать использование лучших практик и наработок из других сфер разработки ПО, еще более переводя Vue.js из фреймворка для небольших проектов в разряд enterprise level решений.

#architecture #vuejs #reactivity #rbo #composables
Аспект проектирования при основных типах методологий разработки программных систем:

Каскад (waterfall) - заказчик дает четкие требования, по ним строится архитектура системы, программисты делают по ней код.

Гибкая (agile, XP, итеративная) - заказчик дает общие требования, по ним строится прототип архитектуры системы, программисты делают по ней код, систему показывают заказчику, вносятся корректировки, выпускается следующая версия и.т.д по кругу.

DDD (domain-driven design, предметно-ориентированная проектирование) - заказчик и программисты постоянно тесно работают над выработкой четкой модели предметной области, которая затем практически один в один становится скелетом архитектуры программной системы.

Каскад применяется для более-менее типовых задач и когда есть четкие требования (SRS, техзадание).
DDD увеличивает вероятность успеха при решении сложных задач, с нечеткими и меняющимися требованиями и необходимостью исследования предметной области.

#architecture
Чистая архитектура (Clean Architecture) — это способ разделения функционала по степени его близости к предметной области приложения.

Она даёт:

- Независимость от зависимостей. Архитектура вашей системы не зависит напрямую от существования какой-либо библиотеки. Это позволяет использовать фреймворки как инструменты, а не втискивать свою систему в их рамки.

- Тестируемость. Бизнес-правила можно тестировать без UI, базы данных, веб-сервера или любого другого внешнего элемента.

- Независимость от UI. Пользовательский интерфейс можно легко изменить. Например, веб-интерфейс может быть заменен на мобильный, без изменения бизнес-правил.

- Независимость от внешних сервисов. Вы можете заменить, например, MySQL на Mongo, поменять платедного провайдера или что-то еще. Ваши бизнес-правила просто ничего не знают о внешнем мире.

Именно по рекомендациями Clean architecture не следует обращаться к web API напрямую из стора. Подобные требования есть у многих методологий проектирования ПО

#architecture #cleanarchitecture
Мир IT крутится вокруг данных. Если задуматься, 99.999% времени любой компьютер внутри себя просто перекладывает данные с одного места в другое.

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

В data lake складывают неструктурированные данные, data warehouse - уже структурированные, удобные для запросов.

#data #architecture
Для любителей FSD описание проекта на Vue на нем (тудушка)

В качестве выводов - констатация факта, что по FSD все сделать нельзя, даже такой маленький проект, и надо искать компромисс между FSD методами и не FSD методами в одном проекте.

#fsd #architecture
Аргументация против глобальных автоимпортов (типа тех, что в Nuxt) от Artyom Tuchkov

1. Это явно - ты всегда видишь, откуда взялся компонент и в один клик можешь провалиться в него, а не в *.d.ts ;)

2. Это наглядно видно не только в редакторе, но и на всяких гитхабах, когда смотришь там код, с автоимпортами тебе придется гадать, откуда взялся компонент

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

4. Не нужно генерировать портянку *.d.ts для того, чтобы редакторы видели их, и, как следствие, без них ты получаешь более качественный тулинг и анализ твоего кода

5. Ты уверен, что тришейкинг работает правильно и ты явно контролируешь загрузку каждого конкретного компонента в каком-либо месте, а не полагаешься на то, что за тебя это каким-то магическим образом сделает автоимпорт

6. Импорты может проставлять сама IDE, а еще их можно сворачивать в 1 строку, если визуально отвлекают

#architecture #bestpractices #tip #nuxt
Чтобы выделить из компонента отдельно некий функционал с реактивным состоянием, были созданы composable функции (называемые "функциями", хотя по сути это объект созданный через js замыкание - closure).

Чтобы использовать функционал с реактивным состоянием между несколькими компонентами, можно задействовать js модули либо Pinia/Vuex сторы.

Иногда нужно нечто среднее - подобную сущность с реактивным стейтом и функционалом на нем, но используемую в нескольких связанных компонентах (например, в Tabs или каких-то виджетах), - то есть, в некотором локальном контексте. Для этого можно в общем родительском компоненте создать composable, который передать потомкам - либо через provide/inject (лучше), либо через props (не надо).

В этом случае данный реактивный объект будет жить в своем ограниченном контексте и не будет конфликтовать с оставшейся частью проекта.

#reactivity #bestpractices #architecture
Выражение "городить свои велосипеды" в IT заиграло новыми красками

Иногда оно используется по делу, но чаще имеет уничижительную форму, показывающую, что человек вместо популярного, раскрученного решения использует что-то свое или малоизвестное.

Если тебе нужен индексируемый поисковиками сайт, надо писать на Nuxt, а не городить отдельную или динамическую отрисовку. Нужно использовать VueUse, потому что это швейцарский нож в любых ситуациях. Для соединения с бэком надо всегда подключать Tanstack vue-query, потому что у него десятки тысяч звезд на GitHub, все его используют, и он легко решает кучу твоих проблем, о которых ты раньше даже не догадывался, но теперь они у тебя есть. Ну и, конечно, Tailwind!

О VueUse уже много говорилось. Как и об #ssr. Как и о Tailwind.

vue-query образовался из react-query, который действительно решал проблемы Реакта. Но во Vue нет этих проблем. Vue предоставляет все инструменты для эффективной и элегантной работы с бэкендом.

Проблема "решений", пришедших и навязываемых из других фреймворков - это действительно проблема. Человек, перешедший с бэкэнда и даже с другого языка программирования возможно будет писать более качественный Vue код, чем переучившийся с Реакта.

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

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

Ну и не будем забывать, что Vue - это тоже велосипед, написанный в эпоху диктатуры Angular, React, JQuery и других солидных, проверенных и общепризнанных решений.

#esse #architecture
Кто занимается микрофронтендами - познавательная статья Micro Frontends на сайте Мартина Фаулера

#microfrontends #architecture #bestpractices
Примеры файловых структур Vue проекта для плоской, атомарной, модульной и FSD архитектур

Предпочитаю всегда модульную с небольшими вариациями

#architecture #fsd
Комментарии к прошлому посту ярко показывают, стоит ли тащить в свой проект чудо природы под названием FSD.

Модульная архитектура даёт понятную четкую декомпозицию проекта, хорошо разделяя ShoppingCart от UserAccount, например. Позволяя видеть в файловой панели только относящиеся к нужному модулю ресурсы, и работать над модулями независимо.

Общие элементы типа BaseButton можно держать в App, а можно выделить под них отдельный проект (вроде своей дизайн системы) и подключать папкой ui через git submodules. Так же, как и объекты типа api.

Между модулем и однофайловым компонентом есть промежуточные структуры - виджеты типа FileUploader, например, в которых есть чисто их композаблы, утилиты, компоненты, типы. Их удобно держать в своих папках без разделения по поддиректориям.

Довольно сложный вопрос, где держать и как наименовать файлы с бизнес-логикой - как реактивной, так и обычной. Однозначного совета пока нет. Скорей тут надо использовать программерские подходы из обычного ООП.

#architecture
Основные принципы локально-ориентированной (Local-First) разработки

Локально-ориентированная разработка имеет сходства с подходами offline-first, но идет дальше, уделяя больше внимания контролю пользователя и владению данными. Вот ключевые принципы, определяющие настоящую локально-ориентированную веб-приложение:

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

- Независимость от устройства: Данные доступны на разных устройствах без проблем.

- Независимость от сети: Основные задачи могут выполняться без подключения к интернету.

- Легкость совместной работы: Приложение поддерживает легкое совместную работу, даже в автономных сценариях.

- Долговечные (Future-Proof) данные: Данные пользователей остаются доступными и пригодными для использования с течением времени, независимо от изменений в программном обеспечении.

- Встроенная безопасность: Безопасность и конфиденциальность являются фундаментальными аспектами дизайна.

- Пользовательский контроль: Пользователи полностью владеют и контролируют свои данные.

#bestpractices #architecture
Options API - это FSD
Composition API с composables - модульная архитектура.
(аналогия)

FSD в основу иерархичного разбиения ставит программный функционал. Модульная - доменные сущности

Можно провести аналогию c физиологией человека

Можно изучать человека разбивая его на руки, ноги, тело, голову и внутри уже по органам, тканям и т.д.

FSD же на верхнем уровне разбивает сперва по органам и тканям - кровеносная система, ЖКТ, мышечные ткани, и внутри уже разбивает по доменам - рот и кишечник внутри ЖКТ

Так же и с переходом от Options API к Composition API. Было разбиение по фичам (options), стало - по бизнес / доменным сущностям (композициям).

Так лучше.

#fsd #architecture
Иллюстрации к принципам ООП из выдающейся книжки Graddy Booch Object-Oriented Analysis and Design with Applications

Очень полезна фронтендерам в том числе

#oop #architecture #gradybooch
При использовании сторов иногда получаются проблемы из-за перекрестных ссылок, которые дают ReferenceEror

При использовании модульных рефов может возникнуть аналогичная ситуация - например, когда переменная refA определяется в модуле А, который использует модуль B, а B вешает watch на refA. Причем это применимо только к системе реактивности Vue, потому что с обычными объектами такой проблемы нет.

#store #reactivity #architecture
Решения для проблемы выше

1. Переделать. Перекрестное использование сущностей - архитектурно плохая практика. Каждая должна содержать в себе только свое состояние и логику работы с собой. Если А использует B, значит B - утилитарен по отношению к А (например, А - какой-то бизнесовый стор, B - отвечает за открытие диалогов). Но тогда коду из А нечего делать в B.

К созданию сторов / модульных рефов надо подходить так же ответственно, как к проектированию схемы реляционной базы данных. Это координатный базис, и в нем не может быть перекрестных зависимостей.

Если есть логика, которая работает и с А, и с B, то, скорей всего, она прикладная для этих сторов, и должна лежать в отдельной сущности (компоненте, композабле, простом или реактивном модуле, сторе).

2. setTimeout / nextTick, как на картинке. Работает и с модульными рефами, но выглядит уродливым костылём

3. Шина событий (eventBus) для сообщений между сторами. Как самостоятельное решение возможно, но в данном случае опять же костыль.

4. Если refA в примере вынести в отдельный модуль, то ошибка пропадет. То же самое, скорей всего, справедливо и для сторов, но будет выглядеть неуклюже. Выносить надо не голый стейт, а разделять стор грамотно, по ответственности.

5. Не надо пихать реактивность туда, где можно обойтись без нее. Если переменная B зависит от А, и источников изменения А всего один-два, то необязательно ставить watch над А в B, можно обновлять B императивно напрямую. Это уберет прямую зависимость от А в B (если код в А уже как-то использует B), а также повысит читаемость и производительность. В первую очередь касается кода, который работает с бэкенд API.
Так же приоритетно, как и пункт 1.

#store #reactivity #architecture
Атрибуты хорошего кода

Хороший код (ПО) обладает рядом атрибутов, которые делают его удобным для чтения, поддержки и развития. Вот ключевые характеристики:

1. Читаемость

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

2. Модульность и структурированность

Разделение на функции/классы/компоненты (принцип Single Responsibility).
Низкая связанность (low coupling) – компоненты минимально зависят друг от друга.
Высокая связность (high cohesion) – код внутри модуля решает одну задачу.

3. Тестируемость

Покрытие тестами (код легко проверить на корректность).
Изолированность (зависимости можно подменить mock-объектами).

4. Эффективность и производительность

Оптимальные алгоритмы (O-нотация учитывается, но без преждевременной оптимизации).
Минимизация ресурсов (память, процессор, сетевые запросы).

5. Гибкость и расширяемость

Открытость/закрытость (Open/Closed Principle) – код можно расширять без изменения существующей логики.
Использование паттернов проектирования (например, Factory, Strategy, Observer).

6. Надежность и отказоустойчивость

Обработка ошибок (корректные исключения, logging).
Обработка edge-cases (крайние случаи, невалидные входные данные).

7. Поддерживаемость

Документация (хотя бы минимальная: README, docstrings).
Рефакторинг – код можно улучшать без страха что-то сломать.

8. Безопасность

Защита от уязвимостей (SQL-инъекции, XSS, CSRF и др.).
Валидация входных данных.

9. Совместимость и переносимость

Кросс-платформенность (если требуется).
Четкие зависимости (использование package managers: pip, pnpm, maven).

10. Соответствие стандартам и best practices

Следование языковым идиомам (Pythonic way, Java Code Conventions, Vue code style и т. д.).
Интеграция с CI/CD (автоматические тесты, деплой)

#architecture #code
Media is too big
VIEW IN TELEGRAM
Пара советов с утра от автора "Clean code" Боба Мартина

#architecture #bobmartin