विधि जंजीर - यह एक अच्छा अभ्यास क्यों है, या नहीं?


151

विधि जंजीर एक और विधि के लिए बुलाया जा करने के लिए परिणाम के क्रम में वस्तु वापस लौटने वाली वस्तु विधियों का अभ्यास है। ऐशे ही:

participant.addSchedule(events[1]).addSchedule(events[2]).setStatus('attending').save()

यह एक अच्छा अभ्यास माना जाता है, क्योंकि यह पठनीय कोड, या "धाराप्रवाह इंटरफ़ेस" पैदा करता है। हालाँकि, मेरे लिए इसके बजाय ऑब्जेक्ट ओरिएंटेशन द्वारा निहित ऑब्जेक्ट कॉलिंग नोटेशन को तोड़ना प्रतीत होता है - परिणामस्वरूप कोड पिछली पद्धति के परिणाम के लिए क्रिया करने का प्रतिनिधित्व नहीं करता है , जो कि ऑब्जेक्ट ओरिएंटेड कोड आमतौर पर काम करने की उम्मीद है:

participant.getSchedule('monday').saveTo('monnday.file')

यह अंतर "परिणामी वस्तु को कॉल करने" की डॉट-नोटेशन के लिए दो अलग-अलग अर्थों का निर्माण करता है: चेनिंग के संदर्भ में, उपरोक्त उदाहरण प्रतिभागी वस्तु को बचाने के रूप में पढ़ेगा , हालांकि उदाहरण वास्तव में शेड्यूल को बचाने के लिए है। getSchedule द्वारा प्राप्त वस्तु।

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

participant.attend(event).setNotifications('silent').getSocialStream('twitter').postStatus('Joining '+event.name).follow(event.getSocialId('twitter'))

अंतिम दो विधि कॉल getSocialStream के परिणाम को संदर्भित करते हैं, जबकि प्रतिभागी को संदर्भित करने से पहले। शायद यह वास्तव में चेन को लिखने के लिए बुरा व्यवहार है जहां संदर्भ बदल जाता है (यह है?), लेकिन फिर भी आपको लगातार जांचना होगा कि क्या समान दिखने वाले डॉट-चेन वास्तव में एक ही संदर्भ में रहते हैं, या केवल परिणाम पर काम करते हैं ।

मेरे लिए यह प्रतीत होता है कि सतही तौर पर पीछा करने की विधि पठनीय कोड का उत्पादन करती है, लेकिन डॉट-नोटेशन के अर्थ को ओवरलोड करने से केवल अधिक भ्रम पैदा होता है। जैसा कि मैं खुद को प्रोग्रामिंग गुरु नहीं मानता, मैं मानता हूं कि गलती मेरी है। तो मुझे क्या याद आ रही है? क्या मैं किसी तरह से गलत तरीके से पीछा करने की विधि को समझता हूं? क्या कुछ ऐसे मामले हैं जहाँ विधि-निर्धारण विशेष रूप से अच्छा है, या कुछ जहाँ यह विशेष रूप से बुरा है?

सिडेनोट: मैं समझता हूं कि इस प्रश्न को एक प्रश्न के रूप में देखा जा सकता है। हालांकि, यह नहीं है - मैं वास्तव में यह समझना चाहता हूं कि चाइनिंग को अच्छा अभ्यास क्यों माना जाता है, और मैं यह सोचने में गलत नहीं हूं कि यह अंतर्निहित वस्तु-उन्मुख संकेतन को तोड़ता है।


लगता है कि विधि जंजीर कम से कम एक तरीका है जावा में स्मार्ट कोड लिखने के लिए। यहां तक ​​कि अगर हर एक सहमत नहीं है ..
मर्सर ट्रेस्टी

वे इन "धाराप्रवाह" विधियों या "धाराप्रवाह" इंटरफ़ेस को भी कहते हैं। आप इस शब्द का उपयोग करने के लिए अपने शीर्षक को अद्यतन करना चाह सकते हैं।
S.Lott

4
एक अन्य एसओ चर्चा में यह कहा गया कि धाराप्रवाह इंटरफ़ेस एक बड़ी अवधारणा है जिसे कोड पठनीयता के साथ करना है, और इस तरीके को लक्ष्य करने के लिए विधि जंजीर केवल एक ही तरीका है। यद्यपि वे निकटता से संबंधित हैं, इसलिए मैंने पाठ में टैग और संदर्भित धाराप्रवाह जोड़ दिए - मुझे लगता है कि ये पर्याप्त हैं।
इलारी कजस्ट

14
जिस तरह से मैं यह सोचने के लिए आया हूं, वह तरीका है चाइनिंग, वास्तव में, भाषा सिंटैक्स में एक लापता सुविधा प्राप्त करने के लिए एक हैकअरेन्स। यह वास्तव में जरूरी नहीं होगा अगर कोई अंतर्निहित वैकल्पिक संकेतन था .जो किसी भी मेहतोड रिटर्न मान को अनदेखा करेगा और हमेशा उसी वस्तु का उपयोग करके किसी भी जंजीर पद्धति को लागू करेगा।
इलारी कजस्ट जूल

यह एक महान कोडिंग मुहावरा है लेकिन सभी महान उपकरणों की तरह इसका दुरुपयोग होता है।
मार्टिन स्पामर

जवाबों:


74

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

MyObject.Start()
    .SpecifySomeParameter(asdasd)
    .SpecifySomeOtherParameter(asdasd)
    .Execute();

विधि का पीछा करने का तरीका वैकल्पिक था, लेकिन इसने कोड को लिखना आसान बना दिया (विशेषकर इंटेलीजेंसी के साथ)। आप ध्यान रखें कि यह एक अलग मामला है, और मेरे कोड में एक सामान्य अभ्यास नहीं है।

मुद्दा यह है - 99% मामलों में आप शायद विधि के रूप में अच्छी तरह से या यहां तक ​​कि बेहतर तरीके से कर सकते हैं। लेकिन 1% है जहां यह सबसे अच्छा तरीका है।


4
IMO, इस परिदृश्य में विधि का उपयोग करने का सबसे अच्छा तरीका है, फंक्शन में पास होने के लिए एक पैरामीटर ऑब्जेक्ट बनाना, जैसे P = MyObject.GetParamsObj().SomeParameter(asdasd).SomeOtherParameter(asdasd); Obj = MyObject.Start(); MyObject.Execute(P);। आपके पास अन्य कॉल में इस पैरामीटर ऑब्जेक्ट को पुन: प्रस्तुत करने में सक्षम होने का लाभ है, जो कि एक प्लस है!
पैडरोमैनोएल

