Bisakah kelas RxJava Flowable secara sah memiliki 460 metode?

14

Saya baru memulai dengan RxJava , implementasi Java dari ReactiveX (juga dikenal sebagai Rx and Reactive Extensions ). Sesuatu yang benar-benar memukul saya adalah ukuran besar RxJava ini Flowable kelas : memiliki 460 metode!

Agar adil:

  • Ada banyak metode yang kelebihan beban, yang menabrak jumlah total metode secara signifikan.

  • Mungkin kelas ini harus dibubarkan, tetapi pengetahuan dan pemahaman saya tentang RxJava sangat terbatas. Orang-orang yang membuat RxJava pasti sangat pintar, dan mereka mungkin dapat menawarkan argumen yang valid untuk memilih untuk membuat Flowable dengan banyak metode.

Di samping itu:

  • RxJava adalah implementasi Java dari Ekstensi Reaktif Microsoft , dan yang bahkan tidak memiliki kelas Flowable , jadi ini bukan kasus porting secara buta kelas yang ada dan mengimplementasikannya di Jawa.

  • [ Pembaruan: Titik sebelumnya dalam huruf miring faktual salah: kelas Microsoft's Observable , yang memiliki lebih dari 400 metode, digunakan sebagai dasar untuk kelas Observable RxJava , dan Flowable mirip dengan Observable tetapi menangani tekanan balik untuk volume data yang besar. Jadi tim RxJava mem - porting kelas yang sudah ada. Posting ini seharusnya lebih menantang desain asli dari kelas Observable oleh Microsoft daripada kelas Flowable RxJava .]

  • RxJava baru berusia kurang dari 3 tahun, jadi ini bukan contoh kode yang dirancang salah karena kurangnya pengetahuan tentang prinsip-prinsip desain kelas ( SOLID ) yang baik (seperti halnya dengan rilis awal Jawa).

Untuk kelas sebesar Flowable desainnya kelihatannya salah, tapi mungkin tidak; satu jawaban untuk pertanyaan SE ini Berapa batas jumlah metode kelas? menyarankan bahwa jawabannya adalah " Miliki metode sebanyak yang Anda butuhkan ".

Jelas ada beberapa kelas yang secara sah membutuhkan sejumlah metode yang adil untuk mendukung mereka terlepas dari bahasa, karena mereka tidak mudah terurai menjadi sesuatu yang lebih kecil dan mereka memiliki sejumlah karakteristik dan atribut yang adil. Misalnya: string, warna, sel spreadsheet, set hasil basis data, dan permintaan HTTP. Mungkin memiliki beberapa lusin metode untuk kelas untuk mewakili hal-hal itu tampaknya tidak masuk akal.

Tetapi apakah Flowable benar-benar membutuhkan 460 metode, atau apakah itu sangat besar sehingga itu merupakan contoh dari desain kelas yang buruk?

[Agar lebih jelas: pertanyaan ini secara khusus berhubungan dengan kelas Flowable RxJava daripada objek Allah pada umumnya.]

skomisa
sumber
1
@gnat Yah pasti terkait, tetapi itu bukan duplikat. Pertanyaan itu bersifat umum, dan pertanyaan saya secara khusus berkaitan dengan kelas Flowable RxJava .
skomisa
@skomisa Kemudian perbaiki judul yang sesuai dengan pertanyaan Anda.
Euforia
@Euphoric Point diambil.
skomisa
1
Pertanyaan ini sangat menarik dan didirikan. Namun, saya menyarankan untuk menulis ulang sedikit agar dapat mengadopsi gaya yang kurang subyektif (mungkin karena guncangan awal ;-))
Christophe

Jawaban:

14

TL; DL

Kurangnya fitur bahasa Jawa dibandingkan dengan C # serta pertimbangan dapat ditemukan membuat kami menempatkan operator sumber dan perantara ke dalam kelas besar.

Rancangan

Rx.NET asli dikembangkan di C # 3.0 yang memiliki dua fitur penting: metode ekstensi dan kelas parsial. Yang pertama memungkinkan Anda mendefinisikan metode instance pada tipe lain yang kemudian tampak menjadi bagian dari tipe target tersebut sedangkan kelas parsial memungkinkan Anda untuk membagi kelas besar menjadi beberapa file.

Tidak satu pun dari fitur ini ada atau ada di Jawa, oleh karena itu, kami harus menemukan cara agar RxJava dapat digunakan dengan cukup mudah.

