Я только начинаю с RxJava , Java-реализации ReactiveX (также известной как Rx и Reactive Extensions ). То , что действительно поразило меня массовый размер RxJava в текучий классе : он имеет 460 методы!
По честному:
Есть много методов, которые перегружены, что значительно увеличивает общее количество методов.
Возможно, этот класс следует разбить, но мои знания и понимание RxJava очень ограничены. Люди, которые создали RxJava, безусловно, очень умны, и они, вероятно, могут предложить веские аргументы для выбора создания Flowable с таким количеством методов.
С другой стороны:
RxJava - это Java-реализация Microsoft Reactive Extensions , которая даже не имеет класса Flowable , так что это не случай слепой портирования существующего класса и его реализации в Java.
[ Обновление: предыдущий пункт в курсиве фактически неверен: класс Observable от Microsoft , который имеет более 400 методов, использовался в качестве основы для класса Observable в RxJava , а Flowable аналогичен Observable, но обрабатывает противодавление для больших объемов данных. Таким образом, команда RxJava были портирование существующего класса. Этот пост должен был оспорить оригинальный дизайн наблюдаемого класса по Microsoft , а не RxJava в текучем классе.]
RxJava всего немногим более 3 лет, так что это не пример неправильного проектирования кода из-за недостатка знаний о хороших ( SOLID ) принципах проектирования классов (как это было в ранних выпусках Java).
Для такого большого класса, как Flowable, его дизайн кажется неправильным, но, возможно, нет; один ответ на этот вопрос SE Каково ограничение на количество методов класса? предположил, что ответ « есть столько методов, сколько вам нужно ».
Очевидно, что есть некоторые классы, которым на законных основаниях требуется достаточное количество методов для их поддержки независимо от языка, потому что они не разбиваются на что-то меньшее и имеют достаточное количество характеристик и атрибутов. Например: строки, цвета, ячейки электронной таблицы, наборы результатов базы данных и HTTP-запросы. Возможно, наличие нескольких десятков методов для классов, представляющих эти вещи, не кажется необоснованным.
Но действительно ли Flowable нужны 460 методов, или он настолько велик, что обязательно является примером плохого дизайна класса?
[Чтобы быть ясно: этот вопрос конкретно относится к RxJava в текучий класса , а не объекты Бога вообще.]
источник
Ответы:
TL; DL
Отсутствие языковых возможностей Java по сравнению с C #, а также соображения об открываемости заставили нас поместить исходные и промежуточные операторы в большие классы.
дизайн
Оригинальный Rx.NET был разработан в C # 3.0, который имеет две важные функции: методы расширения и частичные классы. Первый позволяет вам определять методы экземпляра для других типов, которые затем становятся частью этого целевого типа, тогда как частичные классы позволяют разбивать большие классы на несколько файлов.
Ни одна из этих функций не была и не присутствует в Java, поэтому нам пришлось искать способ сделать RxJava удобным для использования.
В RxJava есть два вида операторов: исходные, представленные статическими фабричными методами, и промежуточные, представленные экземплярами. Первые могут жить в любом классе, и, таким образом, они могут быть распределены по нескольким служебным классам. Последний требует, чтобы экземпляр работал. По идее, все это можно выразить статическими методами с восходящим потоком в качестве первого параметра.
На практике, однако, наличие нескольких классов входа делает обнаружение новых пользователей неудобным (помните, что RxJava должен был привнести новую концепцию и парадигму программирования в Java), а также использование этих промежуточных операторов в некотором смысле кошмар. Поэтому первоначальная команда разработала так называемый плавный дизайн API: один класс, который содержит все методы static и instance и представляет собой источник или этап обработки самостоятельно.
Из-за первоклассной природы ошибок, поддержки параллелизма и функциональной природы, можно придумать всевозможные источники и преобразования относительно реактивного потока. По мере развития библиотеки (и концепции) со времен Rx.NET все больше и больше стандартных операторов добавлялись, что по своей природе увеличивало количество методов. Это приводит к двум обычным жалобам:
Написание реактивных операторов - трудная задача, с которой не справились многие люди; большинство типичных пользователей библиотеки не могут сами создавать операторы (и зачастую им не обязательно пытаться это делать). Это означает, что мы время от времени добавляем дополнительные операторы в стандартный набор. Напротив, мы отказались от многих других операторов из-за того, что они слишком специфичны или просто из-за удобства, которое не может тянуть свой вес.
Я бы сказал, что дизайн RxJava развивался органически, а не в соответствии с определенными принципами проектирования, такими как SOLID. Это главным образом обусловлено использованием и ощущением его свободного API.
Другие отношения к Rx.NET
Я присоединился к разработке RxJava в конце 2013 года. Насколько я могу судить, начальные ранние версии 0.x были в основном переопределением черного ящика, в котором имена и подписи
Observable
операторов Rx.NET, а также несколько архитектурных решений использовались повторно. В этом участвовало около 20% операторов Rx.NET. Тогда главной трудностью было разрешение языковых и платформенных различий между C # и Java. С огромными усилиями нам удалось реализовать множество операторов, не глядя на исходный код Rx.NET, и мы портировали более сложные.В этом смысле, вплоть до RxJava 0.19, наш
Observable
был эквивалентен Rx.NETIObservable
и его сопутствующимObservable
методам расширения. Однако появилась так называемая проблема противодавления, и RxJava 0.20 начал расходиться с Rx.NET на уровне протокола и архитектуры. Доступные операторы были расширены, многие стали реагировать на противодавление, и мы ввели новые типы:Single
иCompletable
в эпоху 1.x, у которых на данный момент нет аналогов в Rx.NET.Осознание противодавления значительно усложняет ситуацию, и 1.x
Observable
получает это в качестве запоздалой мысли. Мы поклялись в верности двоичной совместимости, поэтому изменение протокола и API в большинстве случаев было невозможно.Была еще одна проблема с архитектурой Rx.NET: синхронная отмена невозможна, потому что для этого нужно
Disposable
вернуть ее, прежде чем оператор начнет выполнение. Тем не менее, источники, которыеRange
были готовы и не возвращаются, пока они не закончат. Эта проблема может быть решена путем введенияDisposable
вObserver
вместо возвращения одного изsubscribe()
.RxJava 2.x был переработан и реализован с нуля по этим направлениям. У нас есть отдельный тип с поддержкой обратного давления,
Flowable
который предлагает тот же набор операторов, что иObservable
.Observable
не поддерживает противодавление и в некоторой степени эквивалентно Rx.NETObservable
. Внутренне все реактивные типы вводят свой дескриптор отмены своим потребителям, что позволяет эффективно работать синхронному аннулированию.источник
Хотя я признаю, что не знаком с библиотекой, я взглянул на рассматриваемый класс Flowable, и кажется, что он действует как своего рода центр. Другими словами, это класс, предназначенный для проверки ввода и соответствующего распределения вызовов в проекте.
Следовательно, этот класс на самом деле не будет рассматриваться как объект Бога, так как объект Бога пытается сделать все. Это очень мало с точки зрения логики. С точки зрения единоличной ответственности, можно сказать, что единственной работой класса является делегирование работы по всей библиотеке.
Поэтому, естественно, что для такого класса потребуется метод для каждой возможной задачи, которую вам потребуется от
Flowable
класса в этом контексте. Вы видите тот же тип шаблона с библиотекой jQuery в javascript, где переменная$
имеет все функции и переменные, необходимые для выполнения вызовов библиотеки, хотя в случае с jQuery код не просто делегируется, но и обладает хорошей логикой работает внутри.Я думаю, что вы должны быть осторожны, чтобы создать такой класс, но он имеет свое место, пока разработчик помнит, что это всего лишь концентратор, и, следовательно, не медленно превращается в объект бога.
источник
Эквивалент RX для .NET
Flowable
- Observable . В нем также есть все эти методы, но они являются статическими и могут использоваться как методы расширения . Суть RX в том, что композиция написана с использованием свободного интерфейса .Но для того, чтобы у Java был свободный интерфейс, эти методы должны быть методами экземпляра, так как статические методы не могли бы хорошо сочиняться, и у них нет методов расширения, чтобы сделать статические методы компонуемыми. Таким образом, на практике все эти методы могут быть сделаны статическими, если у вас все в порядке, не используя свободный синтаксис интерфейса.
источник