20
पैटर्न, फैक्ट्री पद्धति के बारे में मेरे योगदान का सिर्फ एक प्रतिशत है, आमतौर पर केवल एक निर्माण बिंदु होता है और उत्पाद फैक्ट्री विधि के मापदंडों के आधार पर एक स्थिर चयन होते हैं। श्रृंखला निर्माण एक बिल्डर पैटर्न के लिए अधिक दिखता है जहां आप परिणाम प्राप्त करने के लिए अलग-अलग तरीकों को कहते हैं, विधियां वैकल्पिक हो सकती हैं क्योंकि विधि जंजीर में , हमारे पास यहां कुछ PizzaBuilder.AddSauce().AddDough().AddTopping()और संदर्भ हो सकते हैं
मार्को मेद्रेनो

3
विधि जंजीर (मूल प्रश्न में घुट के रूप में) खराब माना जाता है जब यह कानून के कानून का उल्लंघन करता है । देखें: ifacethoughts.net/2006/03/07/… यहाँ दिए गए उत्तर वास्तव में उस कानून का अनुसरण करते हैं क्योंकि यह "बिल्डर पैटर्न" है।
एंजेल ओ स्फीयर

2
@Marco Medrano PizzaBuilder का उदाहरण हमेशा मुझे बहुत बुरा लगा, क्योंकि मैंने इसे JavaWorld के युग में पढ़ा था। मुझे लगता है कि मुझे अपने पिज्जा में सॉस मिलाना चाहिए, न कि मेरे शेफ को।
ब्रेकडान डाल्टन

1
मुझे पता है कि तुम्हारा क्या मतलब है, विल्क्स। लेकिन फिर भी जब मैं पढ़ता हूं list.add(someItem), तो मैं पढ़ता हूं कि "यह कोड ऑब्जेक्ट में जोड़ someItemरहा है list"। इसलिए जब मैं पढ़ता हूं PizzaBuilder.AddSauce(), तो मैं इसे स्वाभाविक रूप से "इस कोड को PizzaBuilderऑब्जेक्ट में सॉस जोड़ रहा हूं" के रूप में पढ़ता हूं । दूसरे शब्दों में, मैं ऑर्केस्ट्रेटर (एक जोड़ने वाला) को उस पद्धति के रूप में देखता हूं जिसमें कोड list.add(someItem)या PizzaBuilder.addSauce()एम्बेडेड है। लेकिन मुझे लगता है कि PizzaBuilder का उदाहरण थोड़ा कृत्रिम है। आपके MyObject.SpecifySomeParameter(asdasd)लिए मेरे काम का उदाहरण ठीक है।
Breandán Dalton

78

बस मेरे 2 सेंट;

मेथड चाइनिंग डिबगिंग को मुश्किल बना देता है: - आप ब्रेकपॉइंट को संक्षिप्त बिंदु पर नहीं रख सकते हैं ताकि आप प्रोग्राम को ठीक उसी जगह पर रख सकें जहाँ आप इसे चाहते हैं - यदि इन विधियों में से कोई एक अपवाद फेंकता है, और आपको एक लाइन नंबर मिलता है, तो आपको कोई पता नहीं है "श्रृंखला" में कौन सी विधि समस्या का कारण बनी।

मुझे लगता है कि यह आम तौर पर बहुत छोटी और संक्षिप्त लाइनों को लिखने के लिए अच्छा अभ्यास है। हर पंक्ति को बस एक विधि कॉल करना चाहिए। लंबी लाइनों के लिए अधिक लाइनों को प्राथमिकता दें।

EDIT: टिप्पणी में उल्लेख किया गया है कि विधि-निर्धारण और लाइन-ब्रेकिंग अलग-अलग हैं। यह सच है। डिबगर के आधार पर, हालांकि, बयान के बीच में विराम बिंदु रखना संभव हो सकता है या नहीं भी हो सकता है। यहां तक ​​कि अगर आप कर सकते हैं, तो इंटरमीडिएट चर के साथ अलग-अलग लाइनों का उपयोग करने से आपको बहुत अधिक लचीलापन मिलता है और मूल्यों की एक पूरी गुच्छा आप वॉच विंडो में जांच कर सकते हैं जो डिबगिंग प्रक्रिया में मदद करता है।


4
स्वतंत्र का पीछा करते हुए newlines और विधि का उपयोग नहीं कर रहे हैं? आप @ Vilx- उत्तर के अनुसार एक नई लाइन पर प्रत्येक कॉल के साथ चेन कर सकते हैं, और आप आमतौर पर एक ही लाइन पर कई अलग-अलग स्टेटमेंट डाल सकते हैं (जैसे जावा में अर्धविराम का उपयोग कर रहे हैं)।
बबस्टर

2
यह उत्तर पूरी तरह से न्यायसंगत है, लेकिन यह सिर्फ उन सभी डिबगर्स में मौजूद एक कमजोरी को दर्शाता है जो मैं जानता हूं और विशेष रूप से सवाल से संबंधित नहीं है।
मास्टरएक्सिलो

1
@Brabster। वे कुछ डिबगर के लिए अलग-अलग हो सकते हैं, हालांकि, मध्यवर्ती चर के साथ अलग-अलग कॉल होने के बाद भी बग की जांच करते समय आपको बहुत अधिक जानकारी मिलती है।
RAY

4
+1, किसी भी समय आपको पता नहीं है कि चरणबद्ध तरीके से चेन को डिबग करने पर प्रत्येक विधि क्या लौटाती है। विधि श्रृंखला पैटर्न एक हैक है। यह एक रखरखाव प्रोग्रामर का सबसे बुरा सपना है।
ली कोवलकोव्स्की

1
मैं या तो चेनिंग का बहुत बड़ा प्रशंसक नहीं हूं, लेकिन केवल विधि की परिभाषाओं के अंदर ही ब्रेकपॉइंट क्यों नहीं लगाया जाता है?
पंकज शर्मा

39

व्यक्तिगत रूप से, मैं उन तरीकों को चुनना पसंद करता हूं जो केवल मूल वस्तु पर कार्य करते हैं, जैसे कि कई गुण सेट करना या उपयोगिता-प्रकार के तरीकों को कॉल करना।

