Как стать автором
Обновить

Комментарии 15

list ... Было/Стало

Спорное улучшение. Вместо отчетливо видимой "UI как функции от стейта", получили какой-то конфиг, без существенной экономии кода. И это в самом базовом варианте.

Вместо отчетливо видимой

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

без существенной экономии кода. И это в самом базовом варианте.

В том то и дело, что в базом варианте экономии и не видно (для меня это не только про экономие, но и про удобство - это из рязряда нужно брать и пробовать), чем больше компонент, чем больше у него состояний, тем больше наша "экономия", + в статье писал про обертку

export const statusesList = ({ effect, source }: Store<ListState>) => {
  return combine(status({effect}), source, (effectStatus, list) =>
    effectStatus === 'done'
      ? Object.values(list).length
        ? 'done'
        : 'empty'
      : effectStatus,
  );
}
....

export const $someStoreStatus = statusesList({
  effect: someEffect,
  source: $someStore,
});

Здесь мы можем обработать базовые исходы все, и теперь, когда в "Было" мы будем каждый компонент обмусоливать, в "Стало" вызовем list и передадим базовые кейсы, вызвав statusesList. (к слову, подобное можно реализовать в любом инструменте, дело в поддержке всего этого написанного)



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

Давайте перейдем к первому этапу - воспользуемся reflect.

Реакт постоянно тянет вывернуться на изнанку и обернуться в мир фантазий с элементами функционального программирования. Но его все равно оттуда достают. Помните HOC, mapStateToProps, а потом нет - хуки?

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

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

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

Человек, удалив зависимости, в виде материал ui и других, почистив код и приведя его к низкому уровню, пытается выставить mol (оперируя фактами кол-ва строк кода и объема зивисимостей), зачем - вопрос. Хотя статья - туториал, и никаких сравнений здесь не должно быть)

приведя его к низкому уровню

Наоборот, к высокому. Вьюшки и модели представлены самодостаточными классами, а не лапшой из глобальных переменных. Не стоит благодарности.

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

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

Добавил туда и тесты.

Чистенько :) Только один вопрос. В приложении компоненты используется декларативно:

<NotesList
  id='notes'
  notes={ ()=> this.notes() }
/>

а в тесте создаются императивно и без таких вот пропертей:

const view = new NotesList

view.notes().make( 'foo' )
view.notes().make( 'bar' )

const dom = view.render()

Уверен, что связь там наверняка тривиальная. Но все равно не покидает ощущение, что тест тестит что-то другое. Можете добавить пример теста с jsx (или объяснить почему так делать не стоит если у вас другое мнение)?

JSX тут на выходе даёт настоящий DOM, а не виртуальный. Из него, конечно, можно получить экземпляр компонента, но зачем, если его можно сразу и создать. К тому же рендеринг зачастую и не нужен - достаточно дёргать апи компонента.

Ну а к декларативности JSX не имеет никакого отношения.

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

Что бы там ни говорили адепты 

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

Ваши трактовки отличаются от классических. Я не говорю, что вы не правы, просто непривычно.

Обычно говорят о трёх категориях моделей вычисления: https://en.m.wikipedia.org/wiki/Model_of_computation - последовательные, функциональные и конкурентные. Они используются при анализе алгоритмов и дают инсайты разработчикам языков программирования.

Языки программирования задают грамматику/синтаксис и модель исполнения https://en.m.wikipedia.org/wiki/Execution_model. Условно, это то, что представляет себе разработчик, читая программу - как она будет исполняться.

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

Декларативное программирование https://en.m.wikipedia.org/wiki/Declarative_programming это стиль, когда конструкции в программе выражают чисто логику вычисления (фактически что было в исходном алгоритме), без описания потока исполнения (т.е. как посчитать).

Например, если мы говорим, что "в списке есть элемент foo и элемент bar", то декларативной можно трактовать запись:

<NotesList>
  <Node>foo</Node>
  <Node>bar</Node>
</NodeList>

Если алгоритм был бы задан иначе: "в пустой список добавили элемент foo, а потом - bar" - тогда декларативной будет вот такая запись:

const notesList = new NotesList

notesList.make( 'foo' )
notesList.make( 'bar' )

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

За пределами алгоритма, ни какой другой семантики декларативный стиль не рассматривает. Все остальные интерпретации это уже область наших оценочных суждений, а не программирование.

Моделей вычислений, которые относят к ФП несколько. У большинства ноги растут из математики. В популярной lambda calculus программа составляется как композиция функций (f.g) и так далее. Данные здесь вещь вторичная, как вам неважно при записи математикой формы X там или Y. Есть даже point-free style, где сам агрумент функции ни разу упоминается. Вычислять все это можно, например, как редукцию функции (упрощение, переписыванием из одной формы в другую, как на уроках матана).

В JS мы в самом деле вынуждены использовать императивые конструкции когда пишем в стиле ФП. Но это вынужденное отклонение от декларативности, из-за ограничений модели вычисления в этом языке, а не свойство исходной модели вычисления. В том же Haskell картинка ровно наоборот - ФП как родной, а императивность и энергичность приходится костылить.

Вы говорите не про декларативность, а про идиоматичность.

Что примечательно - каждый под декларативностью понимает что-то своё. Это верный признак нечёткого определения. А википедия только ещё больше всех запутывает. Английская явно написана "функциональщиками, которые очень хотят называться декларативщиками". Русская в этом плане менее подвержена набегам сектантов: https://ru.m.wikipedia.org/wiki/Декларативное_программирование

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

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

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории