क्या RxJava क्लास फ़्लोएबल में वैध तरीके से 460 तरीके हो सकते हैं?


14

मैं सिर्फ RxJava , जावा के रिएक्टिवएक्स (जिसे आरएक्स और रिएक्टिव एक्सटेंशन्स के रूप में भी जाना जाता है ) के कार्यान्वयन के साथ शुरू कर रहा हूं । कुछ ऐसा जो वास्तव में मुझ पर छा गया, RxJava के फ़्लोएबल क्लास का विशाल आकार था : इसमें 460 विधियाँ हैं!

निष्पक्ष तौर पर:

  • बहुत सारे तरीके हैं जो अतिभारित होते हैं, जो कुल तरीकों की संख्या में काफी वृद्धि करते हैं।

  • शायद इस वर्ग को तोड़ दिया जाए, लेकिन आरएक्सजाव का मेरा ज्ञान और समझ बहुत सीमित है। RxJava को बनाने वाले लोग निश्चित रूप से बहुत स्मार्ट हैं, और वे कई तरीकों से फ़्लोएबल को चुनने के लिए मान्य तर्क प्रस्तुत कर सकते हैं ।

दूसरी ओर:

  • RxJava Microsoft के रिएक्टिव एक्सटेंशन्स का जावा कार्यान्वयन है , और इसमें फ्लोएबल क्लास भी नहीं है , इसलिए यह किसी मौजूदा क्लास को आँख बंद करके जावा में लागू करने का मामला नहीं है।

  • [ अद्यतन: इटैलिक में पिछले बिंदु तथ्यात्मक रूप से गलत है: माइक्रोसॉफ्ट के प्रत्यक्ष वर्ग है, जो 400 से अधिक तरीकों है, RxJava के लिए आधार के रूप में इस्तेमाल किया गया था नमूदार वर्ग, और flowable के समान है नमूदार लेकिन हैंडल डेटा की बड़ी मात्रा के लिए backpressure। तो RxJava टीम एक मौजूदा वर्ग को पोर्ट कर रही थी। यह पोस्ट RxJava के फ़्लोएबल क्लास के बजाय Microsoft द्वारा ऑब्ज़र्वेबल क्लास के मूल डिज़ाइन को चुनौती देने वाली होनी चाहिए ।]

  • RxJava केवल 3 साल से अधिक पुराना है, इसलिए यह कोड का उदाहरण नहीं है, जो अच्छे ( SOLID ) वर्ग डिजाइन सिद्धांतों के बारे में ज्ञान की कमी के कारण गलत तरीके से डिजाइन किया गया है (जैसा कि जावा के शुरुआती रिलीज के साथ हुआ था)।

एक वर्ग के लिए जितना बड़ा फ्लोएबल होता है उसका डिज़ाइन स्वाभाविक रूप से गलत लगता है, लेकिन शायद नहीं; इस एसई प्रश्न का एक उत्तर कक्षा विधियों की संख्या की सीमा क्या है? सुझाव दिया गया है कि उत्तर "आपके पास जितनी ज़रूरत है उतने तरीके हैं "।

स्पष्ट रूप से कुछ वर्ग ऐसे हैं जिन्हें भाषा की परवाह किए बिना उचित तरीके से उचित संख्या में तरीकों की आवश्यकता है, क्योंकि वे आसानी से किसी भी छोटी चीज को नहीं तोड़ते हैं और उनके पास उचित विशेषताओं और विशेषताओं की संख्या होती है। उदाहरण के लिए: स्ट्रिंग्स, रंग, स्प्रेडशीट सेल, डेटाबेस परिणाम सेट और HTTP अनुरोध। उन चीजों का प्रतिनिधित्व करने के लिए कक्षाओं के लिए शायद कुछ दर्जन विधियां होने के बाद अनुचित नहीं लगती हैं।

लेकिन क्या फ्लोएबल को वास्तव में 460 तरीकों की आवश्यकता होती है, या क्या यह इतना विशाल है कि यह आवश्यक रूप से खराब वर्ग डिजाइन का एक उदाहरण है?

[स्पष्ट होने के लिए: यह प्रश्न विशेष रूप से सामान्य रूप से भगवान की वस्तुओं के बजाय RxJava के फ़्लोएबल क्लास से संबंधित है ।]



1
@gnat अच्छी तरह से संबंधित है, लेकिन यह एक डुप्लिकेट नहीं है। यह सवाल सामान्य था, और मेरा सवाल विशेष रूप से RxJava के फ़्लोएबल क्लास से संबंधित है ।
स्कोमीसा