foo.setHeight(100).setWidth(50).setColor('#ffffff');
foo.moveTo(100,100).highlight();

मैं इसका उपयोग नहीं करता हूं जब एक या अधिक जंजीर विधियां मेरे उदाहरण में फू के अलावा किसी भी वस्तु को वापस कर देंगी। जब तक आप श्रृंखला में उस वस्तु के लिए सही एपीआई का उपयोग कर रहे होते हैं, तब तक आप कुछ भी श्रृंखलाबद्ध कर सकते हैं, लेकिन वस्तु को बदलकर आईएमएचओ चीजों को कम पठनीय बनाता है और वास्तव में भ्रमित हो सकता है यदि विभिन्न वस्तुओं के एपीआई में कोई समानता हो। आप अंत में कुछ वास्तव में आम तरीका कॉल करते हैं ( .toString(), .print(), जो कुछ भी) जो वस्तु आप अंततः पर कार्य कर रहे हैं? कोड को पढ़ने वाले किसी व्यक्ति ने शायद यह नहीं पकड़ा कि यह मूल संदर्भ के बजाय श्रृंखला में एक अंतर्निहित लौटी वस्तु होगी।

विभिन्न वस्तुओं को जकड़ने से अप्रत्याशित अशक्त त्रुटियां भी हो सकती हैं। मेरे उदाहरणों में, यह मानते हुए कि फू वैध है, सभी विधि कॉल "सुरक्षित" हैं (उदाहरण के लिए, फू के लिए वैध)। ओपी के उदाहरण में:

participant.getSchedule('monday').saveTo('monnday.file')

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


अगर ऐसा मौका है कि एक Participantवैध नहीं है, Scheduleतो getScheduleविधि एक Maybe(of Schedule)प्रकार को लौटाने के लिए डिज़ाइन की गई है और एक प्रकार saveToको स्वीकार करने के लिए विधि तैयार की गई है Maybe
लाइटमैन

24

मार्टिन फॉलर की यहाँ अच्छी चर्चा है:

विधि जंजीर

इसका उपयोग कब करना है

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

विधि चाइनिंग विशेष रूप से माता-पिता जैसे व्याकरण के साथ प्रभावी है :: = (यह | वह) *। विभिन्न तरीकों का उपयोग देखने का पठनीय तरीका प्रदान करता है कि आगे कौन सा तर्क आ रहा है। इसी तरह से वैकल्पिक तर्क आसानी से विधि जंजीर के साथ छोड़ दिया जा सकता है। अनिवार्य खंडों की एक सूची, जैसे कि अभिभावक :: = पहला दूसरा मूल रूप के साथ इतनी अच्छी तरह से काम नहीं करता है, हालांकि इसे प्रगतिशील इंटरफेस का उपयोग करके अच्छी तरह से समर्थित किया जा सकता है। उस मामले के लिए मैं ज्यादातर समय नेस्टेड फंक्शन पसंद करता हूँ।

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


2
यह लिंक मृत है :(
Qw3ry

DSL के साथ आपका क्या मतलब है? डोमेन विशिष्ट भाषा
सोरेन

@ सॉरेन: फाउलर डोमेन-विशिष्ट भाषाओं को संदर्भित करता है।
डर्क वोल्मार

21

मेरी राय में, विधि जंजीर एक नवीनता का एक सा है। यकीन है, यह अच्छा लग रहा है, लेकिन मुझे इसमें कोई वास्तविक लाभ नहीं दिखता है।

कैसे:

someList.addObject("str1").addObject("str2").addObject("str3")

किसी भी बेहतर से:

someList.addObject("str1")
someList.addObject("str2")
someList.addObject("str3")

अपवाद तब हो सकता है जब addObject () एक नई वस्तु लौटाता है, जिस स्थिति में अनचाही कोड थोड़ा अधिक बोझिल हो सकता है जैसे:

someList = someList.addObject("str1")
someList = someList.addObject("str2")
someList = someList.addObject("str3")

9
यह अधिक संक्षिप्त है, क्योंकि आप अपने पहले उदाहरण में भी दो 'someList' भागों से बचते हैं और तीन के बजाय एक पंक्ति के साथ समाप्त होते हैं। अब अगर वह वास्तव में अच्छा या बुरा है, तो यह अलग-अलग चीजों पर निर्भर करता है और शायद स्वाद का मामला है।
फेबियन स्टिग जूल

26
केवल एक बार 'someList' होने का वास्तविक लाभ यह है कि इसे तब अधिक लंबा, अधिक वर्णनात्मक नाम देना बहुत आसान है। किसी भी समय किसी नाम को त्वरित उत्तराधिकार में कई बार प्रकट होने की आवश्यकता होती है, इसे कम करने (पुनरावृत्ति को कम करने और पठनीयता में सुधार करने) की प्रवृत्ति होती है, जो इसे कम विवरणात्मक, पठनीयता को नुकसान पहुंचाती है।
क्रिस डोड

कैविटी के साथ पठनीयता और डीआरवाई सिद्धांतों के बारे में अच्छी बात यह है कि विधि-चाइनिंग किसी दिए गए तरीके के रिटर्न मूल्य के आत्मनिरीक्षण को रोकती है और / या श्रृंखला में प्रत्येक विधि से खाली सूचियों / सेटों और गैर-शून्य मानों का अनुमान लगाती है, जिससे एक गिरावट पैदा होती है। कई NPEs सिस्टम में मुझे अक्सर डिबग / फिक्स करना पड़ता है)।
डेरेल टेग्यूग

@ChrisDodd ऑटो पूरा होने के बारे में कभी नहीं सुना?
inf3rno

1
"मानव मस्तिष्क पाठ पुनरावृत्ति को पहचानने में बहुत अच्छा होता है अगर इसमें एक ही इंडेंटेशन हो" - यही पुनरावृत्ति के साथ समस्या है: यह मस्तिष्क को दोहराए जाने वाले पैटर्न पर ध्यान केंद्रित करने का कारण बनता है। तो पढ़ने के लिए और कोड को दोहराने के लिए आपको अपने दिमाग को दोहराने के पैटर्न से परे / देखने के लिए मजबूर करना होगा कि वास्तव में क्या चल रहा है, जो कि दोहराए जाने वाले पैटर्न के बीच अंतर है कि आपका मस्तिष्क चमकता है। यह कोड पुनरावृत्ति के लिए इतना बुरा क्यों दोहराव है।
क्रिस डोड

