2009-08-14 9 views
5

संपादित करें:आप gen_server मॉड्यूल को पैरामीटर कैसे करते हैं?

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

जेड को यह दिखाने के लिए धन्यवाद कि मेरा प्राथमिक उद्देश्य संभव है।


क्या कोई भी gen_servers पर पैरामीटरयुक्त मॉड्यूल का उपयोग करने का कोई तरीका समझ सकता है? निम्न उदाहरण में, मान लीजिए कि test_child एक पैरामीटर के साथ एक gen_server है। जब मैंने इसे शुरू करने की कोशिश, सभी मैं है:

42> {test_child, "hello"}:start_link(). 
** exception exit: undef 
    in function test_child:init/1 
     called as test_child:init([]) 
    in call from gen_server:init_it/6 
    in call from proc_lib:init_p_do_apply/3 

अंत में, मैं एक gen_server के कई नामित उदाहरणों का उपयोग करने के लिए एक तरह से यह पता लगाने की कोशिश कर रहा हूँ। जहां तक ​​मैं कह सकता हूं, जैसे ही आप इसे करना शुरू करते हैं, आप अब अपने सुंदर एपीआई का उपयोग नहीं कर सकते हैं और gen_server के साथ अपने उदाहरणों पर संदेशों को फेंकना होगा: कॉल और gen_server: cast। अगर मैं उनके नामों को उदाहरण बता सकता हूं, तो इस समस्या को कम किया जा सकता है।

+0

आप एक ही कॉलबैक मॉड्यूल का उपयोग करके एकाधिक gen_servers चाहते हैं, प्रत्येक एक अलग नाम के साथ? या एक ही नाम के साथ कई gen_servers? – Jacob

+0

एक ही कॉलबैक मॉड्यूल का उपयोग कर एकाधिक gen_servers। आप अलग-अलग "उदाहरण" को पंजीकृत करने के लिए एक नाम start_link पास कर सकते हैं। जब आपके पास एक ही उदाहरण हो, तो ऐसा लगता है कि यह मॉड्यूल के समान नाम देने के लिए सामान्य है, और फिर आपका सार्वजनिक एपीआई इस तरह काम करता है: some_module: some_function()। ... लेकिन ऐसा लगता है कि यह एक सुविधा है। यदि आप gen_server को किसी भिन्न नाम से पंजीकृत करते हैं, तो यह अब और काम नहीं करता है। मैं कुछ ऐसा करना चाहता हूं जैसे: 1> मॉड: some_function()। 2> मॉड 1: some_function()। ... जहां प्रत्येक चर gen_server मॉड्यूल – mwt

+0

के विभिन्न उदाहरणों को संदर्भित करता है या वैकल्पिक रूप से, मैं जानना चाहता हूं कि मुझे इसकी परवाह क्यों नहीं करनी चाहिए। मैंने देखा है कि प्रत्येक gen_server परिचय gen_server कास्ट/कॉल का उपयोग करने के बजाय एक एपीआई सेट अप करता है।एरलांग के लिए नया होने के नाते, मुझे कई प्रक्रियाओं को आसानी से क्लोन करने में सक्षम होने की उम्मीद है, और मुझे आश्चर्य है कि जैसे ही आप अपने gen_servers का नाम बदलते हैं, एपीआई सुविधा टूट जाती है। – mwt

उत्तर

-4
-module(zed, [Name]). 
-behavior(gen_server). 

-export([start_link/0, init/1, handle_cast/2]). 
-export([increment/0]). 

increment() -> 
    gen_server:cast(Name, increment). 

start_link() -> 
    gen_server:start_link({local, Name}, {?MODULE, Name}, [], []). 

init([]) -> 
    {ok, 0}. 

handle_cast(increment, Counter) -> 
    NewCounter = Counter + 1, 
    io:format("~p~n", [NewCounter]), 
    {noreply, NewCounter}. 

इस मॉड्यूल मेरे लिए ठीक काम कर रहा है:

Eshell V5.7.2 (abort with ^G) 
1> S1 = zed:new(s1). 
{zed,s1} 
2> S1:start_link(). 
{ok,<0.36.0>} 
3> S1:increment(). 
1 
ok 
4> S1:increment(). 
2 
ok 
+0