@skomisa फिर अपने प्रश्न को फिट करने के लिए शीर्षक को ठीक करें।
यूफोरिक

@ यूफोरिक प्वाइंट लिया।
स्कोमीसा

1
यह प्रश्न बहुत ही रोचक और स्थापित है। फिर भी, मैं एक कम व्यक्तिपरक शैली (शायद शुरुआती झटके ;-) के कारण) को अपनाने के लिए इसे थोड़ा पुन: व्यवस्थित करने का सुझाव दूंगा
क्रिस्टोफ़े

जवाबों:


14

टी एल; डीएल

जावा की भाषा सुविधाओं की कमी सी # की तुलना में और साथ ही खोज योग्यताओं ने हमें बड़े वर्गों में स्रोत और मध्यवर्ती ऑपरेटर डाल दिया।

डिज़ाइन

मूल Rx.NET C # 3.0 में विकसित किया गया था जिसमें दो महत्वपूर्ण विशेषताएं हैं: विस्तार विधियाँ और आंशिक वर्ग। पूर्व आपको अन्य प्रकारों पर आवृत्ति विधियों को परिभाषित करने देता है जो तब उस लक्ष्य प्रकार का हिस्सा प्रतीत होते हैं जबकि आंशिक कक्षाएं आपको बड़ी कक्षाओं को कई फाइलों में विभाजित करने की अनुमति देती हैं।

इनमें से कोई भी सुविधाएँ जावा में मौजूद नहीं थीं या मौजूद थीं, इसलिए हमें RxJava को सुविधाजनक रूप से उपयोग करने के लिए एक रास्ता खोजना था।

RxJava में दो प्रकार के ऑपरेटर होते हैं: स्थिर फैक्ट्री विधियों द्वारा प्रस्तुत स्रोत-जैसे और उदाहरण के तरीकों द्वारा इंटरमीडिएट-जैसे प्रतिनिधित्व। पूर्व किसी भी वर्ग में रह सकता है और इस प्रकार उन्हें कई उपयोगिता वर्गों के साथ वितरित किया जा सकता है। बाद वाले को काम करने के लिए एक उदाहरण की आवश्यकता होती है। अवधारणा में, इन सभी को पहले पैरामीटर के रूप में अपस्ट्रीम के साथ स्थिर तरीकों के माध्यम से व्यक्त किया जा सकता है।

व्यवहार में, हालांकि, कई प्रवेश-कक्षाएं होने से नए उपयोगकर्ताओं द्वारा असुविधाजनक सुविधा की खोज होती है (याद रखें, RxJava को जावा में एक नई अवधारणा और प्रोग्रामिंग प्रतिमान लाना था) और साथ ही उन मध्यवर्ती ऑपरेटरों के उपयोग से कुछ बुरा सपना भी था। इसलिए, मूल टीम तथाकथित धाराप्रवाह एपीआई डिजाइन के साथ आई: एक वर्ग जो सभी स्थिर और आवृत्ति विधियों को रखता है और एक स्रोत या प्रसंस्करण चरण का प्रतिनिधित्व करता है।

त्रुटियों, संगामिति समर्थन और कार्यात्मक प्रकृति की प्रथम श्रेणी प्रकृति के कारण, प्रतिक्रियाशील प्रवाह के बारे में सभी प्रकार के स्रोतों और परिवर्तनों के साथ आ सकता है। जैसा कि Rx.NET के दिनों से पुस्तकालय (और अवधारणा) विकसित हुआ था, अधिक से अधिक मानक ऑपरेटरों को जोड़ा गया था, जो कि स्वभाव से विधि की संख्या में वृद्धि हुई थी। इससे दो सामान्य शिकायतें होती हैं:

  • इतने सारे तरीके क्यों हैं?
  • क्यों वहाँ एक विधि एक्स नहीं है जो मेरी बहुत विशेष समस्या को हल करता है?

प्रतिक्रियाशील ऑपरेटरों को लिखना कठिन काम है जो कई लोगों को वर्षों से महारत हासिल है; अधिकांश विशिष्ट पुस्तकालय उपयोगकर्ता खुद से ऑपरेटर नहीं बना सकते हैं (और अक्सर यह उनके लिए प्रयास करने के लिए वास्तव में आवश्यक नहीं है)। इसका मतलब है कि हम समय-समय पर मानक सेट में आगे के ऑपरेटरों को जोड़ते हैं। इसके विपरीत, हमने बहुत अधिक ऑपरेटरों को अस्वीकार कर दिया है क्योंकि वे बहुत विशिष्ट हैं या बस एक सुविधा है जो अपना स्वयं का वजन नहीं खींच सकती है।

