जब कार्यात्मक शैली में प्रोग्रामिंग करते हैं, तो क्या आपके पास एक एकल एप्लिकेशन स्थिति है जिसे आप एप्लिकेशन लॉजिक के माध्यम से बुनते हैं?


12

मैं एक ऐसी प्रणाली का निर्माण कैसे कर सकता हूं जिसमें निम्नलिखित हैं :

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

मुझे ऐसा प्रतीत होता है कि राज्य का मठ नियम # 2 को तोड़ता है, हालांकि यह स्पष्ट नहीं है क्योंकि यह मठ के माध्यम से बुना हुआ है।

मुझे लगता है कि मुझे किसी भी तरह से लेंस का उपयोग करने की आवश्यकता है, लेकिन गैर-कार्यात्मक भाषाओं के लिए इसके बारे में बहुत कम लिखा गया है।

पृष्ठभूमि

एक अभ्यास के रूप में, मैं अपने मौजूदा एप्लिकेशन को ऑब्जेक्ट-ओरिएंटेड शैली से कार्यात्मक शैली में परिवर्तित कर रहा हूं। पहली चीज जो मैं करने की कोशिश कर रहा हूं वह है कि जितना संभव हो सके आवेदन के इनर-कोर को अधिक से अधिक बनाना।

एक बात मैंने सुनी है कि विशुद्ध रूप से कार्यात्मक भाषा में "राज्य" का प्रबंधन कैसे किया जाता है, और यह मेरा मानना ​​है कि राज्य के मठों द्वारा किया जाता है, क्या तार्किक रूप से, आप एक शुद्ध कार्य कहते हैं, "राज्य में गुजर रहा है" जैसा कि यह है, "तब, जब फ़ंक्शन वापस लौटता है, तो यह आपके लिए दुनिया की स्थिति के रूप में बदल जाता है।

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

उसके आधार पर, मैं अपने आवेदन के माध्यम से चला गया, और: 1. सबसे पहले अपने सभी एप्लिकेशन स्टेट को एक ही वैश्विक ऑब्जेक्ट (GameState) में डाल दिया 2. दूसरा, मैंने GameState को अपरिवर्तनीय बना दिया। आप इसे बदल नहीं सकते। यदि आपको एक बदलाव की आवश्यकता है, तो आपको एक नया निर्माण करना होगा। मैंने एक कॉपी-कंस्ट्रक्टर को जोड़कर ऐसा किया, जो वैकल्पिक रूप से एक या अधिक फ़ील्ड लेता है जो बदल गया। 3. प्रत्येक आवेदन के लिए, मैं एक पैरामीटर के रूप में GameState में पास करता हूं। फ़ंक्शन के भीतर, यह क्या करने जा रहा है, इसे करने के बाद, यह एक नया GameState बनाता है और इसे वापस करता है।

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

मेरा प्रश्न:

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

इसके बारे में कुछ गलत लगता है। फ़ंक्शन को GameState की संपूर्णता की आवश्यकता नहीं है। इसके लिए सिर्फ स्कोर ऑब्जेक्ट की जरूरत है। इसलिए मैंने इसे स्कोर में पास करने के लिए अपडेट किया, और स्कोर को वापस कर दिया।

यह समझ में आता है, इसलिए मैं अन्य कार्यों के साथ आगे बढ़ गया। कुछ कार्यों के लिए मुझे GameState से 2, 3 या 4 मापदंडों को पारित करने की आवश्यकता होगी, लेकिन जैसा कि मैंने आवेदन के बाहरी कोर के सभी तरह से पैटर्न का उपयोग किया है, मैं अधिक से अधिक आवेदन स्थिति से गुजर रहा हूं। जैसे, वर्कफ़्लो लूप के शीर्ष पर, मैं एक विधि कहूंगा, वह विधि कहेगा जो एक विधि कहेगा, आदि, नीचे सभी तरह से जहां स्कोर की गणना की जाती है। इसका मतलब है कि वर्तमान स्कोर को उन सभी परतों के माध्यम से पारित किया जाता है, क्योंकि बहुत नीचे स्थित एक फ़ंक्शन स्कोर की गणना करने जा रहा है।

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

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

