Чи може законно мати клас RxJava Flowable законно 460 методів?


14

Я тільки починаю роботу з RxJava , реалізацією Java ReactiveX (також відомим як Rx і Reactive Extensions ). Те , що дійсно вразило мене масовий розмір RxJava в текучий класі : він має 460 методи!

Справедливості:

  • Існує маса перевантажених методів, що значно зменшує загальну кількість методів.

  • Можливо, цей клас слід розбити, але мої знання та розуміння RxJava дуже обмежені. Люди, які створили RxJava, безумовно, дуже розумні, і вони, імовірно, можуть запропонувати вагомі аргументи для вибору створити Flowable з такою кількістю методів.

З іншої сторони:

  • RxJava - це реалізація Java на реактивних розширеннях Microsoft , яка навіть не має класу Flowable , тому це не випадок сліпого перенесення існуючого класу та впровадження його в Java.

  • [ Оновлення: Попередній пункт у курсиві фактично невірний: клас спостереження Microsoft , який налічує понад 400 методів, був використаний як основа для класу спостереження RxJava , і Flowable схожий на спостерігається, але обробляє зворотний тиск для великих обсягів даних. Таким чином, команда RxJava були портирование існуючого класу. Цей пост повинен був оскаржити оригінальний дизайн спостережуваного класу по Microsoft , а не RxJava в текучому класі.]

  • RxJava лише трохи більше 3-х років, тому це не приклад неправильного проектування коду через відсутність знань про хороші принципи дизайну класів ( SOLID ) (як це було у ранніх версіях Java).

Для класу, великого як Flowable його дизайн здається неправильним, але, можливо, ні; одна відповідь на це питання SE Що обмежує кількість методів класу? запропонував відповідь " Майте стільки методів, скільки вам потрібно ".

Зрозуміло, що є деякі класи, які легітимно потребують достатньої кількості методів для їх підтримки незалежно від мови, оскільки вони не легко розбиваються на щось менше і мають неабияку кількість характеристик та ознак. Наприклад: рядки, кольори, комірки електронних таблиць, набори результатів бази даних та HTTP-запити. Маючи, можливо, кілька десятків методів для занять для представлення цих речей, не здається безпідставним.

Але робить потрібні Flowable справді 460 методів, чи він настільки величезний, що це обов'язково зразок поганого дизайну класу?

[Щоб бути зрозумілим: це питання стосується конкретно класу Flowable RxJava, а не предметів Бога взагалі.]



1
@gnat Ну, звичайно, пов'язано, але це не дублікат. Це питання було загальним, і моє запитання спеціально стосується класу Flowable RxJava .
skomisa

@skomisa Потім виправте заголовок, щоб відповідати вашому питанню.
Ейфорія

@Euphoric Point прийнято.
скоміса

1
Це питання дуже цікаве та обґрунтоване. Однак я б запропонував переробити це трохи, щоб прийняти менш суб’єктивний стиль (можливо, через початковий шок ;-))
Крістоф

Відповіді:


14

TL; DL

Відсутність мовних особливостей Java в порівнянні з C #, а також міркування щодо виявлення змусили нас поставити вихідні та проміжні оператори у великі класи.

Дизайн

Оригінальний Rx.NET був розроблений в C # 3.0, який має дві найважливіші особливості: методи розширення та часткові класи. Перший дозволяє визначати методи екземплярів для інших типів, які потім є частиною цього цільового типу, тоді як часткові класи дозволяють розділити великі класи на кілька файлів.

Жодна з цих функцій не була або не присутня на Java, тому нам довелося знайти спосіб зробити RxJava зручним для використання.

У RxJava є два види операторів: джерелоподібний, представлений статичними фабричними методами, і проміжний, представлений методами екземплярів. Перші могли жити в будь-якому класі, і тому їх можна було розподілити по декількох класах корисності. Останнє вимагає, щоб над ним працював екземпляр. В принципі, все це може бути виражено статичними методами, в якості першого параметра - вгору.

