Комментарии 9
С ELM не знаком, но по описанию он похож на другую популярную архитектуру в вебе, которая появилась позже.
Я написал статью из двух частей, в которой указываю ее проблемные моменты (это редьюсеры и использование событий там, где нет необходимости):
habr.com/ru/post/546606
habr.com/ru/post/546628
Основное отличие стора/сторов у меня в том, что там нет редьюсеров и событий.
Нет необходимости создавать функцию-редьюсер, в которой реализуется функционал нескольких функций. Вместо одной большой функции с 3-мя Event, лучше сделать 3 отдельных функции. Имя события тогда не понадобится.
У функции уже есть имя, зачем ей передавать лишнюю информацию (имя события) о том, что именно эту функцию нужно вызвать? Это конечно в некоторых ситуациях может быть полезно (чтобы уменьшить зависимость; для тестов), но пригодится далеко не во всех проектах. Да и вызвать функцию и передать ей параметры можно по имени, указав его как строку (но это в JavaScript. Как в других языках – не знаю), не заводя событий.
То есть чистые функции – это хорошо. А вот объединение функционала нескольких функций в одну (редьюсер) – это уже архитектурная ошибка, если этого можно избежать. Подробнее про редьюсеры написано в первой части моей статьи.
Но, это применимо к вебу. Не знаю, насколько это применимо к мобильной разработке.
Спасибо за статьи. Возможно эти идеи можно переложить на android, сложно сказать сразу. В андроид мире по-другому устроена работа с View, но возможно это изменится с приходом jetpack compose. Так же есть разница в языках. Например, проблема нарушения принципа Liskov решается в kotlin с помощью sealed classes, которые позволяют проверять добавление новых типов на этапе компиляции. Вызывать функцию по имени тоже проблематично — kotlin статически типизированный язык.
Так же есть некоторые различия в архитектуре, одним разбением редюсера на функии не получится ограничиться. В вашем примере событие saveTodo не является чистой фукнцией. У нее есть явная зависимость на todoController и получается, что ее запуск имеет побочные эффекты. Например это усложнит ее тестирование, поскольку придется работать с зависимостями. У нас Reducer — полностью чистая функция и не имеет такой проблемы.
Да, я о Redux.
Вызывать функцию по имени тоже проблематично — kotlin статически типизированный язык.
Конечно, язык и стек в целом играет большую роль. Не знаю, есть ли в kotlin рефлексия, но хоть словари должны быть, чтобы динамически вызывать функции, обращаясь по строковому имени/ключу. Но это не понадобится, если не пишется какой-то универсальный код или нет необходимости в событиях. В моем примере контроллера методы обновления стора вызываются напрямую: store.someAction();
В вашем примере событие saveTodo не является чистой функцией.
Ну, это уже side effect во view и к сторам не относиться. Аналоги редьюсеров находятся здесь:
например, setEditState. Сторонние зависимости и сайд-эффекты в нем отсутствуют.
В идеале логику не стоит писать в самих компонентах и код оттуда стоит выносить. Но в вебе не часто бывают достаточно большие и сложные проекты, где это дало бы существенные преимущества. Ну и в вебе так сложилось, что обычно логика компонента объединена с его разметкой.
Redux тоже со временем пришел к разделению редьюссеров на отдельные методы в объекте: https://redux-toolkit.js.org/api/createSlice
А почему вы используете RxЖабу, а не корутины?(
Разбираем ELM архитектуру в рамках мобильного приложения