सी # में धाराप्रवाह कब जाना है?


78

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

निष्कर्ष:

अब तक के जवाबों से अंगूठे के कुछ अच्छे नियम:

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

यहाँ इसका एक उदाहरण है कि आधुनिक सुविधाओं से मेरा मतलब है कि इसकी आवश्यकता कम महसूस होती है। उदाहरण के लिए ले लो (शायद खराब उदाहरण) धाराप्रवाह इंटरफ़ेस जो मुझे एक कर्मचारी बनाने की अनुमति देता है जैसे:

Employees.CreateNew().WithFirstName("Peter")
                     .WithLastName("Gibbons")
                     .WithManager()
                          .WithFirstName("Bill")
                          .WithLastName("Lumbergh")
                          .WithTitle("Manager")
                          .WithDepartment("Y2K");

आसानी से शुरुआती के साथ लिखा जा सकता है जैसे:

Employees.Add(new Employee()
              {
                  FirstName = "Peter",
                  LastName = "Gibbons",
                  Manager = new Employee()
                            {
                                 FirstName = "Bill",
                                 LastName = "Lumbergh",
                                 Title = "Manager",
                                 Department = "Y2K"
                            }
              });

मैं इस उदाहरण में कंस्ट्रक्टरों में नामित मापदंडों का उपयोग कर सकता था।


1
अच्छा सवाल है, लेकिन मुझे लगता है कि इसका अधिक विकी सवाल है
Ivo

आपके प्रश्न को "धाराप्रवाह-निरबनेट" टैग किया गया है। तो क्या आप यह तय करने की कोशिश कर रहे हैं कि धाराप्रवाह इंटरफ़ेस बनाना है, या धाराप्रवाह nberberate बनाम XML कॉन्फ़िगरेशन का उपयोग करना है या नहीं ?
इल्या कोगन

1
प्रोग्रामर के पास माइग्रेट करने के लिए वोट दिया गया।ई
मैट एलेन

@ इलिया कोगन, मुझे लगता है कि यह वास्तव में "धाराप्रवाह-इंटरफ़ेस" है जो धाराप्रवाह इंटरफ़ेस पैटर्न के लिए एक सामान्य टैग है। यह सवाल निबर्नेट के संबंध में नहीं है, लेकिन जैसा कि आपने केवल एक धाराप्रवाह इंटरफ़ेस बनाने के लिए कहा था। धन्यवाद।

1
इस पोस्ट ने मुझे सी में इस पैटर्न का उपयोग करने के तरीके के बारे में सोचने के लिए प्रेरित किया। मेरा प्रयास कोड समीक्षा बहन साइट पर पाया जा सकता है ।
ओटो

जवाबों:


28

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

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