ऐसा लग रहा था कि जिस तरह से इस समस्या से बचा जा रहा है उसी तरह से GameState में गुजर रहा है। लेकिन मैं फ़ंक्शन की आवश्यकता से अधिक जानकारी को किसी फ़ंक्शन में पास करने की मूल समस्या पर वापस आ गया हूं।


1
मैं डिजाइन और विशेष रूप से कार्य करने में कोई विशेषज्ञ नहीं हूं, लेकिन चूंकि आपके खेल में एक राज्य है जो विकसित होता है, क्या आप सुनिश्चित हैं कि कार्यात्मक प्रोग्रामिंग एक प्रतिमान है जो आपके आवेदन की सभी परतों में फिट है?
वॉलफ्रैट

Walfrat, मुझे लगता है कि यदि आप कार्यात्मक प्रोग्रामिंग विशेषज्ञों से बात करते हैं, तो आप शायद पाएंगे कि वे कहेंगे कि कार्यात्मक प्रोग्रामिंग प्रतिमान में विकसित राज्य के प्रबंधन के लिए समाधान हैं।
दाशा लिन

आपका प्रश्न मेरे लिए व्यापक था जो केवल कहता है। यदि यह केवल प्रबंध राज्यों के बारे में है, तो यह एक शुरुआत है: stackoverflow.com/questions/1020653/… के
Walfrat

2
@DaishaLynn मुझे नहीं लगता कि आपको सवाल हटाना चाहिए। इसे उकेरा गया है और कोई भी इसे बंद करने की कोशिश नहीं कर रहा है, इसलिए मुझे नहीं लगता कि यह इस साइट के दायरे से बाहर है। अब तक एक उत्तर की कमी सिर्फ इसलिए हो सकती है क्योंकि इसमें कुछ अपेक्षाकृत आला विशेषज्ञता की आवश्यकता होती है। लेकिन इसका मतलब यह नहीं है कि यह अंततः नहीं मिलेगा और इसका जवाब दिया जाएगा।
बेन आरोनसन

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

जवाबों:


2

मुझे यकीन नहीं है कि एक अच्छा समाधान है। यह एक उत्तर हो सकता है या नहीं भी हो सकता है, लेकिन यह एक टिप्पणी के लिए बहुत लंबा है। मैं एक समान काम कर रहा था और निम्नलिखित ट्रिक से मदद मिली:

  • GameStateपदानुक्रम को विभाजित करें , ताकि आपको 15 के बजाय 3-5 छोटे हिस्से मिलें।
  • इसे इंटरफेस को लागू करने दें, ताकि आपके तरीके केवल आवश्यक भागों को देखें। वास्तविक प्रकार के बारे में अपने आप से झूठ बोलने पर कभी भी उन्हें वापस न लें।
  • भागों को इंटरफेस लागू करने दें, ताकि आप जो पास करते हैं उसका ठीक-ठीक नियंत्रण हो सके।
  • पैरामीटर ऑब्जेक्ट का उपयोग करें, लेकिन इसे संयम से करें और उन्हें अपने व्यवहार से वास्तविक वस्तुओं में बदलने की कोशिश करें।
  • कभी-कभी जरूरत से थोड़ा अधिक गुजरना एक लंबी पैरामीटर सूची से बेहतर होता है।

इसलिए अब मैं सोच रहा हूं कि मुझे जो समस्या है, वह यह है कि मेरे कार्य बहुत गहराई से निहित हैं।

मुझे ऐसा नहीं लगता। छोटे कार्यों में रिफैक्टिंग करना सही है, लेकिन हो सकता है कि आप उन्हें बेहतर तरीके से पुनः संगठित कर सकें। कभी-कभी, यह संभव नहीं है, कभी-कभी इसे समस्या को देखने के लिए एक दूसरे (या तीसरे) की आवश्यकता होती है।