मैं कहता हूँ कि RxJava का डिज़ाइन व्यवस्थित रूप से बढ़ा है और वास्तव में SOLID जैसे कुछ डिज़ाइन सिद्धांतों के साथ नहीं है। यह ज्यादातर अपने धाराप्रवाह एपीआई के उपयोग और अनुभव से प्रेरित है।

Rx.NET के अन्य संबंध

मैं 2013 के अंत में RxJava विकास में शामिल हो गया। जहां तक ​​मैं बता सकता हूं, शुरुआती शुरुआती 0.x संस्करण काफी हद तक एक ब्लैक-बॉक्स रीइम्प्लीमेंटेशन थे, जहां Rx.NET Observableऑपरेटरों के नाम और हस्ताक्षर और साथ ही कुछ वास्तु निर्णय भी पुन: उपयोग किए गए थे। इसमें लगभग 20% Rx.NET ऑपरेटर शामिल थे। मुख्य कठिनाई तब C # और जावा के बीच भाषा और प्लेटफ़ॉर्म अंतर का समाधान था। बहुत प्रयास के साथ, हमने Rx.NET के स्रोत कोड को देखे बिना कई ऑपरेटरों को लागू करने में कामयाबी हासिल की और हमने अधिक जटिल लोगों को चित्रित किया।

इस अर्थ में, RxJava 0.19 तक, हमारा ObservableRx.NET IObservableऔर उसके साथी Observableविस्तार विधियों के बराबर था । हालाँकि, तथाकथित बैकस्पेस की समस्या सामने आई और RxJava 0.20 ने Rx.NET को एक प्रोटोकॉल और वास्तु स्तर पर बदलना शुरू कर दिया। उपलब्ध ऑपरेटरों को हटा दिया गया था, कई बैकपेचर-अवगत हो गए और हमने नए प्रकार पेश किए: Singleऔर Completable1.x युग में, जिनके पास अब तक Rx.NET में कोई समकक्ष नहीं है।

बैकप्रेशर-जागरूकता चीजों को काफी जटिल करती है और 1.x Observableने इसे बाद में प्राप्त किया। हम बाइनरी संगतता के लिए निष्ठा की शपथ लेते हैं इसलिए प्रोटोकॉल और एपीआई को बदलना ज्यादातर संभव नहीं था।

Rx.NET की वास्तुकला के साथ एक और समस्या थी: तुल्यकालिक रद्दीकरण संभव नहीं है क्योंकि ऐसा करने के Disposableलिए, ऑपरेटर को निष्पादित करने से पहले एक को वापस करने की आवश्यकता होती है। हालांकि, जैसे स्रोत Rangeउत्सुक थे और जब तक वे खत्म नहीं करते तब तक वापस नहीं आते। एक से लौटने Disposableके Observerबजाय एक में इंजेक्ट करके इस समस्या को हल किया जा सकता है subscribe()

RxJava 2.x को इन लाइनों के साथ खरोंच से फिर से डिजाइन और पुन: लागू किया गया था । हमारे पास एक अलग, बैकस्पेस-अवेयर प्रकार है Flowableजो ऑपरेटरों के समान सेट प्रदान करता है ObservableObservableबैकप्रेशर का समर्थन नहीं करता है और Rx.NET के समतुल्य है Observable। आंतरिक रूप से, सभी प्रतिक्रियाशील प्रकार अपने उपभोक्ताओं के लिए अपने रद्दीकरण हैंडल को इंजेक्ट करते हैं, जिससे सिंक्रोनस रद्दीकरण को कुशलतापूर्वक काम करने की अनुमति मिलती है।


10

जबकि मैं मानता हूँ कि मैं पुस्तकालय से परिचित नहीं हूँ, मैंने प्रश्न में फ़्लोएबल क्लास पर एक नज़र डाली और ऐसा लगा जैसे यह एक तरह का हब है। दूसरे शब्दों में, यह एक वर्ग है जो इनपुट को मान्य करता है और परियोजना के अनुसार कॉल वितरित करता है।

इस वर्ग को वास्तव में ईश्वर वस्तु नहीं माना जाएगा क्योंकि ईश्वर वस्तु वह है जो सब कुछ करने का प्रयास करता है। तर्क की दृष्टि से यह बहुत कम है। एकल-जिम्मेदारी के संदर्भ में, कक्षा की एकमात्र नौकरी को पूरे पुस्तकालय में काम सौंपना कहा जा सकता है।