7

यह खतरनाक है क्योंकि आप उम्मीद से अधिक वस्तुओं पर निर्भर हो सकते हैं, जैसे कि तब आपका कॉल दूसरे वर्ग का उदाहरण देता है:

मैं एक उदाहरण दूंगा:

foodStore एक ऐसी वस्तु है जो कई खाद्य भंडारों से मिलकर बनती है। foodstore.getLocalStore () एक ऑब्जेक्ट देता है जो पैरामीटर के निकटतम स्टोर पर जानकारी रखता है। getPriceforProduct (कुछ भी) उस ऑब्जेक्ट का एक तरीका है।

इसलिए जब आप foodStore.getLocalStore (पैरामीटर्स) को कॉल करते हैं .getPriceforProduct (कुछ भी)

आप न केवल FoodStore पर निर्भर हैं, बल्कि आप LocalStore पर भी निर्भर हैं।

GetPriceforProduct (कुछ भी) कभी भी बदलना चाहिए, आपको न केवल फूडस्टोर बल्कि उस वर्ग को भी बदलने की आवश्यकता है जिसे अराजकता विधि कहा जाता है।

आपको कक्षाओं में ढीले युग्मन के लिए हमेशा लक्ष्य रखना चाहिए।

कहा जा रहा है, मैं व्यक्तिगत रूप से रूबी प्रोग्रामिंग करते समय उन्हें चेन करना पसंद करता हूं।


7

कई उपयोग विधि को मन में किसी भी पठनीयता संबंधी चिंताओं के बजाय सुविधा के रूप में उपयोग करते हैं। विधि जंजीर स्वीकार्य है अगर इसमें एक ही वस्तु पर समान कार्रवाई करना शामिल है - लेकिन केवल अगर यह वास्तव में पठनीयता बढ़ाता है, और न केवल कम कोड लिखने के लिए।

दुर्भाग्य से कई प्रश्न में दिए गए उदाहरणों के अनुसार विधि का उपयोग करते हैं। जबकि वे कर सकते हैं अभी भी पठनीय बनाया जा, वे दुर्भाग्य से कई वर्गों के बीच उच्च युग्मन उत्पन्न कर रहे हैं, इसलिए यह वांछनीय नहीं है।


6

यह थोड़े व्यक्तिपरक लगता है।

विधि जंजीर soemthing नहीं है कि स्वाभाविक रूप से बुरा या अच्छा imo है।

पठनीयता सबसे महत्वपूर्ण चीज है।

(यह भी विचार करें कि जंजीरों की बड़ी संख्या में होने से चीजें बहुत नाजुक हो जाएंगी अगर कुछ बदल जाए)


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

यदि यह उच्च युग्मन में परिणत होता है तो क्या यह स्वाभाविक रूप से बुरा नहीं होगा? अलग-अलग बयानों में श्रृंखला को तोड़ने से पठनीयता कम नहीं होती है।
aberrant80

1
इस बात पर निर्भर करता है कि आप कैसे हठधर्मी होना चाहते हैं। यदि यह कुछ अधिक पठनीय होता है तो यह बहुत सारी स्थितियों में बेहतर हो सकता है। इस दृष्टिकोण के साथ मुझे जो बड़ी समस्या है, वह यह है कि किसी वस्तु पर अधिकांश विधियाँ वस्तु के संदर्भ में ही लौट आएंगी, लेकिन अक्सर यह विधि एक बच्चे की वस्तु के संदर्भ को लौटा देगी, जिस पर आप अधिक विधियों की श्रृंखला बना सकते हैं। एक बार जब आप ऐसा करना शुरू कर देते हैं तो दूसरे कोडर के लिए यह मुश्किल हो जाता है कि क्या चल रहा है। इसके अलावा एक विधि की कार्यक्षमता में कोई भी परिवर्तन एक बड़े यौगिक बयान में डिबग करने के लिए एक दर्द होने जा रहा है।
जॉन निकोलस

6

चेनिंग के लाभ
अर्थात, जहाँ मुझे इसका उपयोग करना पसंद है

चाइनिंग का एक लाभ जो मैंने उल्लेख नहीं किया था, वह चर दीक्षा के दौरान इसका उपयोग करने की क्षमता थी, या किसी नई वस्तु को एक विधि से गुजरते समय, यह सुनिश्चित नहीं था कि यह खराब अभ्यास है या नहीं।

मुझे पता है कि यह आकस्मिक उदाहरण है लेकिन कहते हैं कि आपके पास निम्न वर्ग हैं

Public Class Location
   Private _x As Integer = 15
   Private _y As Integer = 421513

   Public Function X() As Integer
      Return _x
   End Function
   Public Function X(ByVal value As Integer) As Location
      _x = value
      Return Me
   End Function

   Public Function Y() As Integer
      Return _y
   End Function
   Public Function Y(ByVal value As Integer) As Location
      _y = value
      Return Me
   End Function

   Public Overrides Function toString() As String
      Return String.Format("{0},{1}", _x, _y)
   End Function
End Class

Public Class HomeLocation
   Inherits Location

   Public Overrides Function toString() As String
      Return String.Format("Home Is at: {0},{1}", X(), Y())
   End Function
End Class

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

  Dim loc As New HomeLocation()
  loc.X(1337)
  PrintLocation(loc)

लेकिन यह सिर्फ पढ़ने के लिए बहुत आसान नहीं है:

  PrintLocation(New HomeLocation().X(1337))

या, एक वर्ग के सदस्य के बारे में क्या?

Public Class Dummy
   Private _locA As New Location()
   Public Sub New()
      _locA.X(1337)
   End Sub
End Class

बनाम

Public Class Dummy
   Private _locC As Location = New Location().X(1337)
End Class

यह है कि मैं कैसे चाइनिंग का उपयोग कर रहा हूं, और आमतौर पर मेरे तरीके केवल कॉन्फ़िगरेशन के लिए हैं, इसलिए वे केवल 2 लाइनें लंबी हैं, फिर एक मान सेट करें Return Me। हमारे लिए यह एक पंक्ति में कोड को पढ़ने और समझने के लिए बहुत बड़ी लाइनों को साफ कर चुका है जो एक वाक्य की तरह पढ़ता है। कुछ इस तरह

