Comments 4
DISCLAIMER: Я буду говорить относительно Vue и только в рамках Vue. Если вы собираетесь читать относительно концепции в других фреймворках и языках, то можете скипать, так как обсуждение каждого фреймворка или другого подхода требует другой аргументации и обсуждения в целом. Данный комментарий больше ориентирован на тех кто воодушивившись уже собрался тащить такой подход к себе в проект
А ради чего Vue который из коробки изначально был MVVM (в последствии реактивная модель по своей сути вышла за рамки классического MV*) пытаться превращать в MVC? Концепции заложенные во фреймворк уже прекрасно работают относительно разделения, а классические подходы в разработке фронтенда закрепляют это еще лучше.
Ну и перепишем предложенный код как он мог быть написанным в классическом Vue исполнении:
"Модель":
function useProgress() {
const isGoing = ref(false)
const percentages = ref(0)
function start() {
isGoing.value = false
percentages.value = 0
}
function finish() {
isGoing.value = false
percentages.value = 0
}
// сохраню изначальную задумку автора
function update(percentages: number) {
switch (true) {
case percentages <= 0:
percentages.value = 0;
break;
case percentages >= 100:
percentages.value = 100;
break;
default:
percentages.value = percentages;
}
}
return {
// для понятности использую самый наивный метод реализации readonly.
// однако так писать не рекомендую
isGoing: computed(() => isGoing.value),
percentages: computed(() => percentages.value),
start,
finish,
update
}
}
Да, это просто композабл. Композаблы это прекрасные кирпичики чтобы выносить бизнес логику или позволять различным компонентам использовать одну функциональность. Создавать классы нет никакой нужды и я надеюсь, что автор это сделал исключительно только ради того, чтобы быть не столь сильно привязанным ко Vue подходам
Представление:
Да не нужно никакую model создавать для передачи. Классические подходы работают прекрасно: пропсы+события это и есть МОДЕЛЬ с которой работает данный компонент (если уж мы начали так представлять). Соответственно
<ProgressBar :is-going :percentages />
Если вам так нравится концепция: передать "все", то есть уже для этого механизм
<ProgressBar v-data="progress" />
Контроллер:
Почему компонент-родитель является контроллером опустим за скобкой, но в классическом представлении для такого уже есть паттерн smart dumb components, когда простое представление контролирует умный компонент.
Итого: натянув MVC предложенный в статье на Vue приложение вы ломаете привычный флоу для Vue разработчиков, усложняете разработку пытаясь реализовать и поддерживать инородные сущности и увеличиваете количество необходимого кода для их поддержания. При этом классические паттерны для работы со Vue (да и в целом Frontend-ом) уже давно выведены и перед такими трюками лучше вначале изучить их и сравнить с тем что могут дать вам они.
Вообще, MVP - это больше про разделение на части большущего кода, который прячется за api компонента. Поэтому сравнивать MVVM с MVP на примере прогресс бара пахнет сомнительной затеей. И фреймворк тут не важен.
Я думаю, что ваш комментарий поможет применить идеи из статьи при работе с Vue и случайно не разругаться с остальными разработчиками на проекте. Мой подход к написанию кода действительно отличается от принятых практик, потому что я привязываюсь к концепциям, а не к принятым в фреймворке реализациям. Что позволяет мне переключаться между фреймворками не замечая разницы. Это не всем подходит, так что спасибо за дополнение :)
Объясню некоторые выборы в статье, возможно вы взгляните на них под другим углом.
На счёт composable. Вы создали функцию, которая возвращает объект, в котором есть поля и процедуры, работающие с этими полями. То есть - вы создали класс (шаблон для создания объектов). Тут уже дело договорённостей. Если на проекте всю кастомную логику держат в composable, во Vue так принято и разработчикам так привычнее - конечно делайте через них. Суть от этого не изменится - это всё еще класс. Я же люблю для создания объектов использовать механизм, который для них предназначается. А функциям и процедурам отводить свою отдельную роль.
На счёт представления не очень понял. Внутри компонента ProgressBar.vue
всё равно придётся указать тип данных пропса (в моём случае Progress
). И он должен быть без методов (ProgressModel
не подходит), потому что это, как вы правильно сказали, dumb component. И на что он будет ссылаться, если нет разделения на данные и модель, мне не понятно. Но у вас компонент ProgressBar
контролируется через модель - а это главное. Остальное - детали реализации, так что для меня это не принципиально.
На счёт контроллеров. В статье я дал им определение: "Это класс объектов, которые подписываются на события от устройств ввода". В моей реализации компонент-родитель подписывается на события, так что относительно MVC для Progress
- он контроллер. Да, он же является и mediator (в ваших терминах "smart component"). Но контроллером, относительно MVC для progress
, он от этого быть не перестаёт.
Ещё раз спасибо за проявленный к статье интерес и полезное прикладное дополнение для разработчиков на Vue
Статья понравилась. Лёгкое и интересное повествование о важной теме, учитывая как слабо развиты концепции MVC, MVP, MVVM в современном вебе. Однозначно жду развития идей и анализа. Спасибо!
UI/UX: Учимся использовать настоящий MVC