शब्द (या "पैटर्न")? "कुछ के लिए अगर यह पहले से ही नहीं किया है" [बंद]


54

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

प्रश्न : क्या एक विधि की अवधारणा के पीछे एक प्रलेखित डिज़ाइन पैटर्न है जो एक नो-ऑप है यदि आवश्यक कार्रवाई पहले से ही प्रभावी है? या, यदि कोई पैटर्न नहीं है, तो क्या इसका कोई नाम है? और यदि नहीं, तो क्या इस तरीके से लिखने पर विचार करने के लिए बहुत जटिल है?


6
कैशिंग जैसा लगता है - और इसे अक्सर जटिल माना जाता है (यह भी देखें कि मैं $ {कुछ} को $ {किसी को कैसे
समझाऊं

8
आपको 3 अलग-अलग उत्तर मिले, लेकिन सबसे अच्छा जवाब होगा, उन सभी को लागू करें: मूल फ़ंक्शन का नाम बदलें, इसके कोड को दो कार्यों में विभाजित करें (जहां अब दोनों में से एक को नाम मिलता है startHttpServer), और हां, शब्द "idempotent" यहां लागू होता है कुंआ।
डॉक ब्राउन

8
आपके सहकर्मी किस तरह के जवाबी सबूत देते हैं? क्या आप इसे लिंक प्रदान कर सकते हैं?
रॉबर्ट हार्वे

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

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

जवाबों:


127

NickWilliams के रूप में पहले से ही कहा है : अवधारणा ओ पी का वर्णन करता है कहा जाता है idempotent (संज्ञा Idempotency )। यह वास्तव में सामान्य अभ्यास है, विशेष रूप से उच्च-स्तरीय एपीआई में।

लेकिन: फ़ंक्शन का नाम बदलें।

इसके बजाय startHttpServerइसे कहते makeSureHttpServerIsRunningया ensureHttpServerIsRunning

जब कोई फ़ंक्शन कहा जाता है startHttpServer, तो पाठक इसे HTTP सर्वर शुरू करने की उम्मीद करते हैं; जब एक पंक्ति में दस बार कॉल किया जाता है, तो मेरे पास दस सर्वर चलेंगे। आपका कार्य अधिकतर समय ऐसा नहीं करता है। इसके अतिरिक्त, "स्टार्ट" नाम से पता चलता है कि अगर मुझे केवल एक सर्वर चल रहा है तो मुझे इस बात का ध्यान रखना होगा कि फ़ंक्शन को पहले ही कॉल किया गया है या नहीं।

जब कोई फ़ंक्शन कहा जाता है makeSureHttpServerIsRunning, तो मुझे लगता है कि यह सुनिश्चित करने के लिए आवश्यक चीजें करेगा कि एक HTTP सर्वर चल रहा है, सबसे अधिक संभावना यह जांचने से कि क्या यह पहले से ही चल रहा है, और अन्यथा इसे शुरू करना। मैं यह भी मानता हूं कि फ़ंक्शन यह सुनिश्चित करता है कि सर्वर वास्तव में चल रहा है (सर्वर शुरू करने में कुछ समय शामिल हो सकता है जहां यह अभी तक नहीं चल रहा है)।


83
इस। व्यक्तिगत रूप से मैं इसके बजाय "सुनिश्चित" का उपयोग करता हूं। मुद्दा यह है कि यह एक नामकरण योजना बननी चाहिए जो आपकी टीम में समझ में आए।
व्यंग्यात्मक

3
या एक अपवाद को फेंकना शुरू कर दिया है अगर इसकी शुरुआत हो गई है। जैसे sqlconnection.open
Ewan

9
मैं हमेशा "do" के लिए "सुनिश्चित करें" नामकरण का उपयोग करें यदि पहले से ही नहीं है "फ़ंक्शन।
काज

3
एक और नाम जो मुझे अक्सर दिखाई देता है, वह हैऑर्क्रीटोमेस्टिंग, जो केवल पहली कॉल पर बनाता है और फिर बस कुछ लौटाता है
Fabich

5
@aroth क्या आप सुनिश्चित हैं कि आप किसी भी उपलब्ध पोर्ट को खोजने और उसे वापस करने का प्रयास नहीं करेंगे? या सिर्फ बुरी तरह से लिखा जा सकता है? ;)
jpmc26

33

इसका नाम बदला EnsureServerRunning

पूरी तरह से अस्पष्ट और स्पष्ट है कि यह सुनिश्चित करता है कि यह चल रहा है (यदि ऐसा नहीं है) यदि यह है तो पुनः आरंभ किए बिना।

(वैकल्पिक: StartServerIfNotRunning?)


1
ज्यादातर कॉल करने वाले सिर्फ इस बात का ध्यान रखते हैं कि कॉल के बाद सर्वर चल रहा हो। यह कैसे हासिल किया जाता है, वे परवाह नहीं करते।
gnasher729

29

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

निष्प्राण विधियाँ। तरीकों में भी "बेकारता" की संपत्ति हो सकती है (एक तरफ त्रुटि या समाप्ति मुद्दों से) एन> 0 के समान प्रभाव के समान अनुरोध एक ही अनुरोध के लिए समान है। ( W3.org से )

यहाँ सर्वर साइड इफ़ेक्ट यह है कि एक बार मेथड कहलाने के बाद http सर्वर शुरू हो जाता है। मुझे ऐसा करने की एक विधि में कुछ भी गलत नहीं दिख रहा है।

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


5
समारोह है नहीं idempotent यह एक बार बुला http सर्वर शुरू होता है, और यह बुला दूसरी बार नहीं करता है। यह शाब्दिक रूप से आलस्य के विपरीत है। अगर हर कॉल ने एक नया http सर्वर शुरू किया तो यह बहुत ही सुखद होगा ।
पॉलिग्नोमे

36
@ पोलीगोमेन विकिपीडिया ने एफ (एफ (x)) = f (x) के रूप में बेकरारी को परिभाषित किया है जो आम तौर पर निक के विवरण से मेल खाता है। यहाँ फ़ंक्शन इनपुट और आउटपुट निहित सर्वर स्थिति होगी, इसलिए "सर्वर चल रहा है" राज्य इस फ़ंक्शन के लिए एक निश्चित बिंदु होगा। शायद मैं यहाँ विकिपीडिया लेख को गलत समझ रहा हूँ, क्या आप अन्य संदर्भों से जुड़ सकते हैं?
आमोन

16
@ पॉलीग्नोम: यह उत्तर सही है, idempotency से तात्पर्य उन कार्यों से है जिनके लिए एक बार या एक से अधिक बार बुलाए जाने से कोई फर्क नहीं पड़ता, परिणाम हमेशा एक जैसा रहता है। यहां, परिणाम एक चल रही http सेवा है, जिसे स्वतंत्र रूप से फ़ंक्शन कहा जाता है।
डॉक ब्राउन

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

10
@Polygnome क्षमा करें, आप गलत हैं। इम्पोटेंट का मतलब है कि अनुरोध का एक ही प्रभाव है कि क्या इसे एक बार निष्पादित किया जाता है, या एक से अधिक बार। N http सर्वर शुरू करना, अगर N के अनुरोध के डुप्लिकेट प्राप्त होते हैं, तो निश्चित रूप से यह बेकार नहीं है।
काज

7

एक है जो इसे लागू के रूप में उपकरण , startHttpServer, आप इसे, सबसे सरल चिकनी और बनाने की कोशिश कर किया जाना चाहिए सहज उपयोग करने के लिए ...

फ़ंक्शन का तर्क

तकनीकी तौर पर, बंटवारे से startHttpServerकी तर्क 2 कार्यों में और उन्हें बुला अलग , सभी तुम क्या करते है चलती startHttpServer s ' idempotency कोड में बजाय दोनों कार्यों बुला ... इसके अलावा, जब तक आप (एक तिहाई समारोह में दोनों तर्क लपेट जो है क्या करता है startHttpServerपहले स्थान पर), यह आपको असूचीबद्ध कोड लिखने के लिए मजबूर करता है, इसे हर जगह तेजी से नकल करते हुए आपको कॉल करना होगा startHttpServer। संक्षेप में, startHttpServer के लिए है ही फोन isHttpServerRunningसमारोह।

तो मेरी बात यह है:

  • isHttpServerRunningफ़ंक्शन को लागू करें क्योंकि इसे स्वतंत्र रूप से वैसे भी आवश्यक हो सकता है ...
  • इसके अनुसार अपनी अगली कार्रवाई को परिभाषित startHttpServerकरने के isHttpServerRunningलिए इसे लागू करने का कार्यान्वयन करें ...

फिर भी, आप startHttpServerइस फ़ंक्शन के उपयोगकर्ता की आवश्यकता वाले किसी भी मूल्य को वापस कर सकते हैं , जैसे:

  • 0 => सर्वर की विफलता
  • 1 => सर्वर सफलता की शुरुआत
  • 2 => सर्वर पहले ही शुरू कर दिया गया था

फ़ंक्शन का नामकरण

सबसे पहले, उपयोगकर्ता का प्राथमिक लक्ष्य क्या है ? HTTP सर्वर शुरू करने के लिए , है ना?

मौलिक रूप से, कुछ शुरू करने का इरादा रखने से कोई समस्या नहीं है जो पहले से ही शुरू हो चुका है, एकेए 1*1=1। इसलिए, कम से कम मेरे लिए, इसे कॉल करना " ensureHttpServerIsRunning" गंभीर रूप से आवश्यक नहीं लगता है, मैं इस बात की अधिक परवाह करता हूं कि फ़ंक्शन का नाम कितना लंबा, प्राकृतिक और यादगार है।

अब यदि आप यह जानना चाहते हैं कि हुड के तहत फ़ंक्शन का विस्तार से काम कैसे होता है, तो इसके लिए प्रलेखन या कोड स्रोत है, मेरा मतलब है कि लाइब्रेरी / फ्रेमवर्क / एपीआई / आदि से किसी अन्य फ़ंक्शन के लिए ...

आप सीखना समारोह एक बार जब तुम लिख इसे कई बार ...

तो वैसे भी, मैं इसके साथ startHttpServerकम, सरल और अधिक स्पष्ट रहना चाहूँगा ensureHttpServerIsRunning


1
विशेष रूप से चूंकि विधि को कुछ कॉन्फ़िगरेशन तर्क लेना चाहिए, जैसे रूट निर्देशिका, सुरक्षा सेटिंग्स, संभवतः एक पोर्ट संख्या, मैं यहां "प्रारंभ" के साथ 100% आरामदायक हूं।
user949300

@ user949300: "ensHttpServerIsRunning" का कॉलर कॉन्फ़िगरेशन, रूट निर्देशिका आदि के बारे में परवाह नहीं करता है, जो उस व्यक्ति का व्यवसाय है जो इसे लागू करता है।
gnasher729

2
@ gnasher729 जो मानता है कि http सर्वर एक सिंगलटन है। सिंगलटन दुष्ट हैं। और संभवतः यहाँ अनुचित है। आसानी से कई पोर्ट पर कई सर्वर हो सकते हैं। अगर वास्तव में सिर्फ एक http सर्वर है, तो यह पूरी विधि, IMO, खराब डिज़ाइन है बेहतर है कि बस एक बार प्रोग्राम इनिशियलाइज़ेशन पर सर्वर शुरू करें।
user949300

2

मुझे लगता है कि आपके सहयोगी का मतलब है कि startHttpServerबहुत ज्यादा कर रहा है:

  • जाँच रहा है कि क्या सर्वर पहले से चल रहा है,
  • जरूरत पड़ने पर सर्वर शुरू करना।

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

इसका मतलब है कि आपके पास एक नहीं, बल्कि कम से कम दो तरीके हैं :

  • isHttpServerRunning: boolean
  • startHttpServer

आवेदन प्रविष्टि बिंदु पहले विधि को कॉल करेगा, और फिर दूसरा अगर रिटर्न वैल्यू है false। अब, हर विधि एक और एक काम कर रही है, और समझने में आसान है।


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


21
अब कुछ और दो कार्यों को बुलाकर दो काम कर रहा है, साथ ही, अलग-अलग कार्यों को उजागर करने से दौड़ की स्थिति का परिचय हो सकता है। मुफ्त लंच नहीं।
whatsisname

1
यदि वह सहकर्मी के लिए बहुत अधिक है, तो सौभाग्य।
gnasher729

@ gnasher729: यह जवाब आपके विपरीत नहीं है - काफी विपरीत है, यह वास्तव में दो में बंटवारे के साथ विधि का नाम बदलने के लिए एक अच्छा विचार हो सकता है। और जब तक हम वास्तविक कोड नहीं देखते, हमें पता नहीं है कि कोड कितना जटिल है।
डॉक ब्राउन

10
यह उत्तर अमूर्तता और DRY का विरोध करता है। क्या होगा अगर startHttpServerकोड में एक से अधिक स्थान कहा जाता है? क्या कई समान लाइनों को हर जगह कॉपी-पेस्ट किया जाना चाहिए? क्या यह सभी कार्यों के साथ किया जाना चाहिए? बहुत जल्द आप कार्यक्रम अनंत आकार होगा।
जैक्सबी

3
मुझे लगता है कि इस दृष्टिकोण का पहला दुष्परिणाम यह है कि startHttpServerविधि की शुरुआत मोटे तौर पर जैसी दिखेगी if (isHttpServerRunning()){ return; }। आप एक व्यावसायिक नियम की पुष्टि कर रहे हैं कि "यह http सर्वर शुरू करने के लिए मान्य नहीं है यदि यह पहले से चल रहा है", लेकिन फिर उस नियम को लागू करने के लिए इसे किसी और की ज़िम्मेदारी बना दें। तदर्थ और हर स्थान पर बार-बार जहां वे कॉल कर सकते हैं startHttpServer
एरोथ 28:17

2

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

स्वयं, जावा से अधिक आने पर, "कैशिंग" या "आलसी मूल्यांकन" शब्द दिमाग में आते हैं। "Idempotent" तकनीकी रूप से सही है और एक अच्छा विकल्प है, esp। यदि आपके पास अधिक कार्यात्मक पृष्ठभूमि है।


यह "एक बार" नहीं हो सकता है, अगर सर्वर को रोका जा सकता है।
gnasher729

@ gnasher729। मैं शायद ही कभी इस्तेमाल की जाने वाली restartHttpServer()विधि की कल्पना कर सकता था । लेकिन बस रोक - वहाँ का उपयोग मामला क्या है? आप छिटपुट कनेक्शन विफलताओं को पसंद करते हैं? :-)
user949300