धाराप्रवाह इंटरफेस संदर्भ के बारे में अधिक हैं, और वस्तुओं को कॉन्फ़िगर करने के तरीकों से बहुत अधिक हैं। जैसा कि आप ऊपर दिए गए लिंक में देख सकते हैं, मैंने इसे प्राप्त करने के लिए धाराप्रवाह ईश एपीआई का उपयोग किया है:

  1. संदर्भ (इसलिए जब आप आमतौर पर एक ही चीज़ के साथ अनुक्रम में कई कार्य करते हैं, तो आप अपने संदर्भ को घोषित किए बिना क्रियाओं को श्रृंखलाबद्ध कर सकते हैं)।
  2. खोजे जाने (जब आप के पास जाओ objectA.तो IntelliSense आप संकेत के बहुत सारे देता है। ऊपर मेरे मामले में, plm.Led.आप में निर्मित एलईडी, और नियंत्रित करने के लिए सभी विकल्प देता है plm.Network.चीजें आप नेटवर्क इंटरफेस के साथ क्या कर सकते हैं देता है। plm.Network.X10.आप के सबसेट देता है X10 उपकरणों के लिए नेटवर्क एक्शन। आपको यह कंस्ट्रक्टर इनिशियलाइज़र के साथ नहीं मिलेगा (जब तक कि आपको हर अलग-अलग प्रकार के एक्शन के लिए ऑब्जेक्ट नहीं बनाना है, जो मुहावरा नहीं है)।
  3. परावर्तन (ऊपर उदाहरण में उपयोग नहीं किया गया) - LINQ अभिव्यक्ति में पारित करने और इसे हेरफेर करने की क्षमता एक बहुत शक्तिशाली उपकरण है, विशेष रूप से कुछ हेल्पर एपीआई के मैंने यूनिट परीक्षणों के लिए बनाया है। मैं एक प्रॉपर्टी गेट्टर एक्सप्रेशन में पास हो सकता हूं, उपयोगी भावों का एक पूरा गुच्छा तैयार कर सकता हूं, उन्हें संकलित कर सकता हूं, या यहां तक ​​कि मेरे संदर्भ को सेट करने के लिए प्रॉपर्टी गेट्टर का उपयोग कर सकता हूं।

एक चीज जो मैं आमतौर पर करता हूं:

test.Property(t => t.SomeProperty)
    .InitializedTo(string.Empty)
    .CantBeNull() // tries to set to null and Asserts ArgumentNullException
    .YaddaYadda();

मैं यह नहीं देखता कि आप एक धाराप्रवाह इंटरफ़ेस के बिना ऐसा कैसे कर सकते हैं।

संपादित करें 2 : आप वास्तव में दिलचस्प पठनीयता सुधार भी कर सकते हैं, जैसे:

test.ListProperty(t => t.MyList)
    .ShouldHave(18).Items()
    .AndThenAfter(t => testAddingItemToList(t))
    .ShouldHave(19).Items();

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

विस्तारित उत्तर के लिए धन्यवाद। मुझे लगता है कि आपने अंगूठे के दो अच्छे नियमों को रेखांकित किया है: 1) जब आपके पास कई कॉल हैं, जो संदर्भ के 'पास-थ्रू' से लाभान्वित करते हैं, तो धाराप्रवाह का उपयोग करें। 2) फ़्लटर के बारे में सोचें जब आपके पास बसने वालों की तुलना में अधिक कॉल हैं।
एंड्रयू हैनॉन

2
@ नहीं, मुझे इस उत्तर में "बसने वालों से अधिक कॉल" के बारे में कुछ भी दिखाई नहीं देता है। क्या आप "कोड [के बारे में] उसके कथन से भ्रमित हो गए हैं कि यह बहुत अधिक पढ़ा गया है"? यह संपत्ति पाने वालों / बसने वालों के बारे में नहीं है, यह मनुष्यों के लिए कोड पढ़ने वाले मनुष्यों के बारे में है - कोड लिखने वाले मनुष्यों के बारे में - कोड को मनुष्यों के लिए पढ़ना आसान बनाते हैं, क्योंकि हम आम तौर पर कोड की एक पंक्ति को बहुत अधिक बार पढ़ते हैं, जबकि हम इसे संशोधित करते हैं।
जो व्हाइट

@ जो व्हाइट, मुझे शायद 'एक्शन' के लिए अपने 'कॉल' शब्द की पुष्टि करनी चाहिए। लेकिन विचार अभी भी खड़ा है। धन्यवाद।
एंड्रयू हनलन

परीक्षण के लिए प्रतिबिंब बुराई है!
एड्रोनियस

24

स्कॉट हैनेलमैन ने जोनाथन कार्टर के साथ अपने पॉडकास्ट हंसेलमिन्यूट्स के एपिसोड 260 में इस बारे में बात की । वे बताते हैं कि एक धाराप्रवाह इंटरफ़ेस एक एपीआई पर यूआई की तरह अधिक है। आपको केवल पहुंच बिंदु के रूप में एक धाराप्रवाह इंटरफ़ेस प्रदान नहीं करना चाहिए, बल्कि इसे "नियमित एपीआई इंटरफ़ेस" के शीर्ष पर किसी प्रकार के कोड-यूआई के रूप में प्रदान करना चाहिए।

जोनाथन कार्टर भी अपने ब्लॉग पर एपीआई डिजाइन के बारे में थोड़ी बात करते हैं ।


जानकारी लिंक के लिए बहुत धन्यवाद और एपीआई के शीर्ष पर यूआई इसे देखने का एक अच्छा तरीका है।
एंड्रयू हनलन

14

