Comments 22

В английском языке нет слова cohesity. Ну и код бы моноширинным шрифтом набирать.

Да, и не стоит этот термин переводить (либо переводить как сцепленность а не зацепление, это семантически ближе).

Причем у кого-то кохижен это зацепление (из того что помню сходу — лекции Немчинского) а у кого-то (википедия например) кохижен это связанность, а зацепление это coupling. Короч каша полная.

Что грустно ибо это одни их самых важных концептов в контексте разделения системы на модули.
Ремарка насчёт Яндекс Музыки и его интерфейса, который очень даже приятный, но с некоторыми оговорками, такими как — кнопки старта/остановки/следующей/предыдущей трек и т.д. на клавиатуре не поддерживается, так же иногда сервис думает непростительно долго думает при выборе в плейлисте с рандомной выборкой, было бы хорошо если бы в течении проигрывания, а лучше в начале, трека происходило выбор следующего трека или даже нескольких ибо при пролистывании он тоже подтупливает. Кнопка не рекомендовать исполнителя/песню работает не совсем очевидно, ибо при нажатии на неё, в рекомендациях всё же иногда выпадают такие удалённые из рекомендаций вещи.
Какие у MVC есть проблемы. Мы их уже проговорили, но проговорим. Тестировать как не понятно, как реализовывать клиентскую валидацию — можно, но сложно, AJAX прикручивается сбоку, надо чего-то делать.

Что? Почему?

Меня больше возмущает следующее:


Придумали его вообще для консольных приложений

Если что, это были ребята из Xerox Parc, и речь шла о графическом интерфейсе. Изначально оно вообще должно было называться Model-View-Editor-Controller но уж больно любил Тругве (я наверное сейчас снова изуродовал имя) аббривиатуры в 3 буквы. Занятно что в списке литературы есть отсылки на все это, но создается впечатление что автор их не очень то читала.


Вообще наискосок прочитал — польза от данного доклада только в ключевых словах для гугла. Не более.

Очень просто. Если контроллер и модель находятся в back-end, а шаблонизация View серверная. Так устроены фреймворки Ruby on Rails, ASP.NET, Django, в общем, везде, где вы пишете серверную шаблонизацию, а на клиент вам приходит собранный HTML, и также уходят данные обратно, с большой вероятностью, это вот этот подход.

т.е. у вас View на сервере, модель на сервере и контроллер на сервере, окей, пусть так. Не понимаю только, почему, если у нас view выносится на сторону клиента, то оно сразу становится Presenter.

В чем у нас здесь проблемы. В single page application такой штуки не построить. У нас постоянно данные на сервер пришли, на сервер ушли, страница перезагружается.

Почему? Вы точно сейчас про архитектуру (взаимодействие разных блоков), а не её имплементацию (полное обновление страницы)?

Во-вторых, совершенно не понятно, куда здесь пихать клиентскую валидацию, и, вообще, клиентский JavaScript, AJAX и все вот это вот? Потому что, если мы хотим что-то быстренькое, − некуда.

Ну, туда же, где вы это делали на сервере, но на клиенте. Никак не возьму в толк, в чём проблема
Дальше третьим пунктом на Presenter честная JS-валидация. Мы ее можем уже спокойно писать, это для нее специально место выделено.


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

Стоп, это как это, вьюшка поменяла модель? Вьюшка сама не может поменять модель, только посредством контроллера.

Модель поменяла другую модель.
Вот тут спорно конечно, но либо это отношения типа родительская модель -> дочерняя модель, либо тут тоже не обошлось без контроллера.

Поменялась нижняя желтая вьюшка. Нижняя вьюшка тоже поменяла модель. Все они дружно поменяли центральную красную вьюшку, и в ней происходит что-то не понятное.

Это у вас описание какое-то непонятное, потому всё и не понятно.

Бонус-вопрос: опишите всё то же самое во flux/redux. Сильно стало понятнее?
Вьюшки идут за данными. Они идут в Store и говорят: «Мне вот это поле, вот это поле и вот это поле».