New Dealer.CarPicker().Subaru.WRX.SixSpeed.TurboCharged.BlueExterior.GrayInterior.Leather.HeatedSeats

बनाम कुछ पसंद है

New Dealer.CarPicker(Dealer.CarPicker.Makes.Subaru
                   , Dealer.CarPicker.Models.WRX
                   , Dealer.CarPicker.Transmissions.SixSpeed
                   , Dealer.CarPicker.Engine.Options.TurboCharged
                   , Dealer.CarPicker.Exterior.Color.Blue
                   , Dealer.CarPicker.Interior.Color.Gray
                   , Dealer.CarPicker.Interior.Options.Leather
                   , Dealer.CarPicker.Interior.Seats.Heated)

चैनिंग की खोज
अर्थात, जहाँ मैं इसका उपयोग करना पसंद नहीं करता

जब रूटीन को पास करने के लिए बहुत सारे पैरामीटर होते हैं, तो मैं चेनिंग का उपयोग नहीं करता हूं, मुख्यतः क्योंकि लाइनें बहुत लंबी हो जाती हैं, और जैसा कि ओपी ने उल्लेख किया है कि आप भ्रमित कर सकते हैं जब आप अन्य वर्गों में से किसी एक को पास करने के लिए रूटीन कॉल कर रहे हैं पीछा करने की विधियाँ।

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

निष्कर्ष

जीवन और प्रोग्रामिंग में सब कुछ की तरह, चैनिंग न तो अच्छा है, न ही बुरा है यदि आप बुरे से बच सकते हैं तो चेनिंग एक महान लाभ हो सकता है।

मैं इन नियमों का पालन करने की कोशिश करता हूं।

  1. कोशिश करें कि कक्षाओं के बीच श्रृंखला न बनाएं
  2. खासतौर पर चैनिंग के लिए रूटीन बनाएं
  3. चैनिंग रूटीन में केवल एक ही काम करें
  4. पठनीयता में सुधार होने पर इसका उपयोग करें
  5. जब यह कोड को सरल बनाता है तो इसका उपयोग करें

6

विधि chaining जावा में सीधे उन्नत DSLs डिजाइन करने के लिए अनुमति दे सकते हैं। संक्षेप में, आप कम से कम इस प्रकार के DSL नियमों को मॉडल कर सकते हैं:

1. SINGLE-WORD
2. PARAMETERISED-WORD parameter
3. WORD1 [ OPTIONAL-WORD]
4. WORD2 { WORD-CHOICE-A | WORD-CHOICE-B }
5. WORD3 [ , WORD3 ... ]

इन इंटरफेस का उपयोग करके इन नियमों को लागू किया जा सकता है

// Initial interface, entry point of the DSL
interface Start {
  End singleWord();
  End parameterisedWord(String parameter);
  Intermediate1 word1();
  Intermediate2 word2();
  Intermediate3 word3();
}

// Terminating interface, might also contain methods like execute();
interface End {}

// Intermediate DSL "step" extending the interface that is returned
// by optionalWord(), to make that method "optional"
interface Intermediate1 extends End {
  End optionalWord();
}

// Intermediate DSL "step" providing several choices (similar to Start)
interface Intermediate2 {
  End wordChoiceA();
  End wordChoiceB();
}

// Intermediate interface returning itself on word3(), in order to allow for
// repetitions. Repetitions can be ended any time because this interface
// extends End
interface Intermediate3 extends End {
  Intermediate3 word3();
}

इन सरल नियमों के साथ, आप जटिल DSL जैसे SQL को सीधे जावा में लागू कर सकते हैं, जैसा कि jOOQ , एक पुस्तकालय जो मैंने बनाया है, द्वारा किया जाता है । यहां मेरे ब्लॉग से लिया गया एक जटिल जटिल SQL उदाहरण देखें :

create().select(
    r1.ROUTINE_NAME,
    r1.SPECIFIC_NAME,
    decode()
        .when(exists(create()
            .selectOne()
            .from(PARAMETERS)
            .where(PARAMETERS.SPECIFIC_SCHEMA.equal(r1.SPECIFIC_SCHEMA))
            .and(PARAMETERS.SPECIFIC_NAME.equal(r1.SPECIFIC_NAME))
            .and(upper(PARAMETERS.PARAMETER_MODE).notEqual("IN"))),
                val("void"))
        .otherwise(r1.DATA_TYPE).as("data_type"),
    r1.NUMERIC_PRECISION,
    r1.NUMERIC_SCALE,
    r1.TYPE_UDT_NAME,
    decode().when(
    exists(
        create().selectOne()
            .from(r2)
            .where(r2.ROUTINE_SCHEMA.equal(getSchemaName()))
            .and(r2.ROUTINE_NAME.equal(r1.ROUTINE_NAME))
            .and(r2.SPECIFIC_NAME.notEqual(r1.SPECIFIC_NAME))),
        create().select(count())
            .from(r2)
            .where(r2.ROUTINE_SCHEMA.equal(getSchemaName()))
            .and(r2.ROUTINE_NAME.equal(r1.ROUTINE_NAME))
            .and(r2.SPECIFIC_NAME.lessOrEqual(r1.SPECIFIC_NAME)).asField())
    .as("overload"))
.from(r1)
.where(r1.ROUTINE_SCHEMA.equal(getSchemaName()))
.orderBy(r1.ROUTINE_NAME.asc())
.fetch()

एक और अच्छा उदाहरण jRTF है , जो थोड़ा DSL सीधे जावा में RTF दस्तावेजों को व्यवस्थित करने के लिए डिज़ाइन किया गया है। एक उदाहरण:

rtf()
  .header(
    color( 0xff, 0, 0 ).at( 0 ),
    color( 0, 0xff, 0 ).at( 1 ),
    color( 0, 0, 0xff ).at( 2 ),
    font( "Calibri" ).at( 0 ) )
  .section(
        p( font( 1, "Second paragraph" ) ),
        p( color( 1, "green" ) )
  )
).out( out );

@ user877329: हां, इसका उपयोग किसी भी वस्तु उन्मुख प्रोग्रामिंग भाषा में किया जा सकता है, जो इंटरफेस और उप-प्रकार बहुरूपता जैसे कुछ जानता है
लुकास ईडर