केवल HTTP सर्वर को रोकने के लिए एक उपयोग के मामले की आवश्यकता नहीं है क्योंकि इसे प्रोग्राम के लिए कुछ बाहरी द्वारा रोका जा सकता है - HTTP सर्वर ने segfaulted और मृत्यु हो सकती है, किसी व्यवस्थापक ने मैन्युअल रूप से इसे किसी कारण से रोका हो सकता है, आदि
डेव शेरोहमान

डेव, एक दुर्घटना "असाधारण" है और इसे इस तरह से संभाला जाना चाहिए। इसके अलावा, चूंकि दुर्घटना कभी भी हो सकती है , क्या आपके कोड की हर पंक्ति नहीं होनी चाहिए ensureRunning()? :-) जैसा कि व्यवस्थापक इसे रोक रहा है, इस दूसरे कोड को लगातार पुनरारंभ करना जबकि व्यवस्थापक को संशोधित करने या ठीक करने की कोशिश कर रहा है अविश्वसनीय रूप से कष्टप्रद और गलत होगा। व्यवस्थापक इसे पुनः आरंभ करें, कोड नहीं।
user949300

-2

मैं पसंद करूंगा startHttpServerIfNotIsRunning

इस तरह, विधि नाम में पहले से ही स्थिति स्पष्ट रूप से उल्लिखित है। Ensureया makeSureमुझे थोड़ा अस्पष्ट लगता है, क्योंकि यह कोई तकनीकी अभिव्यक्ति नहीं है। ऐसा लगता है जैसे हम नहीं जानते कि वास्तव में क्या होने जा रहा है।


