За что я не люблю Redux

?v=1

Тема, конечно, не нова, и немало на этот счет уже сказано и написано. Но все же поделюсь и своим взглядом на этот счет, т.к. мое осознание данного факта формировалось скорее независимо и на основании собственного опыта, ценностей и взглядов, и возможно (надеюсь) в нем читатель найдет для себя что-то свежее или полезное.

Flux — это вовсе не что-то новое либо революционное

Не то, чтобы я не люблю его за это. Скорее, в этом даже нет ничего плохого — если решение хорошее и проверенное временем, разве это плохо? Скорее мне просто удивительно слышать, как подход, реализованный в Flux в целом (и в Redux в частности) некоторые пытаются выдавать за что-то инновационное и революционное. Да и само решение, на мой взгляд, как минимум не лишено недостатков. Но об этом далее, а пока вспомню молодость.

В начале нулевых я разрабатывал ПО и библиотеки компонент на Delphi под Windows (сначала Win9x, потом XP). В операционных системах Windows с самых первых, если не ошибаюсь, версий, для визуальных элементов интерфейса (кнопки, поля ввода) существует понятие окна — да, окно это не только то, что с рамкой, почти любой визуальный элемент управления имел свое собственное окно. Окно в данном случае — это некая структура в памяти, которая имеет ассоциированный с ним идентификатор (window handle) и оконную функцию (см. далее). Если мы хотим выполнить какое-либо действие над элементом, например — изменить текст кнопки, мы должны упаковать это действие в специальную структуру-сообщение (Window message) и отправить ее соответствующему окну. Структура состоит из закодированного типа сообщения (например WM_SETTEXT — для установки текста) и собственно payload. Будучи отправленным, сообщение не попадает в обработчик напрямую — вместо этого оно отправится в очередь, из которой его извлекает некий диспетчер и вызывает оконную функцию того окна, в которое мы сообщение отправили, передав его в виде параметра. Оконная функция в простейшем случае — это большой switch, где в зависимости от типа сообщения мы передаем управление более конкретному обработчику. Ничего не напоминает?

Те времена давно прошли и больших сожалений на этот счет нет. Более широкое использование ООП со временем значительно улучшило качество кода по сравнению с чистым WinAPI с его сообщениями и оконными функциями. И сегодня, наблюдая код с использованием Redux, определенное чувство дежавю возникает.

Нарушение принципа «Low coupling, high cohesion»

Если вы ищите простую и понятную формулировку, что такое качественный дизайн, то эти четыре слова из подзаголовка коротко и емко его описывают — внутри модуля или компонента его элементы должны быть тесно связанны друг с другом, в то время как связи между отдельными модулями/компонентами должны быть слабыми. Это базовая ценность. Все остальные принципы и подходы в проектировании — следствия из этого принципа. «Low coupling, high cohesion» отвечает на вопрос »чего мы хотим добиться», в то время как, скажем, SOLID-принципы или любой из Design Pattern указывает нам »как мы можем этого добиться».

И вот тут Redux подводит — то, что должно быть цельным внутри компонента, оказывается размазанным по множеству файлов и сущностей — получаем Low cohesion вместо High. Связи, которые должны оставаться внутри, выходят наружу. Если нарушение принципа Low Coupling обычно представляют себе в виде переплетений из лапши, то здесь у меня в голове всплывает другое кулинарное блюдо. Позаимствовав терминологию у Java-разработчиков, если отдельный компонент — это фасолинка (Bean) — цельная, замкнутая вещь в себе, то тут мы получаем что-то вроде рагу, где фасоль полопалась и его содержимое вытекло, образовав густую однородную кашу, обволакивающую всю систему целиком, и не позволяющую на нее смотреть как на композицию отдельных законченных и слабо-зависимых сущностей.

Множество Boilerplate кода

Ну и нельзя не упомянуть то, за что Redux не ругал разве что ленивый. Мало того, что даже небольшое изменение функционала может потребовать относительно большие изменения в коде, так еще и код этот однотипный и не несущий никакой полезной для данной конкретной задачи нагрузки. По идее однотипный подход и код, над которым не надо думать, должен ускорять разработку, но лично меня это скорее утомляет, а эффект получается прямо противоположным. И да, инструменты, направленные на решение этой проблемы, существуют, но как по мне — не решают ее полностью.

Неуместное использование

А еще мне не нравится, что Redux или схожие с ним инструменты пытаются использовать там, где они не нужны — скажем, в Angular (angular-redux, NgRx). Redux предназначен для решения проблемы передачи данных в компоненты путем использования глобального State, и в React.js действительно существует такая проблема, там его использование кажется уместным. Но в Angular такой проблемы нет, Injectable-сервисы прекрасно справляются с этой задачей. Зачем решать несуществующую проблему, порождая при этом новые (о которых было написано выше)?

Ну и если говорить о неуместном использовании, также неуместным кажется использования Redux для управления локальным стейтом, что встречается довольно часто.

В заключение надо бы отметить и что-нибудь хорошее. Допустим, это не так плохо, когда у вас большая команда разработчиков разного уровня, и все пишут понятный всем код примерно в одном стиле ничего не выдумывая. Если иначе такая разношерстная команда не сможет работать эффективно, значит овчинка выделки определенно стоит. Но на самом деле хотелось бы иметь простое и эффективное решение, лишенное вышеназванных недостатков. Context API? Может быть.

© Habrahabr.ru