तो स्वाभाविक रूप से इस तरह के Flowableवर्ग को इस संदर्भ में एक वर्ग की आवश्यकता होती है जो आपको हर संभव कार्य के लिए एक विधि की आवश्यकता होगी । आप जावास्क्रिप्ट में jQuery लाइब्रेरी के साथ एक ही प्रकार के पैटर्न को देखते हैं, जहां चर $में लाइब्रेरी पर कॉल करने के लिए आवश्यक सभी फ़ंक्शन और चर हैं, jQuery के मामले में, कोड को केवल प्रत्यायोजित नहीं किया गया है, बल्कि एक अच्छा तर्क भी है भीतर चलाया जाता है।

मुझे लगता है कि आपको इस तरह की एक कक्षा बनाने के लिए सावधान रहना चाहिए, लेकिन इसकी जगह इतनी लंबी है कि डेवलपर को याद है कि यह केवल एक हब है, और इसलिए धीरे-धीरे एक देव वस्तु में परिवर्तित नहीं होता है।


2
आपके उत्तर की स्वीकृति को दूर करने के लिए क्षमा याचना, जो सहायक और ज्ञानवर्धक, दोनों थी, लेकिन एंकरोकड की बाद की प्रतिक्रिया RxJava टीम के किसी व्यक्ति की थी!
स्कोमीसा

@skomisa मैं और कुछ नहीं के लिए उम्मीद कर सकता था अगर यह मेरा अपना सवाल था! कोई अपराध नहीं लिया! :)
नील

7

नेट के RX के बराबर करने के लिए Flowableहै प्रत्यक्ष । यह भी उन सभी तरीकों की है, लेकिन वे विस्तार विधियों के रूप में स्थिर और उपयोग करने योग्य हैं । आरएक्स का मुख्य बिंदु यह है कि रचना धाराप्रवाह इंटरफ़ेस का उपयोग करके लिखी गई है

लेकिन जावा में धाराप्रवाह इंटरफ़ेस होने के लिए, इसे उन तरीकों की आवश्यकता होती है, उदाहरण के तरीके, क्योंकि स्थैतिक विधियाँ अच्छी तरह से नहीं बनती हैं और इसमें स्थैतिक विधियों को बनाने के लिए विस्तार विधियाँ नहीं होती हैं। तो व्यवहार में, उन सभी विधियों को स्थिर तरीके से बनाया जा सकता है, जब तक आप धाराप्रवाह इंटरफ़ेस सिंटैक्स का उपयोग नहीं कर रहे थे।


3
धाराप्रवाह इंटरफ़ेस अवधारणा, IMHO, भाषा सीमाओं के लिए एक समाधान है। प्रभावी रूप से, आप जावा के शीर्ष पर एक वर्ग का उपयोग करके एक भाषा का निर्माण कर रहे हैं। यदि आप सोचते हैं कि एक साधारण प्रोग्रामिंग भाषा में भी कितनी विशेषताएं हैं और सभी अतिभारित वेरिएंट की गणना नहीं करते हैं, तो यह देखना काफी आसान हो जाता है कि आप इस कई तरीकों से कैसे समाप्त होते हैं। जावा 8 की कार्यात्मक विशेषताएं बहुत सारे मुद्दों को संबोधित कर सकती हैं जो इस तरह के डिजाइन और समकालीन भाषाओं को जन्म देती हैं जैसे कि कोटलिन, विधि जंजीर की आवश्यकता के बिना उसी तरह के लाभ प्राप्त करने में सक्षम हैं।
जिम्मीजेम्स

आपके पोस्ट के लिए धन्यवाद, मैंने गहराई से खोदा और ऐसा लगता है कि .NET का RX ऑब्जर्वेबल RxJava के ऑब्ज़र्वेबल के लिए d है, इसलिए मेरे प्रश्न का एक आधार गलत था। मैंने तदनुसार ओपी को अपडेट किया है। इसके अलावा, RxJava के फ़्लोएबल ≈ (ऑब्जर्वेबल + बैकपैक्चर को समानांतर करने और संभालने के लिए कुछ अतिरिक्त तरीके)।
स्कोमीसा

@skomisa जावा के अवलोकनीय में भी सैकड़ों विधियाँ हैं। तो आप दोनों की तुलना कर सकते हैं। लेकिन प्रमुख अंतर यह है कि .NET का अवलोकन स्थिर है और सभी विधियाँ स्थिर हैं। जबकि जावा का नहीं है। और वह बहुत बड़ा अंतर है। लेकिन व्यवहार में, वे एक ही व्यवहार करते हैं।
व्यंग्यात्मक
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.