4

अधिकांश मामलों के लिए विधि का पीछा करना एक नवीनता हो सकती है, लेकिन मुझे लगता है कि इसकी जगह है। एक उदाहरण CodeIgniter के सक्रिय रिकॉर्ड उपयोग में पाया जा सकता है :

$this->db->select('something')->from('table')->where('id', $id);

यह एक बहुत क्लीनर दिखता है (और मेरी राय में अधिक समझ में आता है):

$this->db->select('something');
$this->db->from('table');
$this->db->where('id', $id);

यह वास्तव में व्यक्तिपरक है; सबकी अपनी-अपनी राय है।


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

3

मुझे लगता है कि प्राथमिक गिरावट यह सोच रही है कि यह सामान्य रूप से एक वस्तु उन्मुख दृष्टिकोण है जब वास्तव में यह कुछ और की तुलना में कार्यात्मक प्रोग्रामिंग दृष्टिकोण से अधिक है।

मेरे द्वारा उपयोग किए जाने वाले मुख्य कारण दोनों पठनीयता के लिए हैं और मेरे कोड को चरों द्वारा निस्तारित करने से रोकते हैं।

मुझे वास्तव में समझ में नहीं आता कि दूसरे क्या बात कर रहे हैं जब वे कहते हैं कि यह पठनीयता को नुकसान पहुंचाता है। यह मेरे द्वारा उपयोग की जाने वाली प्रोग्रामिंग का सबसे संक्षिप्त और सामंजस्यपूर्ण रूप है।

यह भी:

। ConvertTextToVoice.LoadText ( "source.txt") ConvertToVoice ( "destination.wav");

यह है कि मैं आमतौर पर इसका उपयोग कैसे करूंगा। मापदंडों की श्रृंखला x संख्या का उपयोग करना यह नहीं है कि मैं आमतौर पर इसका उपयोग कैसे करता हूं। अगर मैं एक विधि कॉल में x के मापदंडों को x संख्या में रखना चाहता हूं तो मैं पैरामेट्स सिंटैक्स का उपयोग करूंगा :

सार्वजनिक शून्य फ़ू (परम वस्तु [] आइटम)

और टाइप के आधार पर ऑब्जेक्ट्स को कास्ट करें या केवल अपने उपयोग के मामले के आधार पर एक डेटाटाइप सरणी या संग्रह का उपयोग करें।


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

हाँ, आप सही हैं यह एक राज्य-कम हेरफेर है, सिवाय इसके कि मैं आमतौर पर एक नई वस्तु नहीं बनाता हूं, लेकिन इसे उपलब्ध सेवा बनाने के लिए निर्भरता इंजेक्शन का उपयोग करें। और हां स्टेटफुल यूज के मामले वो नहीं हैं, जो मुझे लगता है कि मेथड चेनिंग का मकसद था। एकमात्र अपवाद जो मैं देख रहा हूं, यदि आप DI सेवा को कुछ सेटिंग्स के साथ आरंभीकृत करते हैं और किसी प्रकार की वॉचडॉग की स्थिति की निगरानी करने के लिए किसी तरह की COM सेवा की तरह है। सिर्फ IMHO।
शेन थार्नडाइक

2

मैं सहमत हूं, मैंने अपने पुस्तकालय में एक धाराप्रवाह इंटरफ़ेस लागू करने के तरीके को बदल दिया है।

इससे पहले:

collection.orderBy("column").limit(10);

उपरांत:

collection = collection.orderBy("column").limit(10);

"पहले" कार्यान्वयन में कार्यों ने वस्तु को संशोधित किया और अंदर समाप्त हो गया return this। मैंने उसी प्रकार की एक नई वस्तु को वापस करने के लिए कार्यान्वयन को बदल दिया ।

इस परिवर्तन के लिए मेरा तर्क :

  1. रिटर्न वैल्यू का फंक्शन से कोई लेना-देना नहीं था, यह शुद्ध रूप से चैनिंग भाग का समर्थन करने के लिए था, यह OOP के अनुसार एक शून्य फ़ंक्शन होना चाहिए था।

  2. सिस्टम लाइब्रेरियों में विधि का पालन भी इसे उसी तरह से लागू करता है (जैसे लाइनक या स्ट्रिंग):

    myText = myText.trim().toUpperCase();
    
  3. मूल वस्तु बरकरार है, एपीआई उपयोगकर्ता को यह तय करने की अनुमति देता है कि इसके साथ क्या करना है। यह इसके लिए अनुमति देता है:

    page1 = collection.limit(10);
    page2 = collection.offset(10).limit(10);
    
  4. एक कॉपी कार्यान्वयन का उपयोग वस्तुओं के निर्माण के लिए भी किया जा सकता है:

    painting = canvas.withBackground('white').withPenSize(10);
    

    जहां setBackground(color)फ़ंक्शन आवृत्ति को बदलता है और कुछ भी नहीं लौटाता है (जैसे कि माना जाता है)

  5. कार्यों का व्यवहार अधिक विधेय है (बिंदु 1 और 2 देखें)।

  6. लघु चर नाम का उपयोग करके कोड-अव्यवस्था को भी कम कर सकते हैं, मॉडल पर एपीआई के लिए मजबूर किए बिना।

    var p = participant; // create a reference
    p.addSchedule(events[1]);p.addSchedule(events[2]);p.setStatus('attending');p.save()
    

निष्कर्ष:
मेरी राय में एक धाराप्रवाह इंटरफ़ेस जो एक return thisकार्यान्वयन का उपयोग करता है, बस गलत है।


1
लेकिन प्रत्येक कॉल के लिए एक नया उदाहरण नहीं लौटाया जा सकता है, जिससे ओवरहेड का थोड़ा सा हिस्सा पैदा होता है, खासकर यदि आप बड़ी वस्तुओं का उपयोग कर रहे हैं? कम से कम गैर-प्रबंधित भाषाओं के लिए।
एपैरॉन

@ एपिरॉन प्रदर्शन-वार यह निश्चित रूप से return thisप्रबंधित या अन्य के लिए तेज़ है । यह मेरी राय है कि यह एक "नहीं प्राकृतिक" तरीके से एक धाराप्रवाह एपीआई प्राप्त करता है। (जोड़ा गया कारण 6: एक गैर-धाराप्रवाह विकल्प दिखाने के लिए, जिसमें ओवरहेड / अतिरिक्त-कार्यक्षमता नहीं है)
बॉब फेन्जर

