HeadlinesBriefing favicon HeadlinesBriefing.com

निर्धारित मूल गैर-निर्धारित शेल आर्किटेक्चर

Hacker News •
×

भीतर 14 वर्षों पहले, Gary Bernhardt ने Functional Core, Imperative Shell शब्द को प्रयुक्त किया। अधिकांश अच्छे कंप्यूटिंग विचारों के समान, यह पूरी तरह से नई आवश्यकता नहीं थी, लेकिन उसकी स्पष्ट धारणा के बढ़िया प्रभाव थे और मौजूदा प्रणालियों में परीक्षण और निर्धारण के बारे में बात करने के लिए एक उत्कृष्ट आधार प्रदान करती है। संक्षेप में, Functional Core Imperative Shell आर्किटेक्चर कोड को दो भागों में बाँटता है। Functional Core पूरी तरह से फंक्शनल है - अर्थात कोई IO नहीं और कोई नष्ट करने वाला स्थिति अपडेट नहीं। यह एप्लिकेशन की व्यावसायिक तार्किकता को संभालता है। Imperative Shell में पथबद्धता कम होती है, लेकिन स्थिति को बनाए रखता है, बाहरी निर्भरताओं को समन्वय देता है और बाहरी दुनिया के साथ संवाद करता है - अर्थात IO। इसका काम कोई मूल्य पूछना है, कुछ blackbox निर्णय के परिणाम के रूप में मूल्य प्राप्त करना, और उसे उपयोग करना है बाहरी दुनिया के साथ संवाद करने के लिए; चाहे वह डेटाबेस में लिखना, एक अनुरोध भेजना, या GUI अपडेट करना हो। इस मॉडल में Core और Shell के पास distinct विशेषताएँ होती हैं: कोर शेल निर्णय लेता है निर्भरताओं को समन्वय देता है अधिक विभाजन प्रक्रिया पथ अधिक रैले प्रक्रिया स्वतंत्र रूप से दुनिया को एकीकृत करता है यह कोर को बहुत परीक्षण योग्य बनाता है। चूंकि यह पूरी तरह से फंक्शनल है, समान इनपुट्स हमेशा समान परिणाम देते हैं। चूंकि यह स्वतंत्र है, कोई भी mock या stub नहीं है। और चूंकि यह जटिल व्यावसायिक तार्किकता को संभालता है, परीक्षण हमें प्रणाली के व्यवहार के बारे में बहुत कुछ बता सकते हैं। फंक्शनल शुद्धता और निर्धारण एक छोटा तरीका उन गुणों का विवरण देना है जो शुद्ध फंक्शन्स को परीक्षण के लायक बनाते हैं यह एक मान हैं कि वे निर्धारित हैं। यह कहता है - दिए गए एक इनपुट स्ट्रीम पर, एक शुद्ध फंक्शन हमेशा समान एक output स्ट्रीम वापस करता है; उनका व्यवहार दोहराया जा सकता है। लेकिन शुद्ध फंक्शनल प्रोग्रामिंग केवल इस तकनीक तक पहुँचने का एकमात्र रास्ता नहीं है। अगर हम सिर को थोड़ा कूलो, हम देख सकते हैं कि एक मूल्यों की एक श्रृंखला और एक assignments की श्रृंखला एक ही चीज़ को विभिन्न तरीकों से व्यक्त करती हैं, और State Machines हमें समान लाभ ले सकते हैं। निम्नलिखित कोड को देखिए: function add(ns) {return ns.reduce((a, b) => a + b, 0)} class Add Machine {#state = 0 transition(input) {this.#state += input} get state() {return this.#state}} add फ़ंक्शन आसानी से समझ में आता है; यह शुद्ध है और इसलिए निर्धारित है। लेकिन Add Machine भी निर्धारित है - दिए गए transition फ़ंक्शन की समान कॉल सीक्वेंस पर, Add Machine समान state वापस करेगा। यह इम्प्रेसिव होना इसे बदलता नहीं है। const output = add([1, 2, 3]) const a = new Add Machine() a.transition(1) a.transition(2) a.transition(3) const output = a.state शुद्ध फंक्शनल प्रोग्रामिंग एक अच्छा पैराडाइम है, लेकिन कार्यक्षमता या भाषा के कारण, यह हमेशा व्यावहारिक नहीं है - मैं C में इसे करने की कोशिश नहीं करूंगा! लेकिन पूरी फंक्शनल के मापदंडों को केवल निर्धारित में कम करके, हमें Functional Core Imperative Shell के परीक्षण योग्यता के लाभ को बनाए रखते हैं, जबकि इसकी प्रयोग्यता को विस्तारित करते हैं। और इसलिए इस पोस्ट का शीर्षक: निर्धारित मूल, गैर-निर्धारित शेल। निर्धारण एक अधिक सांभलित अवधारणा हो सकता है फंक्शनल शुद्धता की तुलना में। आप इसे कब देखेंगे? मैं इसे पहचानना आसान है क्योंकि यह शुरू में वह चीज़ से शुरू करना आसान है जो निर्धारित नहीं है। यहाँ कुछ सामान्य उदाहरण हैं गैर-दोहराया जा सकने वाले व्यवहार के: जैसे कि उन्हें seed नहीं दिए गए RNG कalls Asynchronous और मल्टी-थ्रेडेड ऑपरेशन्स नेटवर्क पर संवाद करना अन्य प्रक्रियाओं के साथ संवाद करना पढ़ना लिखना local storage में डेटाबेस इंटरैक्शन्स OS को तारीख या समय मांगना सभी ये गैर-निर्धारित शेल में संपत्ति हैं। जब आप उन्हें अपनी व्यावसायिक तार्किकता में पाते हैं, तभी आपके पास एक प्राकृतिक लक्ष्य है फ्रैगमेंटेशन के लिए - या उनके आसपास फ़ंक्शन को दो भागों में बाँटना, या उन्हें एक लेयर ऊपर ले जाना और उनके परिणाम को parameter के रूप में इंजेक्ट करना। शेल की मेटाफ़ोर को साधारण रूप से समझना महत्वपूर्ण है; यह तर्क को आसपास रखना चाहिए, एप्लिकेशन के दिल को समझना है ताकि वह क्या चाहता है। वही उपलब्ध साथ काम करना यह सब बहुत अच्छा है, आप सोच सकते हैं, लेकिन मेरे पास पुराने कोड में काम करना क्या मदद करता है?