В итоге любая вьюшка может заиметь доступ к любому элементу стора, прощай инкапсуляция (а потом мы придумаем reselect, чтобы это скрыть)
а потом мы придумаем reselect, чтобы это скрыть

Reselect же придуман не для того, чтобы что-то скрыть (это скорее вы про mapStateToProps в container-ах в redux). А для того чтобы это люто не тормозило при каждом обновлении store.

ну, сама идея селекторов от Дена Абрамова преподносилась как раз под соусом, что мол потребителям не надо будет знать, как устроен редюсер. Ну и частичное решение проблемы производительности, да
что мол потребителям не надо будет знать, как устроен редюсер

Вы, наверное, всё таки имели ввиду store, а не reducer? Потребителям ведь и правда не нужно знать, как устроен reducer.


Ideally, only your reducer functions and selectors should know the exact state structure, so if you change where some state lives, you would only need to update those two pieces of logic.

Вероятно вы об этом. Ну дак у Дена Абрамова этими самыми селекторами являются mapStateToProps. Какая разница как у вас устроен mstp? reselect там, lodash.memoize или ещё что. Ключевое в том, что уже компонент-потребитель об этом ничего не знает.


В общем ваш пассаж про "а потом мы придумаем reselect, чтобы это скрыть" я не понял :) Во всяком случае в случае redux это в документации очень хорошо расписано (деление на контейнеры и компоненты). Никакие reselect-ы для инкапсуляции придумывать не пришлось. Вот для мемоизации — да. Даже фабрики селекторов. Даже weakMemoize-ы, даже вложенные weakMemoize в weakMemoize. Даже proxy с трекингом зависимостей. Что там только не придумали.


Но вот проблем с инкапсуляцией mapStateToProps я не вижу )

Потребителям ведь и правда не нужно знать, как устроен reducer

Им нужно знать какую структуру данных возвращает reducer

Вероятно вы об этом. Ну дак у Дена Абрамова этими самыми селекторами являются mapStateToProps.

Да. Нет. Представьте ситуацию, когда у вас по коду разбросана куча mapStateToProps, обращающаяся к state.someReducerName.field1.field1_1. И вот вы принимаете решение вынести этот field1_1 на уровень выше (state.someReducerName.field1_1) ну или наоборот вынести часть полей с общим префиксом на уровень ниже. И вот вы переписываете все эти раскиданные по коду mapStateToProps.
А вот если бы у вас там вместо этого был селектор типа такого getField1_1(state.someReducerName), вам бы пришлось переписать только лишь содержимое этого селектора и всё.
Им нужно знать какую структуру данных возвращает reducer

Да. Но как устроен reducer им знать при этом совершенно не обязательно. Вы можете поменять reducer без ущерба для приложения, оставив схему store той же. Вы можете задать данные до вызова reducer-а.


Представьте ситуацию, когда у вас по коду разбросана куча mapStateToProps, обращающаяся к state.someReducerName.field1.field1_1

Ох, ну теперь понятно почему вы путаете reducer-ы и данные в store. Ведь вы даже поля в store называете именем reducer-а, ответственного за это поле. Наверное это всё влияние combineReducer-а. На самом деле тут всё наоборот.


Если кратко: данные в хранилище первичны, а то каким образом вы их меняете, и читаете — вторично. Т.е. не то как устроены ваши reducer-ы влияет на то как у вас расположены данные в store, а как раз наоборот. Вы пляшете от данных. Не от reducer-а.


Вот даже само слово "reducer-ы" уже многих путает. На самом деле у вас в приложении есть один главный reducer, тот который вы указываете redux-у. Redux больше не знает ничего. Как этот reducer обрабатывает данные — уже ваше личное дело. Будет ли там combineReducers использоваться, будет ли там хоть 1 switch-case, будет ли там древовидная структура, будет ли вообще какая-нибудь очень кастомная логика — зависит только от вас. Какая сигнатура будет у этих методов — всё на ваше усмотрение. Redux-у плевать. Так что по сути корректнее даже говорить об одном reducer-е. Он может быть вообще плоским (а схема данных древовидной).


