RxJavaクラスFlowableは、正当に460個のメソッドを持つことができますか?


14

JavaのReactiveXRxおよびReactive Extensionsとも呼ばれます)の実装であるRxJavaを始めたばかりです。本当に私を襲った何かがの巨大な大きさだったRxJavaのフロアブルクラス:それは460個のメソッドを持っています!

公平であるために:

  • オーバーロードされたメソッドが多数あり、メソッドの総数が大幅に増えます。

  • おそらくこのクラスは分割されるべきですが、RxJavaに関する私の知識と理解は非常に限られています。RxJavaを作成した人々は確かに非常にスマートであり、それらは作成するために選択するための有効な引数を、おそらくを提供することができますフロアブル剤を非常に多くの方法で。

一方:

  • RxJavaはのJava実装であるMicrosoftの反応性の拡張機能、およびそれがさえ持っていないフロアブルクラスを、ので、これは盲目的に既存のクラスを移植し、Javaでそれを実施する場合ではありません。

  • [ 更新:イタリック体の前のポイントは事実正しくありません。マイクロソフトの観察可能な 400以上のメソッドを持つクラスは、RxJavaのための基礎として使用された観察可能なクラス、および流動性は、に似て観察可能な大量のデータのためではなく、ハンドル背圧。そのため、RxJavaチーム既存のクラス移植していました。この投稿は、元のデザインに挑戦されている必要があり、観察可能マイクロソフトによってクラスではなく、RxJavaのフロアブルクラスを。]

  • RxJavaはわずか3年以上前であるため、これは(Javaの初期リリースの場合のように)優れた(SOLID)クラス設計原則に関する知識が不足しているためにコードが誤って設計されている例ではありません。

Flowableほどの大きさのクラスでは、その設計は本質的に間違っているように見えますが、そうではないかもしれません。このSEの質問に対する1つの答えクラスメソッドの数の制限は何ですか?答えは「必要な数のメソッドを用意する」ことです。

明らかに、言語に関係なくそれらをサポートするためにかなりの数のメソッドを必要とするクラスがいくつかあります。それらは簡単に小さなものに分解されず、かなりの数の特性と属性を持っているからです。例:文字列、色、スプレッドシートセル、データベース結果セット、HTTPリクエスト。これらのことを表現するためのクラス用のメソッドをおそらく数十個用意することは、理不尽に思えません。

しかし、Flowableには460個のメソッドが本当に必要なのでしょうか、それとも非常に巨大なために、必ずしもクラスの設計が悪い例ですか?

[明確にするには:この質問は、具体的RxJavaのに関し、フロアブルクラスではなく、神は、一般的にオブジェクト。]



1
@gnat確かに関連していますが、重複しているわけではありません。その質問は、一般的なだった、と私の質問は、具体的RxJavaのに関係フロアブルクラス。
-skomisa

@skomisa次に、質問に合わせてタイトルを修正します。
陶酔

@Euphoricポイントを取得しました。
skomisa

