2015-08-20 6 views
18

मेरे पास मेरे अनुप्रयोगों में अपरिवर्तनीय डेटा का उपयोग करने के लाभों का एक अच्छा विचार है और मैं एक सरल सिंक्रोनस प्रोग्रामिंग वातावरण में इन अपरिवर्तनीय संरचनाओं का उपयोग करने के विचार से काफी सहज हूं।एसिंक सिस्टम में अपरिवर्तनीय डेटा

वहाँ कि पुनरावर्ती कॉल, कुछ इस तरह की एक श्रृंखला में साथ राज्य पारित करके एक खेल के लिए प्रबंध स्थिति का वर्णन करती स्टैक ओवरफ़्लो पर कहीं एक अच्छा उदाहरण है:

function update(state) { 
    sleep(100) 

    return update({ 
    ticks: state.ticks + 1, 
    player: player 
    }) 
} 

हम कुछ मनमाने ढंग से, पक्ष क्या कर सकते हैं फ़ंक्शन के शरीर में प्रभाव मुक्त कार्य करें, फिर हम पुराने को बदलने के बजाए एक नया राज्य वापस कर दें।

जावास्क्रिप्ट कहने में, इसे सरल एसिंक मॉडल में अनुवाद करना काफी आसान लगता है।

function update(state) { 
    const newState = { 
    player, 
    ticks: state.ticks + 1 
    }; 

    setTimeout(update.bind(this, newState), 100); 
} 

हालांकि, जैसे ही हम अतुल्यकालिक घटनाओं के लिए अधिक स्रोतों है, यह राज्य अपरिवर्तनीय और कार्यों को शुद्ध रखने के प्रबंधन करने के लिए एक बहुत कठिन हो रहा है।

यदि हम उदाहरण के लिए एक क्लिक ईवेंट जोड़ते हैं, तो हम इस तरह दिखने वाले कोड के साथ समाप्त होते हैं।

window.addEventListener('click', function() { 
    // I have no idea what the state is 
    // because only our update loop knows about it 
}); 

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

window.addEventListener('click', function() { 
    const state = getState(); 

    createState({ 
    player, 
    clicks: clicks + 1 
    }); 
}); 

लेकिन ऐसा लगता है कि इस तरह के किसी प्रकार के परिवर्तनीय राज्य प्रबंधक की आवश्यकता है?

window.addEventListener('click', function() { 
    createAction('click', e); 
}); 

function update(state, actions) { 
    const newState = { 
    player, 
    ticks: state.ticks + 1, 
    clicks: state.clicks + actions.clicks.length 
    }; 

    setTimeout(update.bind(this, newState, []), 100); 
} 

फिर, यह विशेष रूप से कार्यात्मक महसूस नहीं करता है और कम से पर निर्भर करता है:

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

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

+6

आप कार्यात्मक प्रतिक्रियाशील प्रोग्रामिंग (एफआरपी) के लिए देख रहे हैं। – Bergi

+3

वह कतार वास्तव में एक उचित तरीके की तरह लगती है (बस इसे 'अपडेट' में उपभोग करने के बाद इसे साफ़ करना न भूलें)। लेकिन वास्तव में आपको हमेशा अपने कार्यक्रम के कुछ छोटे हिस्से को उत्परिवर्तनीय होने की आवश्यकता होती है, क्योंकि एक क्लिक * जैसे * एक साइड इफेक्ट होता है (या यह कुछ भी नहीं करता है)। Immutabiltity आपके प्रोग्राम में कभी भी कुछ भी करने के बारे में नहीं है, यह आपके द्वारा किए जा रहे कार्यों को उचित रूप से मॉडलिंग करने के बारे में है। – Bergi

+1

@ बर्गि से सहमत हुए। घटनाक्रम, परिभाषा के अनुसार, राज्यिक हैं; इनपुट, परिभाषा के अनुसार, mutable है। आपके मामले में सबसे अच्छी बात यह है कि आप जितना संभव हो सके अपरिवर्तनीय राज्य से उत्परिवर्तनीय राज्य को अलग करने का प्रयास करें। कतार वास्तव में अच्छी तरह से काम करती है (विशेष रूप से एक गेम स्टैंडपॉइंट से; मैंने इसे स्वयं इस्तेमाल किया है) और इसलिए आपके मामले में, कतार उत्परिवर्तनीय हो सकती है - आप ईवेंट को जोड़ना जारी रख सकते हैं - अगले अपडेट तक। उस बिंदु पर, आपको कतार की एक अपरिवर्तनीय प्रतिलिपि बनाने की आवश्यकता है। उसके बाद, आप अपरिवर्तनीय संरचनाओं के साथ रह सकते हैं। –

उत्तर

4