मैं मान रहा हूं कि आप मूल वक्ता नहीं हैं? क्योंकि यह सुनिश्चित करने की सटीक परिभाषा है कि हम क्या करने जा रहे हैं। लेकिन फिर भी यह एक उचित बिंदु है कि प्रलेखन और एपीआई को मूल अंग्रेजी स्पीकर स्तर को समझने की आवश्यकता नहीं होनी चाहिए।
Voo

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

2
@Voo - मैं एक देशी वक्ता हूँ और मुझे यकीन नहीं है कि इसका मतलब क्या है।
जोनाथन 13

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

@jcast: गंभीरता से?
gnasher729

-3

आपके सहकर्मी को आपको जो बताना चाहिए था, वह यह है कि आपके पास कोई व्यवसाय नहीं है। यह पहले से ही बहुत बार लिखा गया है, और इससे बेहतर लिखा है कि आप इसे लिखने की संभावना रखते हैं। उदाहरण के लिए: http://docs.ansible.com/ansible/latest/systemd_module.html https://docs.saltstack.com/en/latest/ref/states/all/salt.states.service.html

एक वास्तुशिल्प दृष्टिकोण से, एक वेब सर्वर का प्रबंधन करने वाले कोड के कुछ मनमाने तरीके से बुरे सपने आते हैं। जब तक सेवाओं का प्रबंधन विशेष रूप से नहीं होता है तब तक आपका कोड क्या करता है। लेकिन मैं अनुमान लगा रहा हूं कि आपने monit (या kubernetes या ...) नहीं लिखा है।


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

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