धन्यवाद। मैं इसे अपने प्रोजेक्ट में जोड़ने जा रहा हूं और देख सकता हूं कि लाभ इस थ्रेड में आपके द्वारा उठाए गए आपत्तियों से अधिक हैं या नहीं। – mwt

+1

मुझे लगता है कि इस उत्तर पर नकारात्मक वोटों को चीजों को स्पष्ट करना चाहिए :) – gleber

+0

मुझे लगता है कि हम पहले से ही यह पता लगा चुके हैं कि आप और पुरालेख पैरामीट्रिज्ड मॉड्यूल के पक्ष में नहीं हैं, लेकिन गिनती के लिए धन्यवाद :) – Zed

3

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

+0

कार्यक्षमता के मामले में "उनमें से शीर्ष पर प्रबंधक" और बिल्ट-इन प्रक्रिया रजिस्ट्री के बीच क्या अंतर है? – Zed

+1

अंतर यह है कि प्रबंधक एक विशेष प्रक्रिया है, जो एक समय में एक चीज करता है। जबकि अंतर्निहित प्रक्रिया रजिस्ट्री केंद्रीय सर्वर के लिए सामान्य उद्देश्य रजिस्ट्री है, जिसे विश्व स्तर पर (नोड पर) एक्सेस किया जाना चाहिए। प्रक्रिया रजिस्ट्री का उपयोग करते समय नाम संघर्ष का मौका बहुत अधिक है। इसके अलावा AFAIK प्रक्रिया रजिस्ट्री का उद्देश्य बड़ी संख्या में वस्तुओं को स्टोर करना नहीं है - यानी यह – gleber

+0

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

10

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

-module(test_module, [Param1]). 

some_method() -> Param1. 

-module(test_non_paramatized_module). 

some_method(Param1) -> Param1. 

के बराबर है पूर्व आप में ज़्यादा कुछ खरीद नहीं करता है, और बहुत कम मौजूदा Erlang कोड है कि शैली का उपयोग करता है।

यह नाम तर्क (यह मानते हुए आप विभिन्न नामों के तहत पंजीकृत समान gen_servers के एक नंबर बना रहे हैं) start_link कार्य करने के लिए पारित करने के लिए और अधिक सामान्य है।

start_link(Name) -> gen_server:start_link({local, Name}, ?MODULE, [Name], []). 

जवाब देने के लिए दूसरी बात यह है कि gen_server paramatized मॉड्यूल के साथ संगत है है:

-module(some_module, [Param1, Param2]). 

start_link() -> 
    PModule = ?MODULE:new(Param1, Param2), 
    gen_server:start_link(PModule, [], []). 

Param1 और Param2 तो सभी gen_server कॉलबैक कार्यों में उपलब्ध हो जाएगा।

जेड उल्लेख के रूप में, के रूप में start_link एक paramatized मॉड्यूल के अंतर्गत आता है, तो आपको इसे कहते हैं निम्न कार्य करने की आवश्यकता होगी:

Instance = some_module:new(Param1, Param2), 
Instance:start_link(). 

मैं इस एक विशेष रूप से बदसूरत शैली होने के लिए लगता है - कोड है कि कॉल some_module:new/n मॉड्यूल पैरामीटर के नंबर और ऑर्डर को अवश्य जानना चाहिए। some_module:new/n पर कॉल करने वाला कोड some_module में भी नहीं रह सकता है। मॉड्यूल पैरामीटर के नंबर या ऑर्डर में बदलाव होने पर यह बदले में एक गर्म अपग्रेड को और अधिक कठिन बनाता है। आपको some_module कोड को अपग्रेड करने का कोई तरीका मिल सकता है, भले ही आपको एक (some_module और इसके इंटरफ़ेस/कन्स्ट्रक्टर मॉड्यूल) की बजाय दो मॉड्यूल लोड करना समन्वयित करना होगा। एक मामूली नोट पर, यह शैली some_module:start_link उपयोगों के लिए कोडबेस को grep करने में कुछ और मुश्किल बनाती है।