На практиці, однак, наявність декількох початкових класів робить відкриття нових функцій новими користувачами незручним (пам'ятайте, RxJava повинен був запровадити нову концепцію та парадигму програмування в Java), а також використання цих проміжних операторів дещо кошмаром. Тому оригінальна команда придумала так званий текучий дизайн API: один клас, який містить всі статичні методи та методи екземпляра і представляє джерело або етап обробки сам по собі.

Через першокласний характер помилок, підтримку одночасності та функціональний характер можна створити всілякі джерела та перетворення щодо реактивного потоку. По мірі того, як бібліотека (і концепція) розвивалася з часів Rx.NET, додавались все більше стандартних операторів, що від природи збільшувало кількість методів. Це призводить до двох звичайних скарг:

  • Чому існує так багато методів?
  • Чому не існує методу X, який вирішує мою дуже конкретну проблему?

Написання реактивних операторів - важке завдання, яке не багато людей опановували роками; Більшість типових користувачів бібліотеки не можуть створити операторів самостійно (і часто це не дуже важливо для них). Це означає, що ми час від часу додаємо до стандартного набору ще операторів. На відміну від цього, ми відхилили набагато більше операторів через занадто специфіку чи просто зручність, яка не може натягнути власну вагу.

Я б сказав, що дизайн RxJava виріс органічно і не дуже, відповідно до певних принципів дизайну, таких як SOLID. Він здебільшого керується використанням та відчуттям його вільного API.

Інші відносини з Rx.NET

Я приєднався до розробки RxJava в кінці 2013 року. Наскільки я можу сказати, початкові версії 0.x значною мірою були реалізацією чорного поля, де імена та підписи Observableоператорів Rx.NET , а також декілька архітектурних рішень були повторно використані. У цьому було залучено близько 20% операторів Rx.NET. Головною проблемою тоді було вирішення мовних та платформних відмінностей між C # та Java. Доклавши великих зусиль, нам вдалося реалізувати багато операторів, не дивлячись на вихідний код Rx.NET, і ми перенесли більш складні.

У цьому сенсі, до RxJava 0,19, наші Observableбули еквівалентними методам розширення Rx.NET IObservableта супутнього 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.NET Observable. Внутрішньо, всі реактивні типи вводять ручку для скасування своїм споживачам, що дозволяє ефективно синхронізувати скасування.


10

Хоча я визнаю, що я не знайомий з бібліотекою, я поглянув на розглянутий клас Flowable, і, здається, він діє як би сорт . Іншими словами, це клас, призначений для валідації введення та відповідно розподілу викликів у проекті.

Тому цей клас насправді не вважатиметься об'єктом Бога, оскільки об'єктом Бога є все, що намагається зробити все. Це робить дуже мало з точки зору логіки. Що стосується одноосібної відповідальності, єдиним завданням класу можна вважати делегування роботи по всій бібліотеці.

Тож, природно, такий клас потребує методу для кожного можливого завдання, якого ви потребуєте від Flowableкласу в цьому контексті. Ви бачите один і той же тип шаблону з бібліотекою jQuery у javascript, де змінна $має всі функції та змінні, необхідні для виконання дзвінків по бібліотеці, хоча у випадку jQuery код не просто делегується, а й має добру логіку виконується всередині.

Я думаю, вам слід бути обережними, щоб зробити такий клас, але він має своє місце до тих пір, поки розробник пам’ятає, що це лише хаб, і тому не повільно перетворюється на об’єкт бога.


2
Вибачте за те, що ви прийняли вашу відповідь, яка була і корисною, і освічуючою, але наступна відповідь akarnokd була від когось із команди RxJava!
скоміса

@skomisa Я міг би сподіватися ні на що більше, якби це було моє власне питання! Жодного правопорушення не брали! :)
Ніл

7

Що еквівалентно .NET в RX в Flowableце Observable . У ньому також є всі ці методи, але вони є статичними і використовуються як методи розширення . Основним моментом RX є те, що композиція написана за допомогою вільного інтерфейсу .

Але для того, щоб Java мав вільний інтерфейс, потрібні такі методи, щоб вони були методами екземплярів, оскільки статичні методи не могли б складатись добре, і у неї немає методів розширення, щоб статичні методи були компонованими. Тож на практиці всі ці методи можуть бути зроблені статичними методами, якщо ви добре не використовуєте синтаксис вільного інтерфейсу.


3
Концепція вільного інтерфейсу, IMHO, є вирішенням мовних обмежень. Ефективно, ви будуєте мову за допомогою класу поверх Java. Якщо ви думаєте про те, скільки функцій має навіть проста мова програмування, і не враховуєте всі перевантажені варіанти, вам стає досить просто зрозуміти, як ви закінчитеся з цією кількістю методів. Функціональні особливості Java 8 можуть вирішити багато питань, що призводять до такого дизайну, і сучасні мови, такі як Kotlin, рухаються, щоб отримати можливість отримати такі ж переваги, не потребуючи прив'язки методів.
JimmyJames

Завдяки вашому допису я заглибився, і, здається, що .NET RX's Observable є ≈ до RxJava's Observable, тому передумова мого запитання була невірною. Я відповідно оновив ОП. Крім того, RxJava's Flowable ≈ (спостерігається + кілька додаткових методів для паралелізації та обробки зворотного тиску).
skomisa

@skomisa Java також має сотні методів. Тож можна порівняти два. Але головна відмінність полягає в тому, що .NET's Observable є статичним, а всі методи - статичними. Хоча Java - ні. І це величезна різниця. Але на практиці вони поводяться так само.
Ейфорія
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.