मैं आपसे सहमत हुँ। ज्यादातर एक DSL की अंतर्निहित स्थिति को अछूता छोड़ना और हर विधि कॉल पर नई वस्तुओं को वापस करना बेहतर होता है, इसके बजाय ... मैं उत्सुक हूं: आपने उस पुस्तकालय का क्या उल्लेख किया है?
लुकास एडर

1

यहाँ पूरी तरह से छूटी हुई बात यह है कि यह विधि chaining DRY की अनुमति देता है । यह "के साथ" (जो कुछ भाषाओं में खराब रूप से लागू किया गया है) के लिए एक प्रभावी स्टैंड-इन है।

A.method1().method2().method3(); // one A

A.method1();
A.method2();
A.method3(); // repeating A 3 times

यह एक ही कारण के लिए मायने रखता है DRY हमेशा मायने रखता है; यदि A त्रुटि करता है, और इन ऑपरेशनों को B पर किया जाना है, तो आपको केवल 1 स्थान पर अपडेट करने की आवश्यकता है, 3 नहीं।

व्यावहारिक रूप से, इस उदाहरण में लाभ छोटा है। फिर भी, थोड़ा कम टाइपिंग, एक अधिक मजबूत (DRY), मैं इसे ले जाऊंगा।


14
स्रोत कोड में एक चर नाम को दोहराने का DRY सिद्धांत से कोई लेना-देना नहीं है। DRY में कहा गया है कि "ज्ञान के प्रत्येक टुकड़े में एक प्रणाली के भीतर एक एकल, अस्पष्ट, आधिकारिक प्रतिनिधित्व होना चाहिए", या अन्य शब्दों में, ज्ञान की पुनरावृत्ति ( पाठ की पुनरावृत्ति नहीं ) से बचें ।
पेड्रोनामेल

4
यह सबसे निश्चित रूप से दोहराव है जो सूखे का उल्लंघन करता है। चर नामों को (अनावश्यक रूप से) दोहराने से सभी बुराई उसी तरह से होती हैं, जैसे कि सूखे के अन्य रूप: यह अधिक निर्भरता और अधिक काम पैदा करता है। उपरोक्त उदाहरण में, यदि हम A का नाम बदलते हैं, तो गीले संस्करण को 3 परिवर्तनों की आवश्यकता होगी और तीनों में से किसी के भी छूट जाने पर त्रुटियों को समाप्त करने का कारण होगा।
अनफनी १५'१२

1
मैं इस समस्या को इस उदाहरण में नहीं देख सकता, क्योंकि सभी विधि कॉल एक दूसरे के करीब हैं। साथ ही, यदि आप किसी चर के नाम को एक पंक्ति में बदलना भूल जाते हैं, तो संकलक एक त्रुटि लौटाएगा और यह आपके प्रोग्राम को चलाने से पहले ठीक किया जाएगा। इसके अलावा, एक चर का नाम इसके घोषणा के दायरे तक सीमित है। जब तक यह चर वैश्विक नहीं है, जो पहले से ही एक बुरा प्रोग्रामिंग अभ्यास है। IMO, DRY कम टाइपिंग के बारे में नहीं है, बल्कि चीजों को अलग रखने के बारे में है।
पेड्रोमानोएल

"कंपाइलर" एक त्रुटि लौटा सकता है, या हो सकता है कि आप PHP या JS का उपयोग कर रहे हों और इस स्थिति को हिट करने पर दुभाषिया केवल रनटाइम पर एक त्रुटि का उत्सर्जन कर सकता है।
अनफनी

1

मैं आम तौर पर विधि से घृणा करता हूं क्योंकि मुझे लगता है कि इससे पठनीयता बिगड़ती है। कॉम्पैक्टनेस अक्सर पठनीयता के साथ भ्रमित होता है, लेकिन वे समान शब्द नहीं हैं। यदि आप एक ही बयान में सब कुछ करते हैं तो वह कॉम्पैक्ट है, लेकिन यह कई बयानों में करने की तुलना में कम पठनीय (पालन करने के लिए कठिन) है। जैसा कि आपने देखा कि जब तक आप यह गारंटी नहीं दे सकते कि उपयोग किए गए तरीकों का रिटर्न वैल्यू एक ही है, तब मेथड चेनिंग भ्रम का स्रोत होगा।

1.)

participant
    .addSchedule(events[1])
    .addSchedule(events[2])
    .setStatus('attending')
    .save();

बनाम

participant.addSchedule(events[1]);
participant.addSchedule(events[2]);
participant.setStatus('attending');
participant.save()

2.)

participant
    .getSchedule('monday')
        .saveTo('monnday.file');

बनाम

mondaySchedule = participant.getSchedule('monday');
mondaySchedule.saveTo('monday.file');

3.)

participant
    .attend(event)
    .setNotifications('silent')
    .getSocialStream('twitter')
        .postStatus('Joining '+event.name)
        .follow(event.getSocialId('twitter'));

बनाम

participant.attend(event);
participant.setNotifications('silent')
twitter = participant.getSocialStream('twitter')
twitter.postStatus('Joining '+event.name)
twitter.follow(event.getSocialId('twitter'));

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

मुझे लगता है कि एकमात्र ऐसी जगह जहां इस तरह की चैनिंग उपयोगी हो सकती है, CLI में पाइपिंग स्ट्रीम या SQL में एक साथ कई क्वेश्चन को शामिल करना। दोनों के कई बयानों की कीमत है। लेकिन अगर आप जटिल समस्याओं को हल करना चाहते हैं, तो आप मूल्य का भुगतान करने वाले लोगों के साथ भी समाप्त हो जाएंगे और चर का उपयोग करके कई बयानों में कोड लिख सकते हैं या बैश स्क्रिप्ट और संग्रहीत कार्यविधियाँ या दृश्य लिख सकते हैं।