В общем суть проста — есть схема данных в store. А есть reducer, который, придерживаясь этой схемы, правит данные по action-ам. Т.е. не reducer определяет структуру хранилища. Он только её придерживается.


И вот вы переписываете все эти раскиданные по коду mapStateToProps.

Понимаете, если вы называете любой метод, цель которого — прочитать какие-то поля из store, селектором, то… Все до единого ваши mstp это селекторы. И вот уже внутри них вы подключаете "под-селекторы", а в них "под-подселекторы" и т.д… Сама природа mapStateToProps — быть селектором данных.


То, что неудобно писать копипасту, и вообще удобно дробить однотипную функциональность — это очевидно. Это не нужно придумывать. Это просто DRY. Если вам угодно называть эти подметоды селекторами — да не вопрос. Ключевое в том, что их придумывать было не нужно, это из разряда 2+2 :)


Суть же reselect-а (именно это библиотеки) как раз в мемоизации. Это кеширующая функция, основная цель которой служить именно кеш-селектором (хотя используют не только для этого, но ещё и для кеширования вычислений на основе выбранных данных). Вот это уже можно сказать "придумали", когда стало ясно, что тут у нас бутылочное горлышко производительности.

Вы можете поменять reducer без ущерба для приложения, оставив схему store той же

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

Ведь вы даже поля в store называете именем reducer-а, ответственного за это поле.

О господи. Да я сделал это просто для обозначения того уровня вложенности, где у нас задан редюсер, ни для чего более.

В общем суть проста — есть схема данных в store. А есть reducer, который, придерживаясь этой схемы, правит данные по action-ам

Отлично, замечательно! Суть-то проблемы от этого не меняется: как только вы меняете структуру данных в сторе, все элементы которые явно завязались на эту структуру требуется переписать.

Понимаете, если вы называете любой метод, цель которого — прочитать какие-то поля из store, селектором, то… Все до единого ваши mstp это селекторы.

Да, конечно. Так и есть (селектор — от слова select, ваш Капитан). С той лишь разницей, что они определены не в файле с редьюсером, а в другом файле.

То, что неудобно писать копипасту, и вообще удобно дробить однотипную функциональность — это очевидно. Это не нужно придумывать.

Но ведь «придумали же», даже имя дали, определили, куда поместить, всё в этом духе)

В этом я и вижу комичность ситуации: сначала придумали себе проблему, потом героически пытаются её решить :-)

Но ведь «придумали же», даже имя дали, определили, куда поместить, всё в этом духе)

ну тогда придумали это, наверное, ещё в 60-х годах прошлого века.


сначала придумали себе проблему, потом героически пытаются её решить

Я выше пытался объяснить что никакой проблемы нет, никаких героических попыток её решения тоже нет, это ведь просто DRY. Do-not-repeat-yourself. самый обыкновенный DRY. Странно что это вообще вызывает у вас какие-то эмоции.

Да весь редакс — это чистой воды Repeat yourself, а надстройки — попытка избавиться от давно решённых проблем, от того это и вызывает эмоции, особенно пассажи типа «MVC — ну такое там не понятно с ajax и тестированием, а вот приложения в сочетании с Flux-архитектурой получаются мощные»
Да весь редакс — это чистой воды Repeat yourself

а вот это прямо в точку :)

Давайте рассмотрим Flux поподробнее. Идея тут вот в чем. У нас есть Store, и этот Store — хранилище данных, это единственный источник истины нашего приложения. Все остальное неправда.


И конечно неправда, что у нас есть ещё внутренний стейт компонент, ход анимаций, промежуточные значения инпутов, и скроллов, которые не выносятся туда из соображений производительности. Но это же неправда

И самая весёлая часть ― адресная строка ;) Сколько эти SPA существуют, столько идут холивары по тому как должен работать router.

Only those users with full accounts are able to leave comments. Log in, please.

Information

Founded
Location
Россия
Website
www.yandex.ru
Employees
over 10,000 employees
Registered

Habr blog