मैंने स्टुअर्ट सिएरा की बात " थिंकिंग इन डेटा " देखी और इस गेम में एक डिजाइन सिद्धांत के रूप में उसमें से एक विचार लिया। अंतर वह क्लोजर में काम कर रहा है और मैं जावास्क्रिप्ट में काम कर रहा हूं। मुझे इसमें हमारी भाषाओं के बीच कुछ प्रमुख अंतर दिखाई देते हैं:
- क्लोजर मुहावरेदार कार्यात्मक प्रोग्रामिंग है
- अधिकांश राज्य अपरिवर्तनीय है
मैंने स्लाइड से विचार लिया "सब कुछ एक नक्शा है" (11 मिनट, 6 सेकंड से> 29 मिनट तक)। कुछ बातें वे कहते हैं:
- जब भी आप कोई ऐसा कार्य देखते हैं, जिसमें 2-3 तर्क दिए जाते हैं, तो आप इसे एक मानचित्र में बदलने और सिर्फ एक मानचित्र को पास करने के लिए एक मामला बना सकते हैं। इसके बहुत सारे फायदे हैं:
- आपको तर्क क्रम के बारे में चिंता करने की आवश्यकता नहीं है
- आपको किसी भी अतिरिक्त जानकारी के बारे में चिंता करने की ज़रूरत नहीं है। यदि अतिरिक्त चाबियाँ हैं, तो यह वास्तव में हमारी चिंता नहीं है। वे बस से गुजरते हैं, वे हस्तक्षेप नहीं करते हैं।
- आपको एक स्कीमा परिभाषित करने की आवश्यकता नहीं है
- ऑब्जेक्ट में पास होने का विरोध करने के कारण कोई डेटा छिपा नहीं है। लेकिन, वह इस मामले को बनाता है कि डेटा छिपाने से समस्याएँ पैदा हो सकती हैं और यह खत्म हो गया है:
- प्रदर्शन
- कार्यान्वयन का आसानी
- जैसे ही आप नेटवर्क पर या प्रक्रियाओं पर संवाद करते हैं, आपको वैसे भी दोनों पक्षों को डेटा प्रतिनिधित्व पर सहमत होना होगा। अगर आप सिर्फ डेटा पर काम करते हैं तो यह अतिरिक्त काम है जिसे आप छोड़ सकते हैं।
मेरे सवाल के लिए सबसे अधिक प्रासंगिक है। यह 29 मिनट है: "अपने कार्यों को रचना योग्य बनाएं"। यहाँ वह कोड नमूना है जिसका उपयोग वह अवधारणा को समझाने के लिए करता है:
;; Bad (defn complex-process [] (let [a (get-component @global-state) b (subprocess-one a) c (subprocess-two a b) d (subprocess-three a b c)] (reset! global-state d))) ;; Good (defn complex-process [state] (-> state subprocess-one subprocess-two subprocess-three))
मैं समझता हूं कि अधिकांश प्रोग्रामर क्लोजर से परिचित नहीं हैं, इसलिए मैं इसे अनिवार्य शैली में फिर से लिखूंगा:
;; Good def complex-process(State state) state = subprocess-one(state) state = subprocess-two(state) state = subprocess-three(state) return state
ये हैं फायदे:
- परीक्षण करने में आसान
- अलगाव में उन कार्यों को देखने के लिए आसान है
- इसकी एक पंक्ति पर टिप्पणी करना आसान है और देखें कि एकल चरण को हटाने से क्या परिणाम होता है
- प्रत्येक उपप्रकार राज्य में अधिक जानकारी जोड़ सकता है। यदि सबप्रोसेस को किसी को सबप्रोसेस तीन से कुछ संवाद करने की आवश्यकता है, तो यह कुंजी / मान जोड़ने के समान सरल है।
- आपके द्वारा राज्य से बाहर की आवश्यकता वाले डेटा को निकालने के लिए कोई बॉयलरप्लेट नहीं है ताकि आप इसे वापस सहेज सकें। बस पूरे राज्य में पास करें और उपप्रोसेस को यह बताएं कि उसे क्या चाहिए।
अब, अपनी स्थिति पर वापस: मैंने यह सबक लिया और इसे अपने खेल में लागू किया। अर्थात्, मेरे लगभग सभी उच्च स्तर के कार्य एक gameState
वस्तु को लेते हैं और वापस करते हैं । इस ऑब्जेक्ट में गेम का सारा डेटा है। ईजी: बैडग्यू की एक सूची, मेनू की एक सूची, जमीन पर लूट, आदि। यहां मेरे अपडेट फ़ंक्शन का एक उदाहरण है:
update(gameState)
...
gameState = handleUnitCollision(gameState)
...
gameState = handleLoot(gameState)
...
मैं यहां जो कुछ भी पूछना चाहता हूं, क्या मैंने कुछ घृणा पैदा की है जो एक विचार को विकृत करता है जो केवल कार्यात्मक प्रोग्रामिंग भाषा में व्यावहारिक है? जावास्क्रिप्ट मुहावरेदार कार्यात्मक नहीं है (हालांकि इसे उस तरह से लिखा जा सकता है) और अपरिवर्तनीय डेटा संरचनाओं को लिखना वास्तव में चुनौतीपूर्ण है। एक बात जो मुझे चिंतित करती है वह यह मानती है कि उनमें से प्रत्येक उपप्रकार शुद्ध हैं। उस धारणा को बनाने की आवश्यकता क्यों है? यह दुर्लभ है कि मेरा कोई भी कार्य शुद्ध है (इसके द्वारा, मेरा मतलब है कि वे अक्सर संशोधित करते हैं gameState
। मेरे पास इसके अलावा कोई अन्य जटिल दुष्प्रभाव नहीं है)। यदि आपके पास अपरिवर्तनीय डेटा नहीं है, तो क्या ये विचार टूट जाते हैं?
मुझे चिंता है कि एक दिन मैं उठूंगा और महसूस करूंगा कि यह पूरी डिजाइन एक दिखावा है और मैं वास्तव में सिर्फ बिग बॉल ऑफ मड विरोधी पैटर्न को लागू कर रहा हूं ।
ईमानदारी से, मैं इस कोड पर महीनों से काम कर रहा हूं और यह बहुत अच्छा रहा है। मुझे लगता है कि मुझे उनके द्वारा दावा किए जा रहे सभी फायदे मिल रहे हैं। मेरा कोड मेरे लिए तर्क के लिए सुपर आसान है । लेकिन मैं वन मैन टीम हूं इसलिए मुझे ज्ञान का अभिशाप है।
अपडेट करें
मैं इस पैटर्न के साथ 6+ महीने का कोडिंग कर रहा हूं। आमतौर पर इस समय तक मैं भूल जाता हूं कि मैंने क्या किया है और वह यह है कि "क्या मैंने इसे साफ तरीके से लिखा है?" खेलने के लिए आता है। अगर मैंने नहीं किया, तो मैं वास्तव में संघर्ष करूँगा। अब तक, मैं बिल्कुल संघर्ष नहीं कर रहा हूं।
मैं समझता हूं कि इसकी स्थिरता को सत्यापित करने के लिए आंखों का एक और सेट कैसे आवश्यक होगा। मैं केवल इतना कह सकता हूं कि मैं सबसे पहले और सबसे महत्वपूर्ण है। मैं हमेशा साफ कोड के लिए सबसे जोरदार प्रचारक हूं, जहां मैं काम करता हूं।
मैं सीधे उन लोगों को जवाब देना चाहता हूं जिनके पास कोडिंग के इस तरीके के साथ पहले से ही एक बुरा व्यक्तिगत अनुभव है। मुझे तब यह पता नहीं था, लेकिन मुझे लगता है कि हम वास्तव में कोड लिखने के दो अलग-अलग तरीकों के बारे में बात कर रहे हैं। जिस तरह से मैंने किया है वह अन्य लोगों की तुलना में अधिक संरचित प्रतीत होता है। जब किसी को "सब कुछ एक नक्शा है" के साथ एक बुरा व्यक्तिगत अनुभव होता है, तो वे इस बारे में बात करते हैं कि इसे बनाए रखना कितना कठिन है:
- आप कभी भी नक्शे की संरचना को नहीं जानते हैं जो फ़ंक्शन की आवश्यकता है
- कोई भी फ़ंक्शन उन तरीकों से इनपुट को म्यूट कर सकता है जिनकी आपको कभी उम्मीद नहीं थी। आपको यह पता लगाने के लिए कोड आधार पर सभी को देखना होगा कि किसी विशेष कुंजी को नक्शे में कैसे मिला या यह क्यों गायब हो गया।
इस तरह के अनुभव वाले लोगों के लिए, शायद कोड आधार था, "सब कुछ एन प्रकार के 1 नक्शे लेता है।" मेरा है, "सब कुछ 1 प्रकार के मानचित्र लेता है"। यदि आप उस 1 प्रकार की संरचना को जानते हैं, तो आप हर चीज की संरचना को जानते हैं। बेशक, वह संरचना आमतौर पर समय के साथ बढ़ती है। इसीलिए...
संदर्भ कार्यान्वयन के लिए देखने के लिए एक स्थान है (यानी: स्कीमा)। यह संदर्भ कार्यान्वयन कोड का उपयोग करता है, इसलिए यह पुराना नहीं हो सकता।
दूसरे बिंदु के रूप में, मैं संदर्भ कार्यान्वयन के बाहर के नक्शे में कुंजियाँ नहीं जोड़ता / हटाता, मैं पहले से ही वहां क्या है, इसे म्यूट करता हूं। मेरे पास स्वचालित परीक्षणों का एक बड़ा सूट भी है।
यदि यह वास्तुकला अंततः अपने स्वयं के वजन के तहत ढह जाती है, तो मैं एक दूसरा अपडेट जोड़ूंगा। अन्यथा, मान लें कि सब कुछ ठीक चल रहा है :)