DRY व्याख्याओं के अनुसार: "ज्ञान की पुनरावृत्ति (पाठ की पुनरावृत्ति नहीं) से बचें।" और "कम टाइप करें, टेक्स्ट भी न दोहराएं।", पहला जो सिद्धांत का वास्तव में अर्थ रखता है, लेकिन दूसरा एक आम गलतफहमी है क्योंकि बहुत से लोग इस बात को नहीं समझ सकते हैं जैसे कि "हर ज्ञान का एक टुकड़ा होना चाहिए। एक प्रणाली के भीतर आधिकारिक प्रतिनिधित्व "। दूसरा हर कीमत पर कॉम्पैक्टनेस है, जो इस परिदृश्य में टूट जाता है, क्योंकि यह पठनीयता को खराब करता है। जब आप बंधे हुए संदर्भों के बीच कोड की नकल करते हैं, तो डीडीडी द्वारा पहली व्याख्या टूट जाती है, क्योंकि उस परिदृश्य में ढीली युग्मन अधिक महत्वपूर्ण है।


0

अच्छा:

  1. यह तुकांत है, फिर भी आपको सुरुचिपूर्ण ढंग से एक पंक्ति में अधिक डालने की अनुमति देता है।
  2. आप कभी-कभी एक चर के उपयोग से बच सकते हैं, जो कभी-कभी उपयोगी हो सकता है।
  3. यह बेहतर प्रदर्शन कर सकता है।

खराब:

  1. आप रिटर्न को लागू कर रहे हैं, अनिवार्य रूप से वस्तुओं पर उन तरीकों के लिए कार्यक्षमता जोड़ रहे हैं जो वास्तव में उन तरीकों का हिस्सा नहीं हैं जो करने के लिए हैं। यह कुछ ऐसा है जो आपके पास पहले से ही कुछ बाइट्स को बचाने के लिए है।
  2. यह संदर्भ स्विच को छुपाता है जब एक श्रृंखला दूसरे की ओर ले जाती है। आप इसे प्राप्तकर्ताओं के साथ प्राप्त कर सकते हैं, सिवाय इसके कि संदर्भ स्विच होने पर यह बहुत स्पष्ट हो।
  3. कई लाइनों पर जंजीर बदसूरत दिखती है, इंडेंटेशन के साथ अच्छी तरह से नहीं खेलती है और कुछ ऑपरेटर को भ्रम की स्थिति पैदा कर सकती है (विशेष रूप से एएसआई के साथ भाषाओं में)।
  4. यदि आप कुछ और शुरू करना चाहते हैं जो एक जंजीर विधि के लिए उपयोगी है, तो आप संभवतः इसे ठीक करने के लिए एक कठिन समय लेने जा रहे हैं या इसके साथ और अधिक समस्याएं उठा सकते हैं।
  5. आप एक इकाई के लिए नियंत्रण को लोड कर रहे हैं जिसे आप सामान्य रूप से सुविधाजनक तरीके से पूरी तरह से ऑफ़लोड नहीं करेंगे, यहां तक ​​कि कड़ाई से टाइप की गई भाषाओं में गलतियों के कारण भी इसका हमेशा पता नहीं लगाया जा सकता है।
  6. यह बदतर प्रदर्शन कर सकता है।

सामान्य:

एक अच्छा तरीका यह है कि सामान्य तौर पर जब तक स्थितियां उत्पन्न नहीं होतीं या विशिष्ट मॉड्यूल विशेष रूप से इसके अनुकूल नहीं होंगे, तब तक चेनिंग का उपयोग नहीं किया जाएगा।

चेनिंग कुछ मामलों में पठनीयता को काफी गंभीर रूप से चोट पहुंचा सकता है, खासकर जब बिंदु 1 और 2 में वजन होता है।

आरोप लगाने पर इसका दुरुपयोग किया जा सकता है, जैसे कि एक अन्य दृष्टिकोण (उदाहरण के लिए एक सरणी पास करना) या विचित्र तरीकों (parent.setSomething ()। GetChild ()। SetSomething () .PPentent ()। SetSomething ()) में मिश्रण करने के तरीकों के बजाय।


0

जनमत जवाब

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

कुछ सवाल:

  • क्या श्रृंखला में विधियाँ एक नई वस्तु लौटाती हैं, या एक ही वस्तु उत्परिवर्तित होती है?
  • क्या श्रृंखला के सभी तरीके एक ही प्रकार के हैं?
  • यदि नहीं, तो कैसे इंगित किया जाता है जब श्रृंखला में एक प्रकार बदलता है?
  • क्या अंतिम विधि द्वारा लौटाए गए मूल्य को सुरक्षित रूप से त्याग दिया जा सकता है?

डिबगिंग, अधिकांश भाषाओं में, वास्तव में जंजीरों से सख्त हो सकती है। भले ही श्रृंखला में प्रत्येक चरण अपनी स्वयं की रेखा पर हो (जो कि जंजीर लगाने के उद्देश्य को पराजित करता है), प्रत्येक चरण के बाद लौटे मूल्य का निरीक्षण करना कठिन हो सकता है, विशेष रूप से गैर-उत्परिवर्तन विधियों के लिए।

संकलन समय भाषा और संकलक के आधार पर धीमा हो सकता है, क्योंकि अभिव्यक्ति को हल करने के लिए और अधिक जटिल हो सकता है।

मेरा मानना ​​है कि हर चीज की तरह, चेनिंग एक अच्छा समाधान है जो कुछ परिदृश्य में काम कर सकता है। इसका उपयोग सावधानी के साथ किया जाना चाहिए, निहितार्थ को समझना चाहिए, और कुछ को चेन तत्वों की संख्या को सीमित करना चाहिए।


0

टाइप की गई भाषाओं में (यह कमी autoया समतुल्य) यह कार्यान्वयनकर्ता को मध्यवर्ती परिणामों के प्रकारों को घोषित करने से बचाता है।

import Participant
import Schedule

Participant participant = new Participant()
... snip...
Schedule s = participant.getSchedule(blah)
s.saveTo(filename)

लंबी श्रृंखलाओं के लिए आप कई अलग-अलग मध्यवर्ती प्रकारों के साथ काम कर सकते हैं, आपको उनमें से प्रत्येक को घोषित करने की आवश्यकता होगी।

मेरा मानना ​​है कि यह दृष्टिकोण वास्तव में जावा में विकसित हुआ है जहां ए) सभी फ़ंक्शन कॉल सदस्य फ़ंक्शन चालान हैं, और बी) स्पष्ट प्रकार की आवश्यकता होती है। बेशक कुछ खोजबीनों को देखते हुए, यहां व्यापार बंद है, लेकिन कुछ स्थितियों में कुछ लोगों को इसके लायक लगता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.