आपको Redux पर एक बार देखने में रुचि हो सकती है। रेडक्स एक समान दृष्टिकोण लेता है:

  • यह पूरे अनुप्रयोग स्थिति को एक अपरिवर्तनीय वस्तु के रूप में मॉडल करता है।
  • उपयोगकर्ता क्रियाएं अनिवार्य रूप से संदेश हैं जो store पर मनमाने ढंग से प्रसंस्करण के लिए भेजी जाती हैं।
  • क्रिया रूप f(previousState, action) => newState में कम करने कार्यों के द्वारा नियंत्रित किया जाता है। यह आपके मूल संस्करण की तुलना में एक अधिक कार्यात्मक दृष्टिकोण है।
  • store reducers चलाता है और एक भी अपरिवर्तनीय आवेदन राज्य बनाए रखता है।

आप सही हैं कि यह सख्ती से अपरिवर्तनीय नहीं है, क्योंकि स्टोर के पास वर्तमान स्थिति के लिए एक व्यवहार्य संदर्भ है। लेकिन जैसा कि अन्य ने ध्यान दिया है, यह अपरिवर्तनीय डेटा की अधिकांश धारणाओं के लिए एक मुद्दा की तरह प्रतीत नहीं होता है।

यूआई क्रियाओं के अतिरिक्त, आपके पास tick क्रिया भी हो सकती है जो लूप में आग लगती है - यह केवल एक और इनपुट ईवेंट है, जो रेड्यूसर के उसी सेट द्वारा संसाधित होता है।

0

Object.freeze का उपयोग करना, आप एक वस्तु अपरिवर्तनीय बना सकते हैं:

var o = {foo: "bar"}; 
Object.freeze(o); 
o.abc = "xyz"; 
console.log(o); 

निकलेगा {foo: "bar"}। ध्यान दें कि जमे हुए चर पर नई संपत्ति सेट करने का प्रयास चुपचाप विफल हो जाएगा।

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

+0

मुझे लगता है कि आपने इस सवाल को गलत समझा होगा। मैं पूरी तरह से अवगत डेटा बनाने और प्रबंधित करने के बारे में पूरी तरह से अवगत हूं। सवाल कई असीमित घटनाओं के बीच आवेदन स्थिति का ट्रैक रखने के बारे में है। –

1

सीधे अपने सवाल का जवाब देने की कोशिश में:

"क्या एक प्रणाली के लिए डिजाइन की तरह है जब वहाँ कई अतुल्यकालिक घटना स्रोत हैं दिखता है और हम सब कुछ अपरिवर्तनीय या कम से कम होना चाहते हैं, जो एक अच्छी बात है इस तरह की प्रणाली में उत्परिवर्तन को नियंत्रित करने के लिए पैटर्न? "

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

जैसा कि यह पता चला है कि आपकी कुल संदेश बैंडविड्थ कुल चैनल क्षमता से कम है और आपकी ट्रांसमिशन दूरी एक प्रकाश-सेकंड दूर - प्रतिरोध/स्विचिंग से कम है, आपकी विफलता की संभावना वैश्विक रूप से कम है (जैसे कुछ 10^-24)। सैद्धांतिक वजहों के सभी प्रकार के होते हैं, लेकिन क्वांटम भौतिकी और सूचना सिद्धांत यह वास्तव में concisely का उत्तर नहीं दिया जा सकता है में एक विषयांतर के बिना, लेकिन कोई गणितीय प्रमाण अभी तक निश्चित साबित होता है कि इस तरह के मामले है पाया गया है, यह सब अनुमान और व्यवहार है। लेकिन यूनिक्स के हर स्वाद ने विश्वसनीय अनुमानित संचार के लिए 30+ वर्षों के लिए उन अनुमानों पर भरोसा किया है।

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

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

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

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

मुझे आशा है कि मैंने आपके प्रश्न का उत्तर दिया और आप जो पूछ रहे थे उससे दूर तक नहीं गए। :)

के बाद संपादित करें:

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

https://docs.oracle.com/cd/E19798-01/821-1841/bncfh/index.html

https://blog.codepath.com/2013/01/06/asynchronous-processing-in-web-applications-part-2-developers-need-to-understand-message-queues/

http://www.enterpriseintegrationpatterns.com/patterns/messaging/ComposedMessagingMSMQ.html

http://soapatterns.org/design_patterns/asynchronous_queuing

http://www.rossbencina.com/code/programming-with-lightweight-asynchronous-messages-some-basic-patterns

http://www.asp.net/aspnet/overview/developing-apps-with-windows-azure/building-real-world-cloud-apps-with-windows-azure/queue-centric-work-pattern

http://spin.atomicobject.com/2014/08/18/asynchronous-ios-reactivecocoa/

http://fsharpforfunandprofit.com/posts/concurrency-reactive/

और मार्टिन ओडर्स्की से एक वीडियो ...

https://www.typesafe.com/resources/video/martin-odersky---typesafe-reactive-platform

:)

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