अपने डिज़ाइन की तुलना म्यूटेबल से करें। क्या ऐसी चीजें हैं जो फिर से खराब हो गई हैं? यदि हां, तो क्या आप उन्हें उसी तरह से बेहतर नहीं बना सकते हैं जैसा आपने मूल रूप से किया था?


किसी ने मुझसे कहा कि मैं अपने डिज़ाइन को बदल दूं ताकि कभी भी फ़ंक्शन केवल एक पैरामीटर ले सके ताकि मैं करी का उपयोग कर सकूं। मैंने कोशिश की कि एक एक फ़ंक्शन, इसलिए DeleteEntity (a, b, c) को कॉल करने के बजाय, अब मैं DeleteEntity (a) (b) (c) कहता हूं। तो यह प्यारा है, और यह चीजों को और अधिक बनाने के लिए माना जाता है, लेकिन मुझे अभी तक यह नहीं मिल रहा है।
दिशा लिन

@DaishaLynn मैं जावा का उपयोग कर रहा हूं और करीने के लिए कोई मीठी सिंथैटिक चीनी नहीं है, इसलिए (मेरे लिए) यह कोशिश करने लायक नहीं है। मैं हमारे मामले में उच्च आदेश कार्यों के संभावित उपयोग से संबंधित संदेह करता हूं, लेकिन मुझे बताएं कि क्या यह आपके लिए काम करता है।
माॅर्टिनस

2

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

आप शायद C # में कुछ इस तरह की प्रतिकृति बना सकते हैं, यह इस बात पर निर्भर करता है कि आप उस राज्य को कैसे परिभाषित कर रहे हैं जो आसपास से गुजर रहा है। अगर आपको कुछ पसंद है

public class MyState
{
    public int MyInt {get; set; }
    public string MyString {get; set; }
}

आप इंटरफेस IHasMyIntऔर IHasMyStringतरीकों के साथ GetMyIntऔर GetMyStringक्रमशः परिभाषित कर सकते हैं। राज्य वर्ग तब दिखता है:

public class MyState : IHasMyInt, IHasMyString
{
    public int MyInt {get; set; }
    public string MyString {get; set; }
    public double MyDouble {get; set; }

    public int GetMyInt () 
    {
        return MyInt;
    }

    public string GetMyString ()
    {
        return MyString;
    }

    public double GetMyDouble ()
    {
        return MyDouble;
    }
}

तब आपके तरीकों को IHasMyInt, IHasMyString, या पूरे MyState की आवश्यकता हो सकती है।

फिर आप फ़ंक्शन परिभाषा पर जहां बाधा डाल सकते हैं, ताकि आप राज्य ऑब्जेक्ट को पास कर सकें, लेकिन यह केवल स्ट्रिंग और इंट में ही मिल सकता है, डबल नहीं।

public static T DoSomething<T>(T state) where T : IHasMyString, IHasMyInt
{
    var s = state.GetMyString();
    var i = state.GetMyInt();
    return state;
}

यह तो दिलचस्प है। इसलिए वर्तमान में, जहां मैं एक फ़ंक्शन को कॉल करता हूं और मूल्य से 10 पैरामीटर पास करता हूं, मैं 10 बार "gameSt'ate" में गुजरता हूं, लेकिन 10 अलग-अलग पैरामीटर प्रकारों, जैसे "IHasGameScore", "IHasGameBoard, आदि में। मैं वहां कामना करता हूं।" एक एकल पैरामीटर पास करने का एक तरीका था जो फ़ंक्शन को इंगित कर सकता है कि उस एक प्रकार के सभी इंटरफेस को लागू करना है। मुझे आश्चर्य है कि अगर मैं इसे एक "सामान्य बाधा" के साथ कर सकता हूं .. तो मुझे कोशिश करें।
दिशा लिन

1
इसने काम कर दिया। यहाँ यह काम कर रहा है: dotnetfiddle.net/cfmDbs
दिशा लिन

1

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

मूल रूप से, आपके पास एक शुद्ध कार्य है जो पूरे राज्य को लेता है और उपयोगकर्ता द्वारा की गई कार्रवाई और नया राज्य लौटाता है।

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