सिफारिश gen_servers लिए पैरामीटर भेजने के लिए रास्ता gen_server:start_link/3,4 समारोह तर्क के माध्यम से स्पष्ट रूप से है और उन्हें आप ?MODULE:init/1 callack से लौटने राज्य मूल्य में संग्रहीत करते हैं।

-module(good_style). 

-record(state, {param1, param2}). 

start_link(Param1, Param2) -> 
    gen_server:start_link(?MODULE, [Param1, Param2], []). 

init([Param1, Param2]) -> 
    {ok, #state{param1=Param1,param2=Param2}}. 

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

यह शैली कोड परिवर्तन तंत्र के माध्यम से गर्म अपग्रेड का भी समर्थन करती है। जब code_change/3 फ़ंक्शन कहा जाता है, तो आप एक नया राज्य मान वापस कर सकते हैं। gen_server कोड पर एक नया पैरामाइज्ड मॉड्यूल उदाहरण वापस करने का कोई समान तरीका नहीं है।

+0

मुझे आपके दूसरे भाग का बिंदु नहीं दिख रहा है। Parametrized मॉड्यूल में कोई "स्थिर" कार्य नहीं हैं (मुझे भी उन्हें याद आती है)। आप some_module को पूर्व कॉल के बिना start_link() को कॉल करने में सक्षम नहीं होंगे: नया/2। – Zed

+0

बेशक आपके पास एक अलग मॉड्यूल हो सकता है, जैसे some_module_factory, जिसमें आपका start_link() एक नया पैरामीरिज्ड कुछ_ मॉड्यूल लौटा रहा है, लेकिन फिर हम ओओ स्टाइल कोडिंग में बहुत गहरे हैं ... – Zed

+2

मुझे लगता है कि आप एक इंटरफ़ेस मॉड्यूल बना सकते हैं (वह था parametized) जो gen_server के माध्यम से एक गैर-paramatized gen_server के साथ संवाद: कॉल/2। यह gen_server के साथ अपग्रेड समस्या से बच जाएगा और इसका मतलब है कि आप सर्वर संदर्भ के चारों ओर अलग-अलग पास करते हैं (फ़ंक्शन पैरामीटर के बजाय एक पैरामीटरयुक्त मॉड्यूल के रूप में)। आपको अभी भी समन्वय-दो-मॉड्यूल अपग्रेड समस्या के साथ छोड़ा जाएगा, और मैं इसे अच्छी शैली के रूप में अनुशंसा नहीं कर सकता। – archaelus

10

मैं सिर्फ दो बातें कहना चाहता हूँ:

  • archaelus इसे सही ढंग से बताते हैं। जैसा कि वह कहता है कि वह अंतिम तरीका दिखाता है कि वह ऐसा करने का अनुशंसित तरीका है और जो आप उम्मीद करते हैं वह करता है।

  • कभी नहीं, कभी नहीं, कभी नहीं , कभी प्रपत्र आप कोशिश कर रहे थे का उपयोग करें! यह पुराने दिनों से एक बायीं ओर है जो कभी भी आपके इरादे से नहीं था और अब दृढ़ता से बहिष्कृत है।

+0

@mwt, कृपया रॉबर्ट के अंक पर विचार करें। वह एरलांग के रचनाकारों में से एक है और वह निश्चित रूप से हर एर्लांग-नौसिखिया को सुनना चाहिए! – gleber

+0

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

+0

मैं दिखाए गए आखिरी तरीके का जिक्र कर रहा था, वह पैरामीट्रिज्ड मॉड्यूल, मॉड्यूल good_style का उपयोग नहीं कर रहा है। आर्केलस यह भी टिप्पणी करता है कि पैरामीट्रिज्ड मॉड्यूल का उपयोग करते समय यह काफी फिट बैठता है। ठीक है, भले ही आपने कभी भी अपने उदाहरण में शैली का उपयोग करने का इरादा नहीं किया है, यह वह शैली है जिसका उपयोग आपने किया था, इसलिए आपको यह मानना ​​चाहिए कि आप यही चाहते हैं। – rvirding

संबंधित मुद्दे