1
この質問は非常に興味深いものです。ただし、主観的ではないスタイルを採用するために、それを少し言い換えることをお勧めします(おそらく最初のショックによるものです;
クリストフ

回答:


14

TL; DL

C#と比較したJavaの言語機能の欠如、および発見可能性の考慮事項により、ソースおよび中間演算子を大きなクラスに配置しました。

設計

元のRx.NETはC#3.0で開発され、拡張メソッドと部分クラスという2つの重要な機能があります。前者では、他のタイプのインスタンスメソッドを定義して、そのターゲットタイプの一部のように見えるのに対して、部分クラスでは大きなクラスを複数のファイルに分割できます。

これらの機能はどちらもJavaには存在しなかったため、RxJavaを十分便利に使用できる方法を見つける必要がありました。

RxJavaには2種類の演算子があります。静的ファクトリメソッドで表されるソースのようなものと、インスタンスメソッドで表される中間のようなものです。前者はどのクラスにも住むことができるため、複数のユーティリティクラスに沿って配布できます。後者では、インスタンスを処理する必要があります。概念的には、これらはすべて、アップストリームを最初のパラメーターとする静的メソッドで表現できます。

ただし、実際には、複数のエントリクラスがあると、新しいユーザーによる機能の検出が不便になります(RxJavaが新しい概念とプログラミングパラダイムをJavaに持ち込む必要があったことを思い出してください)。そのため、元のチームは、いわゆる流なAPIデザインを考え出しました。すべての静的メソッドとインスタンスメソッドを保持し、ソースまたは処理段階をすべて単独で表す1つのクラスです。

エラーの第一級の性質、並行性のサポート、および機能の性質により、リアクティブフローに関するあらゆる種類のソースと変換を思い付くことができます。ライブラリ(および概念)がRx.NETの時代から進化するにつれて、ますます多くの標準演算子が追加され、メソッドの数が本質的に増加しました。これは、2つの通常の不満につながります。

  • なぜそんなに多くの方法があるのですか?
  • 特定の問題を解決するメソッドXがないのはなぜですか?

事後対応型の演算子を書くのは難しい作業であり、長年にわたって多くの人が習得したものではありません。ほとんどの典型的なライブラリユーザーは、自分で演算子を作成することはできません(多くの場合、実際に試してみる必要はありません)。これは、時々、標準セットにさらに演算子を追加することを意味します。対照的に、私たちはあまりにも具体的であるか、単に自分の重みを引き出すことができない便利さのために、より多くの演算子を拒否しました。

RxJavaの設計は有機的に成長し、実際にはSOLIDなどの特定の設計原則に沿ったものではなかったと思います。それは、その流ofなAPIの使用法と感触によって主に駆動されます。

Rx.NETとのその他の関係

私の知る限り、初期の初期の0.xバージョンは、Rx.NET Observableオペレーターの名前とシグネチャ、およびいくつかのアーキテクチャ上の決定が再利用されたブラックボックスの再実装でした。これには、Rx.NETオペレーターの約20%が関与していました。当時の主な問題は、言語の解決とC#とJavaのプラットフォームの違いでした。多大な努力を払って、Rx.NETのソースコードを見ずに多くの演算子を実装し、より複雑な演算子を移植しました。

この意味で、RxJava 0.19までObservableは、Rx.NET IObservableおよびそのコンパニオンObservable拡張メソッドと同等でした。ただし、いわゆるバックプレッシャーの問題が発生し、RxJava 0.20はプロトコルおよびアーキテクチャレベルでRx.NETから分岐し始めました。使用可能な演算子をextenededた、多くは背圧-意識するようになりましたし、我々は新しいタイプを導入しました。SingleそしてCompletable今のようRx.NETには対応していない1.xの時代、インチ

背圧認識は事態をかなり複雑にし、1.x Observableはそれを後から受け止めました。バイナリ互換性への忠誠を誓ったため、プロトコルとAPIの変更はほとんど不可能でした。

Rx.NETのアーキテクチャには別の問題がありました。それを行うDisposableには、オペレータが実行を開始する前に返す必要があるため、同期キャンセルができません。ただし、などのソースRangeは熱心であり、終了するまで戻りません。この問題はDisposableObserverを返す代わりににを注入することで解決できますsubscribe()

RxJava 2.xはこれらのラインに沿ってゼロから再設計および再実装されました。にFlowableは、と同じ演算子のセットを提供する、背圧を意識した別のタイプがありますObservableObservableバックプレッシャーをサポートしておらず、Rx.NETのに相当しObservableます。内部的には、すべての事後型は消費者にキャンセルハンドルを注入し、同期キャンセルが効率的に機能するようにします。


10

私はライブラリに詳しくないことは認めますが、問題のFlowableクラスを調べたところ、一種のハブのように機能しているようです。言い換えれば、それは入力を検証し、それに応じてプロジェクト内で呼び出しを分配することを意図したクラスです。

したがって、このクラスは神オブジェクトとは見なされません。神オブジェクトはすべてを実行しようとするものです。これは、ロジックに関してはほとんど何もしません。単一の責任という点では、クラスの唯一の仕事は、図書館全体で仕事を委任していると言えます。

したがって、当然、このようなクラスはFlowable、このコンテキストでクラスに必要なすべての可能なタスクに対してメソッドを必要とします。javascriptのjQueryライブラリで同じタイプのパターンが表示されます。jQueryの場合でも、変数$にはライブラリで呼び出しを実行するために必要なすべての関数と変数があります。内で実行されます。

このようなクラスを作成するのに注意する必要があると思いますが、開発者がそれがハブにすぎず、したがってゆっくりと神のオブジェクトに変換しないことを覚えている限り、その場所があります。


2
回答の受け入れを削除することをおologiesびします。これは有益かつ啓発的でしたが、akarnokdのその後の応答はRxJavaチームの誰かからでした!
-skomisa

@skomisaそれが私自身の質問であれば、私はこれ以上何も望みませんでした!犯罪なし!:)
ニール

7

に相当する.NETのRX FlowableObservableです。これらのメソッドもすべて備えていますが、静的メソッドであり、拡張メソッドとして使用できます。RXの主なポイントは、コンポジションが流れるようなインターフェイスを使用して記述されていることです。

しかし、Javaが流interfaceなインターフェイスを持つためには、静的メソッドがうまく構成されず、静的メソッドを構成可能にする拡張メソッドがないため、それらのメソッドがインスタンスメソッドである必要があります。したがって、実際には、流なインターフェイス構文を使用しなくても問題ない限り、これらのメソッドはすべて静的メソッドにすることができます。


3
流なインターフェースのコンセプトは、IMHO、言語の制限に対する回避策です。事実上、Javaのクラスを使用して言語を構築しています。単純なプログラミング言語でさえ、いくつの機能を備えているかを考え、オーバーロードされたすべてのバリアントをカウントしないと、この多くのメソッドがどのように終わるかがかなり簡単にわかります。Java 8の機能的特徴は、この種の設計につながる多くの問題に対処することができ、Kotlinなどの現代の言語は、メソッドチェーンを必要とせずに同じ種類のメリットを得ることができるようになりつつあります。
ジミージェームズ

あなたの投稿のおかげで私はより深く掘り下げ、.NETのRXのObservableはRxJavaのObservableに匹敵するようであるため、私の質問の前提は間違っていました。それに応じてOPを更新しました。また、RxJavaのFlowable≈(Observable +並列化およびバックプレッシャーを処理するためのいくつかの追加メソッド)。
-skomisa

@skomisa JavaのObservableにも数百のメソッドがあります。したがって、2つを比較できます。ただし、主な違いは、.NETのObservableは静的であり、すべてのメソッドが静的であることです。Javaはそうではありませんが。そしてそれは大きな違いです。しかし、実際には、それらは同じように動作します。
陶酔
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.