Ada dua jenis operator di RxJava: seperti-sumber diwakili oleh metode pabrik statis dan mirip-menengah diwakili oleh metode contoh. Yang pertama dapat hidup di kelas mana saja dan dengan demikian mereka dapat didistribusikan bersama beberapa kelas utilitas. Yang terakhir membutuhkan contoh yang harus dikerjakan. Secara konsep, semua ini dapat diekspresikan melalui metode statis dengan upstream sebagai parameter pertama.

Namun dalam praktiknya, memiliki beberapa kelas entri membuat penemuan fitur oleh pengguna baru tidak nyaman (ingat, RxJava harus membawa konsep dan paradigma pemrograman baru ke Jawa) serta penggunaan operator perantara tersebut agak menjadi mimpi buruk. Oleh karena itu, tim asli datang dengan apa yang disebut desain API lancar: satu kelas yang menampung semua metode statis dan contoh dan mewakili sumber atau tahap pemrosesan dengan sendirinya.

Karena sifat kesalahan kelas satu, dukungan konkurensi, dan sifat fungsional, seseorang dapat memunculkan segala macam sumber dan transformasi berkenaan dengan aliran reaktif. Sebagai perpustakaan (dan konsep) berkembang sejak zaman Rx.NET, operator standar semakin banyak ditambahkan, yang secara alami meningkatkan jumlah metode. Ini mengarah pada dua keluhan biasa:

  • Mengapa ada begitu banyak metode?
  • Mengapa tidak ada metode X yang memecahkan masalah saya yang sangat khusus?

Menulis operator reaktif adalah tugas yang sulit tidak banyak orang kuasai selama bertahun-tahun; sebagian besar pengguna perpustakaan tidak dapat membuat operator sendiri (dan seringkali tidak perlu bagi mereka untuk mencoba). Ini berarti kami, dari waktu ke waktu, menambahkan operator lebih lanjut ke perangkat standar. Sebaliknya, kami telah menolak lebih banyak operator karena terlalu spesifik atau sekadar kenyamanan yang tidak dapat menarik bobotnya sendiri.

Saya akan mengatakan desain RxJava tumbuh secara organik dan tidak benar-benar mengikuti prinsip-prinsip desain tertentu seperti SOLID. Sebagian besar didorong oleh penggunaan dan nuansa API yang lancar.

Hubungan lainnya dengan Rx.NET

Saya bergabung dengan pengembangan RxJava pada akhir 2013. Sejauh yang saya tahu, versi awal 0.x sebagian besar merupakan implementasi ulang kotak hitam di mana nama dan tanda tangan dari Observableoperator Rx.NET serta beberapa keputusan arsitektur digunakan kembali. Ini melibatkan sekitar 20% dari operator Rx.NET. Kesulitan utama saat itu adalah resolusi perbedaan bahasa dan platform antara C # dan Java. Dengan susah payah, kami berhasil mengimplementasikan banyak operator tanpa melihat kode sumber Rx.NET dan kami porting yang lebih rumit.

Dalam hal ini, hingga RxJava 0,19, kami Observablesetara dengan Rx.NET IObservabledan Observablemetode ekstensi pendampingnya . Namun, masalah yang disebut tekanan balik muncul dan RxJava 0,20 mulai menyimpang dari Rx.NET pada tingkat protokol dan arsitektur. Operator yang tersedia telah dikembangkan, banyak yang menjadi sadar tekanan balik dan kami memperkenalkan tipe baru: Singledan Completabledi era 1.x, yang tidak memiliki rekan di Rx.NET seperti sekarang.

Kesadaran backpressure menyulitkan banyak hal dan 1.x Observablemenerimanya sebagai renungan. Kami bersumpah untuk kompatibilitas biner sehingga mengubah protokol dan API sebagian besar tidak mungkin.

Ada masalah lain dengan arsitektur Rx.NET: pembatalan sinkron tidak mungkin karena untuk melakukan itu, orang perlu Disposabledikembalikan sebelum operator mulai mengeksekusi. Namun, sumber-sumber seperti Rangesangat bersemangat dan tidak kembali sampai selesai. Masalah ini dapat diselesaikan dengan menyuntikkan Disposableke dalam Observerbukannya mengembalikan dari subscribe().