धाराप्रवाह इंटरफेस आपके कोड के संदर्भ में प्रदान करने के लिए बहुत शक्तिशाली विशेषताएं हैं, जब "सही" तर्क के साथ डॉन।

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

मैं धाराप्रवाह इंटरफेस बनाते समय एक सामान्य "पैटर्न" बनने के बारे में सोचता हूं, जहां आप अपने सभी धाराप्रवाह तरीकों का नाम "-something" के साथ रखते हैं, क्योंकि यह अपने संदर्भ के संभावित अच्छे एपीआई इंटरफ़ेस को लूटता है, और इसलिए इसका आंतरिक मूल्य ।

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


उत्तर के लिए धन्यवाद, एक अच्छी तरह से सोचा प्रतिक्रिया देने में कभी देर नहीं हुई है।
एंड्रयू हनलॉन

मैं तरीकों के लिए 'उपसर्ग' के साथ बुरा नहीं मानता। यह उन्हें अन्य तरीकों से अलग करता है जो किसी वस्तु को जमाने के लिए वापस नहीं करते हैं। उदाहरण के लिए position.withX(5)बनामposition.getDistanceToOrigin()
LegendLength

5

प्रारंभिक नोट: मैं प्रश्न में एक धारणा के साथ समस्या ले रहा हूं, और उस से मेरे विशिष्ट निष्कर्ष (इस पोस्ट के अंत में) आकर्षित करता हूं। क्योंकि यह संभवतः एक पूर्ण, उत्तर देने के लिए नहीं बनाता है, मैं इसे सीडब्ल्यू के रूप में चिह्नित कर रहा हूं।

Employees.CreateNew().WithFirstName("Peter")…

आसानी से शुरुआती के साथ लिखा जा सकता है जैसे:

Employees.Add(new Employee() { FirstName = "Peter",  });

मेरी नजर में, इन दो संस्करणों का मतलब और अलग-अलग चीजें करना चाहिए।

  • गैर-धाराप्रवाह संस्करण के विपरीत, धाराप्रवाह संस्करण इस तथ्य को छिपाता है कि नया Employeeभी Addसंग्रह में एड है Employees- यह केवल सुझाव देता है कि एक नया ऑब्जेक्ट Createडी है।

  • का अर्थ ….WithX(…)अस्पष्ट है, विशेष रूप से एफ # से आने वाले लोगों के लिए, जिसमें withऑब्जेक्ट एक्सप्रेशन के लिए एक कीवर्ड है : वे obj.WithX(x)एक नई वस्तु के रूप में व्याख्या कर सकते हैं objजो objउससे प्राप्त की जा रही है X, अपनी संपत्ति को छोड़कर समान है , जिसका मूल्य है x। दूसरी ओर, दूसरे संस्करण के साथ, यह स्पष्ट है कि कोई भी व्युत्पन्न वस्तु नहीं बनाई गई है, और यह कि सभी गुण मूल वस्तु के लिए निर्दिष्ट हैं।

….WithManager().With
  • इसका ….With…अभी तक एक और अर्थ है: संपत्ति के प्रारंभिककरण के "फ़ोकस" को किसी भिन्न ऑब्जेक्ट पर स्विच करना। यह तथ्य कि आपके धाराप्रवाह एपीआई के लिए दो अलग-अलग अर्थ हैं, Withयह सही ढंग से व्याख्या करना मुश्किल बना रहा है कि क्या हो रहा है ... शायद यही कारण है कि आपने उस कोड के इच्छित अर्थ को प्रदर्शित करने के लिए अपने उदाहरण में इंडेंटेशन का उपयोग किया। यह इस तरह स्पष्ट होगा:

    (employee).WithManager(Managers.CreateNew().WithFirstName("Bill").…)
    //                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    //                     value of the `Manager` property appears inside the parentheses,
    //                     like with `WithName`, where the `Name` is also inside the parentheses 