अधिक जानने के लिए, Google एल्म आर्किटेक्चर या Redux.js.org।


मैं एल्म को नहीं जानता, लेकिन मेरा मानना ​​है कि यह रेडक्स के समान है। Redux में, क्या सभी reducers को हर राज्य परिवर्तन के लिए नहीं बुलाया जाता है? बेहद अक्षम लगता है।
दाशा लिन

जब यह निम्न स्तर के अनुकूलन की बात आती है, तो यह मत मानो, माप। व्यवहार में यह काफी तेज है।
डैनियल टी।

धन्यवाद डैनियल, लेकिन यह मेरे लिए काम नहीं करेगा। मैंने यह जानने के लिए पर्याप्त विकास किया है कि यह यूआई में हर घटक को किसी भी समय किसी भी डेटा परिवर्तन को सूचित नहीं करता है, भले ही नियंत्रण नियंत्रण के बारे में परवाह करता हो।
लिन

-2

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

आपके प्रश्न का उत्तर देते हुए: नहीं, मैं एप्लिकेशन लॉजिक के माध्यम से किसी विशेष राज्य को नहीं बुनता हूं लेकिन वर्तमान उपयोग के मामले के लिए जो उपयुक्त हो उसका उपयोग करें और उपलब्ध तकनीकों को सबसे उपयुक्त तरीके से लागू करें।

C # तैयार नहीं है (अभी तक) कार्यात्मक के रूप में इस्तेमाल किया जा करने के लिए जैसा आप चाहते हैं।


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

@DaishaLynn आप गलत हैं, मैं किसी भी तरह से इसका विरोध नहीं कर रहा हूं और वास्तव में मैं इसका बहुत उपयोग करता हूं ... लेकिन जहां यह स्वाभाविक और संभव है और एक ओओ भाषा को एक कार्यात्मक में बदलने की कोशिश नहीं कर रहा है, बस यह हिप है ऐसा करने के लिए। आपको मेरे उत्तर से सहमत होने की आवश्यकता नहीं है लेकिन यह इस तथ्य को नहीं बदलता है कि आप अपने उपकरणों का ठीक से उपयोग नहीं कर रहे हैं।
t3chb0t

मैं ऐसा नहीं कर रहा हूं क्योंकि ऐसा करना कूल्हे है। C # स्वयं एक कार्यात्मक शैली का उपयोग करने की ओर बढ़ रहा है। खुद एंडर्स हेजेल्सबर्ग ने ऐसा संकेत दिया है। मैं समझता हूं कि आप केवल भाषा के मुख्य-स्ट्रीम उपयोग में रुचि रखते हैं, और मैं समझता हूं कि क्यों और कब उचित है। मुझे नहीं पता कि आप जैसा कोई व्यक्ति इस धागे पर भी क्यों है .. आप वास्तव में कैसे मदद कर रहे हैं?
दिशा लिन

@DaishaLynn यदि आप अपने प्रश्न या दृष्टिकोण की आलोचना करने वाले उत्तरों का सामना नहीं कर सकते हैं, तो शायद आपको यहां प्रश्न नहीं पूछना चाहिए या अगली बार आपको केवल यह कहते हुए अस्वीकरण जोड़ना चाहिए कि आप केवल अपने विचार का समर्थन करने वाले उत्तरों में रुचि रखते हैं क्योंकि आप 100% नहीं करते हैं। सच सुनना चाहते हैं, लेकिन सहायक राय प्राप्त करना चाहते हैं।
t3chb0t

कृपया एक-दूसरे के प्रति थोड़ा और सौहार्दपूर्ण रहें। भाषा को नापसंद किए बिना समालोचना देना संभव है। कार्यात्मक शैली में C # प्रोग्रामिंग करने का प्रयास निश्चित रूप से "दुरुपयोग" या एक किनारे-मामला नहीं है। यह कई सी # डेवलपर्स द्वारा इस्तेमाल की जाने वाली एक सामान्य तकनीक है जो अन्य भाषाओं से सीखती है।
जुमलाइफगार्ड
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.