RxJava 2.x dirancang ulang dan diimplementasikan kembali dari awal di sepanjang garis-garis ini. Kami memiliki tipe terpisah, yang menyadari tekanan balik Flowableyang menawarkan set yang sama dengan operator Observable. Observabletidak mendukung tekanan balik dan agak setara dengan Rx.NET Observable. Secara internal, semua jenis reaktif menyuntikkan pegangan pembatalan mereka kepada konsumen mereka, memungkinkan pembatalan sinkron untuk bekerja secara efisien.

akarnokd
sumber
10

Meskipun saya akui bahwa saya tidak terbiasa dengan perpustakaan, saya melihat kelas Flowable yang dimaksud dan sepertinya itu bertindak seperti semacam hub. Dengan kata lain, ini adalah kelas yang dimaksudkan untuk memvalidasi input dan mendistribusikan panggilan yang sesuai dalam proyek.

Kelas ini karena itu tidak akan benar-benar dianggap sebagai objek Tuhan sebagai objek Tuhan adalah salah satu yang berusaha melakukan segalanya. Ini sangat sedikit dalam hal logika. Dalam hal tanggung jawab tunggal, satu-satunya tugas kelas dapat dikatakan mendelegasikan pekerjaan di seluruh perpustakaan.

Jadi tentu saja kelas seperti itu akan membutuhkan metode untuk setiap tugas yang mungkin Anda butuhkan dari Flowablekelas dalam konteks ini. Anda melihat jenis pola yang sama dengan pustaka jQuery di javascript, di mana variabel $memiliki semua fungsi dan variabel yang diperlukan untuk melakukan panggilan di pustaka, meskipun dalam kasus jQuery, kode tidak hanya didelegasikan tetapi juga sedikit logika yang baik dijalankan di dalam.

Saya pikir Anda harus berhati-hati untuk membuat kelas seperti ini, tetapi memiliki tempatnya selama pengembang ingat bahwa itu hanya sebuah hub, dan karena itu tidak perlahan-lahan beralih ke objek dewa.

Neil
sumber
2
Permintaan maaf karena menghilangkan penerimaan atas jawaban Anda, yang bermanfaat sekaligus mencerahkan, tetapi respons akarnokd selanjutnya adalah dari seseorang di tim RxJava!
skomisa
@skomisa aku tidak bisa berharap apa-apa lagi jika itu adalah pertanyaanku sendiri! Jangan tersinggung! :)
Neil
7

Setara dengan .NET's RX Flowableadalah Observable . Ini juga memiliki semua metode itu, tetapi mereka statis dan dapat digunakan sebagai metode ekstensi . Poin utama dari RX adalah bahwa komposisi ditulis menggunakan antarmuka yang lancar .

Tetapi agar Java memiliki antarmuka yang lancar, ia perlu metod-metod tersebut sebagai metode instan, karena metode statis tidak dapat menyusun dengan baik dan tidak memiliki metode ekstensi untuk membuat metode statis komposable. Jadi dalam prakteknya, semua metode itu bisa menjadi metode statis, selama Anda baik-baik saja tidak menggunakan sintaks antarmuka fasih.

Euforia
sumber
3
Konsep antarmuka yang lancar adalah, IMHO, solusi untuk keterbatasan bahasa. Secara efektif, Anda sedang membangun bahasa menggunakan kelas di atas Jawa. Jika Anda berpikir tentang berapa banyak fitur bahkan dalam bahasa pemrograman yang sederhana dan tidak menghitung semua varian yang kelebihan beban, menjadi sangat mudah untuk melihat bagaimana Anda berakhir dengan banyak metode ini. Fitur fungsional Java 8 dapat mengatasi banyak masalah yang mengarah pada desain semacam ini dan bahasa kontemporer seperti Kotlin sedang bergerak untuk bisa mendapatkan jenis manfaat yang sama tanpa perlu metode chaining.
JimmyJames
Terima kasih untuk posting Anda, saya menggali lebih dalam dan tampaknya .NET's RX's Observable adalah ≈ to RxJava's Observable, jadi premis dari pertanyaan saya salah. Saya telah memperbarui OP yang sesuai. Juga, Flowable x RxJava (Dapat Diobservasi + beberapa metode tambahan untuk memparalelkan dan menangani tekanan balik).
skomisa
@skomisa Java's Observable juga memiliki ratusan metode. Jadi Anda bisa membandingkan keduanya. Tetapi perbedaan utama adalah bahwa .NET's Observable adalah statis dan semua metode statis. Sedangkan Java tidak. Dan itu perbedaan besar. Namun dalam praktiknya, mereka berperilaku sama.
Euforia