Нужно ли использовать MV* паттерны в React приложениях?
Здравствуйте. Делаю проекты для портфолио на собеседование, поэтому интересно, насколько в вебе, а конкретно в связке с реактом нужно следовать архитектурным паттернам. И нужно ли вообще? Вопрос по большей части задан потому что общее представление о них имею, но как ПРАВИЛЬНО реализовывать это на React-приложениях не совсем представляю. Взять, для примера, MVC.
Насколько я понимаю, view - дочерние (относительно корневого компонента) компоненты, у которых реализуется метод рендера и, возможно, какое-то крайне простое состояние (значение у инпута, например).
Если представить, что Redux для нашего проекта это излишне, что тогда выступает в роли модели? Состояние корневого элемента, из которого данные передаются через пропсы в дочерние компоненты? Тогда выходит, что корневой компонент описывает и M, и V. А контроллер это тогда что?
Конечно же речь идет не о лендосах и не о сайтах в принципе, а именно о приложениях - мессенджеры, несложные графические редакторы, etc. Также буду рад ссылкам на репозитории/сайты с best practices по использованию архитектурных паттернов.
profcat, ну подобные решения, типа реакта скорее MVVM реализуют, потому как бы тот же MVC тут сложно впихнуть. У нас есть слой вью, с которым взаимодействует пользователь, и есть model -связь с сервером, туда данные уходят, оттуда мы их забираем и все передаем во view. Отдельно выделить конкретный пласт контроллера сложно.
profcat, Это подходы были придуманы для вполне конкретных архитектур и задач, где они решали вполне конкретные проблемы.
В современных веб приложениях многое устроено совсем по другому. И поменялось уже настолько что попытка привнести "правильный" MV* паттерн туда где уже нет тех проблем и ограничений, для которых они создавались, нет такой же структуры, по большей части создаст просто лишний код и ненужную сложность, без какой-то явной пользы.
Можно конечно говорить о частичной реализации какого-то паттерна, вот с такими оговорками, вот такими изменениями, и вот этот термин будет теперь значить не то что он значит а другое. Но это если сильно хочется сказать что какой-то паттерн как бы есть, на самом деле, паттерн - это шаблон, либо вы делаете по нему, или признайтесь что делаете что-то другое.
Общие какие-то моменты все равно будут потому что в любом приложении же есть данные, логика и представление данных, это никуда не делось, но никаких MV* паттернов в реакт приложениях никто не реализует.
Даже если слой реакт-компонентов назвать View, то без M* это будет что-то другое.
все MV* можно грубо назвать способами связать M и V.
Если это C - то у вас должен быть контроллер в явном виде. Если у вас какой-то код где-то выполняет некоторые функции контроллера, то это все равно не контроллер.
Если это P или VM то же самое.
Если вы это вкорячите в реакт "по правильному" то с большой вероятностью будет гора костылей.
Моделей в классическом их виде в реакт приложениях тоже не пишут. Можно но незачем.
И в целом разделение другое - отдельно данные, отдельно логика данных, отдельно представление.
Логика представления либо в самих компонентах, если она локальная, либо где-то еще (редьюсеры, экшены, сервисы) если она глобальная. Сейчас уже и логику представления от самого представления начали отделять (привет хуки!).
Так что можете назвать приложения на реакте написанными с использованием паттерна V*
Есть View, который реализует реакт и куча способов как построить остальное приложение. Там ООП, функциональщина, реактивность, синглтоны, очень-умный-удаленный-стейт, магические байндинги и прочее. Кто что придумает, в меру своих способностей и используемых библиотек для реализации логики - данных и их подходов.
Но какого-то "паттерна" такого же устоявшегося и известного как MV* нет.
Что-то из MV* можно построить и на реакте. Но этого не делают не потому что никто не осилил, а потому что это не нужно, усилий много, пользы меньше чем вреда.
Для академического интереса можете реализовать их все. Соберете пару лайков.
А потом обратно на работу писать код в том виде в каком это более быстро, удобно и эффективно.
Это подходы были придуманы для вполне конкретных архитектур и задач, где они решали вполне конкретные проблемы
Что это за архитектуры, и какие конкретные проблемы?
попытка привнести "правильный" MV* паттерн туда где уже нет тех проблем и ограничений
Что за проблемы и ограничения, которые были тогда, и их нет сейчас?
Если это C - то у вас должен быть контроллер в явном виде. Если у вас какой-то код где-то выполняет некоторые функции контроллера, то это все равно не контроллер.
Что такое контроллер в явном виде? Файл, у которого в названии есть *Controller*? А если я вынес код, который выполняет некоторые функции контроллера из компонента в отдельный файл/модуль или хук, это контроллер?
Моделей в классическом их виде в реакт приложениях тоже не пишут.
PxlFxr, Вы хотите к тексту подокапываться с умным видом или расспросить детали и что-то новое узнать?
Если подокапываться - то без меня, не согласны, расскажите как оно все на самом деле, подробно, понятно, чтобы было полезно.
Если что-то новое узнать, то непохоже.
Robur, Я с вами в целом согласен, что городить mvc на фронт далеко не всегда имеет смысл, хотя этот подход и без труда можно тут применять. Просто некоторые доводы показались не полными. Говорите про проблемы, не говорите какие. Так же и про контроллеры с моделями. Ну или вот это:
писать код в том виде в каком это более быстро, удобно и эффективно.
В каком виде писать код на реакте быстро, удобно и эффективно? Как вы сами строите архитектуру большого приложения, какие подходы? Я без сарказма спрашиваю, мне действительно интересно.
В каком виде писать код на реакте быстро, удобно и эффективно? Как вы сами строите архитектуру большого приложения, какие подходы? Я без сарказма спрашиваю, мне действительно интересно.
В данный момент - функциональный подход на хуках + реактивные сторы на mobx. Разделение по сторам в зависимости от "типа" данных - если это глобальный стейт для юай - один стор, если какие-то бизнес-сущности - другой. Однако можно делать и по другому - в стор собирать данные относящиеся к какой-то части приложения, например стор со всем user-related, стор для служебных данных какого-то сервиса и т.п.
Логика, которая относится к данным - в экшенах стора. Логика представления, которая должна использоваться в разных компонентах - в хуки или просто функции в отдельном модуле.
Так как работа с сервером через gql, то данные представляющие собой "серверные" сущности отдельно нигде не хранятся а лежат в кеше аполло. работа с ними и модификация соответственно через вызов мутации, и обновление либо ответом с сервера, либо optimistic update.
Это один из многих вариантов как можно построить архитектуру, этот для меня наиболее оптимальный и хорошо структурированный.
Это не единственный подход конечно. в прошлом был редакс, но он на мой взгляд куда более бойлерплейтный и поощряет хуже структурированный код.
В результате разработки всё-таки понял, что редакс как раз самое то: прокидывать через пропсы и контекст мне не понравилось, некрасиво. Другой вопрос - производительность. Особенно когда надо постоянно копировать большую часть стора если в нем что-то меняется