निष्कर्ष:new T { X = x } एक धाराप्रवाह एपीआई ( Ts.CreateNew().WithX(x)) के साथ "छिपाना" एक सरल-पर्याप्त भाषा सुविधा है, जाहिर है, लेकिन:

  1. ध्यान रखा जाना चाहिए कि परिणामी धाराप्रवाह कोड के पाठक अभी भी समझते हैं कि यह वास्तव में क्या करता है। यही है, धाराप्रवाह एपीआई अर्थ में पारदर्शी होना चाहिए, और अस्पष्ट होना चाहिए। इस तरह के एपीआई को डिजाइन करना अनुमान से अधिक काम हो सकता है (यह आसानी से उपयोग और स्वीकृति के लिए परीक्षण किया जा सकता है), और / या…

  2. इसे डिजाइन करना आवश्यक से अधिक काम हो सकता है: इस उदाहरण में, धाराप्रवाह एपीआई अंतर्निहित एपीआई (एक भाषा सुविधा) पर बहुत कम "उपयोगकर्ता आराम" जोड़ता है। कोई कह सकता है कि एक धाराप्रवाह एपीआई को अंतर्निहित एपीआई / भाषा की सुविधा को "उपयोग करने में आसान" बनाना चाहिए; अर्थात्, यह प्रोग्रामर को काफी मात्रा में प्रयास करने से बचाना चाहिए। यदि यह एक ही बात लिखने का एक और तरीका है, तो यह संभवतः इसके लायक नहीं है, क्योंकि यह प्रोग्रामर के जीवन को आसान नहीं बनाता है, लेकिन केवल डिजाइनर के काम को कठिन बनाता है (निष्कर्ष # 1 ठीक ऊपर देखें)।

  3. ऊपर दोनों बिंदु चुपचाप मानते हैं कि धाराप्रवाह एपीआई एक मौजूदा एपीआई या भाषा सुविधा पर एक परत है। यह धारणा एक और अच्छी दिशानिर्देश हो सकती है: एक धाराप्रवाह एपीआई कुछ करने का एक अतिरिक्त तरीका हो सकता है, केवल रास्ता नहीं। यही है, एक धाराप्रवाह एपीआई को "ऑप्ट-इन" विकल्प के रूप में पेश करना एक अच्छा विचार हो सकता है।


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

2

मुझे धाराप्रवाह शैली पसंद है, यह बहुत स्पष्ट रूप से इरादे व्यक्त करता है। आपके पास होने वाले ऑब्जेक्ट इंटेलाइज़र उदाहरण के साथ, आपके पास उस सिंटैक्स का उपयोग करने के लिए सार्वजनिक संपत्ति होना चाहिए, आप धाराप्रवाह शैली के साथ नहीं हैं। यह कहते हुए कि, आपके उदाहरण से आप जनता में ज्यादा नहीं बसते हैं क्योंकि आप लगभग जावा-एस्क सेट / विधि की शैली प्राप्त कर चुके हैं।

जो मुझे दूसरे बिंदु पर लाता है, मुझे यकीन नहीं है कि यदि आप जिस तरह से आपके पास हैं, मैं धाराप्रवाह शैली का उपयोग करूँगा, बहुत सारी संपत्ति बसने वालों के साथ, मैं शायद इसके लिए दूसरे संस्करण का उपयोग करूँगा, मुझे यह बेहतर लगता है जब आप कई क्रियाओं को एक साथ करने के लिए या सेटिंग्स के बजाय कम से कम बहुत सी क्रियाओं को करना है।


आपके उत्तर के लिए धन्यवाद, मुझे लगता है कि आपने अंगूठे का एक अच्छा नियम व्यक्त किया है: धाराप्रवाह कई बसने वाले कॉल के साथ बेहतर है।
एंड्रयू हैनॉन

1

मैं धाराप्रवाह शब्द से परिचित नहीं था , लेकिन यह मुझे कुछ APIs की याद दिलाता है, जिनका मैंने LINQ उपयोग किया है ।

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

शायद एक ठोस उदाहरण के साथ अपने उत्तर को स्पष्ट करें कि आपके द्वारा उल्लिखित आधुनिक सुविधाओं में से एक का उपयोग करके एक धाराप्रवाह इंटरफ़ेस कैसे बदला जा सकता है।


1
उत्तर के लिए धन्यवाद - मैंने अपने प्रश्न को स्पष्ट करने में मदद करने के लिए एक मूल उदाहरण जोड़ा है।
एंड्रयू हनलन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.