जावास्क्रिप्ट में अपरिवर्तनशीलता इतनी महत्वपूर्ण (या आवश्यक) क्यों है?


204

मैं वर्तमान में रिएक्ट जेएस और रिएक्ट नेटिव फ्रेमवर्क पर काम कर रहा हूं । जब मैं फेसबुक के फ्लक्स और रीडायरेक्शन कार्यान्वयन के बारे में पढ़ रहा था, तब आधे रास्ते में मैं इम्यूटेबिलिटी या इम्युटेबल-जेएस लाइब्रेरी में आया था।

सवाल यह है कि अपरिवर्तनशीलता इतनी महत्वपूर्ण क्यों है? वस्तुओं को बदलने में क्या गलत है? क्या यह चीजों को सरल नहीं बनाता है?

एक उदाहरण देते हुए, आइए एक साधारण समाचार रीडर ऐप पर विचार करें, जिसमें शुरुआती स्क्रीन समाचार सुर्खियों का एक दृश्य है।

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



2
अपरिवर्तनीय डेटा संरचना और शुद्ध कार्य से रेफ़रेंशियल ट्रांसपेरेंसी आती है, जिससे आपके प्रोग्राम के व्यवहार के बारे में तर्क करना बहुत आसान हो जाता है। आप कार्यात्मक डेटा संरचना का उपयोग करते समय मुफ्त में बैकट्रैकिंग भी प्राप्त कर सकते हैं।
वॉर्ब्लक्स

मैंने @bozzmob को एक Redux बिंदु प्रदान किया।
प्रोस्टि

1
जेएस के पास इसके साथ कुछ करने की सोचने की कोशिश करने के बजाय कार्यात्मक प्रतिमान की अवधारणा के रूप में सामान्य रूप से अस्थिरता के बारे में जानने के लिए उपयोगी हो सकता है। प्रतिक्रिया कार्यात्मक प्रोग्रामिंग के प्रशंसकों द्वारा लिखी गई है। आपको यह जानना होगा कि उन्हें समझने के लिए उन्हें क्या पता है।
घुमारवीं

जवाबों:


196

मैं हाल ही में एक ही विषय पर शोध कर रहा हूं। मैं आपके प्रश्न का उत्तर देने के लिए अपनी पूरी कोशिश करूँगा और जो मैंने अभी तक सीखा है उसे साझा करने का प्रयास करूँगा।

सवाल यह है कि अपरिवर्तनशीलता इतनी महत्वपूर्ण क्यों है? वस्तुओं को बदलने में क्या गलत है? क्या यह चीजों को सरल नहीं बनाता है?

मूल रूप से यह इस तथ्य के लिए नीचे आता है कि अपरिवर्तनीयता पूर्वानुमानशीलता, प्रदर्शन (अप्रत्यक्ष रूप से) को बढ़ाती है और म्यूटेशन ट्रैकिंग के लिए अनुमति देती है।

पूर्वानुमान

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

प्रदर्शन

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

सभी अपडेट नए मान लौटाते हैं, लेकिन आंतरिक रूप से संरचनाओं को मेमोरी उपयोग (और जीसी थ्रशिंग) को कम करने के लिए साझा किया जाता है। इसका मतलब यह है कि यदि आप 1000 तत्वों के साथ एक वेक्टर के लिए अपील करते हैं, तो यह वास्तव में 1001-तत्वों का एक नया वेक्टर नहीं बनाता है। सबसे अधिक संभावना है, आंतरिक रूप से केवल कुछ छोटी वस्तुओं को आवंटित किया जाता है।

आप इसके बारे में और अधिक यहाँ पढ़ सकते हैं ।

म्यूटेशन ट्रैकिंग

कम स्मृति उपयोग के अलावा, अपरिवर्तनीयता आपको संदर्भ- और मूल्य समानता का उपयोग करके अपने आवेदन का अनुकूलन करने की अनुमति देती है। यह वास्तव में यह देखने के लिए आसान बनाता है कि क्या कुछ भी बदल गया है। उदाहरण के लिए एक प्रतिक्रिया घटक में एक राज्य परिवर्तन। आप यह shouldComponentUpdateजांचने के लिए उपयोग कर सकते हैं कि क्या राज्य वस्तुओं की तुलना करके राज्य समान है और अनावश्यक रेंडरिंग को रोक सकता है। आप इसके बारे में और अधिक यहाँ पढ़ सकते हैं ।

अतिरिक्त संसाधन:

अगर मैं शुरू में एक मान के साथ वस्तुओं की एक सरणी सेट करता हूँ। मैं इसमें हेरफेर नहीं कर सकता। यही अपरिवर्तन सिद्धांत कहता है, ठीक है? (अगर मैं गलत हूं तो मुझे सुधारो)। लेकिन, क्या होगा अगर मेरे पास एक नया समाचार ऑब्जेक्ट है जिसे अपडेट करना है? सामान्य स्थिति में, मैं ऑब्जेक्ट को केवल सरणी में जोड़ सकता था। मैं इस मामले में कैसे हासिल करूं? दुकान हटाएं और इसे फिर से बनाएँ? सरणी के लिए एक वस्तु को जोड़ना एक कम महंगा ऑपरेशन नहीं है?

हां यह सही है। यदि आप अपने आवेदन में इसे लागू करने के तरीके पर भ्रमित हैं, तो मैं आपको यह देखने के लिए सलाह दूंगा कि कोर अवधारणाओं से परिचित होने के लिए यह कैसे redux करता है, इससे मुझे बहुत मदद मिली।

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

Egghead.io पर एक उत्कृष्ट Redux पाठ्यक्रम है जहां Redux के लेखक डैन अब्रामोव इन सिद्धांतों की व्याख्या करते हैं (मैं इस कोड को थोड़ा बेहतर तरीके से परिदृष्य में बदलने के लिए संशोधित करता हूं):

import React from 'react';
import ReactDOM from 'react-dom';

// Reducer.
const news = (state=[], action) => {
  switch(action.type) {
    case 'ADD_NEWS_ITEM': {
      return [ ...state, action.newsItem ];
    }
    default: {
        return state;
    }
  }
};

// Store.
const createStore = (reducer) => {
  let state;
  let listeners = [];

  const subscribe = (listener) => {
    listeners.push(listener);

    return () => {
      listeners = listeners.filter(cb => cb !== listener);
    };
  };

  const getState = () => state;

  const dispatch = (action) => {
    state = reducer(state, action);
    listeners.forEach( cb => cb() );
  };

  dispatch({});

  return { subscribe, getState, dispatch };
};

// Initialize store with reducer.
const store = createStore(news);

// Component.
const News = React.createClass({
  onAddNewsItem() {
    const { newsTitle } = this.refs;

    store.dispatch({
      type: 'ADD_NEWS_ITEM',
      newsItem: { title: newsTitle.value }
    });
  },

  render() {
    const { news } = this.props;

    return (
      <div>
        <input ref="newsTitle" />
        <button onClick={ this.onAddNewsItem }>add</button>
        <ul>
          { news.map( ({ title }) => <li>{ title }</li>) }
        </ul>
      </div>
    );
  }
});

// Handler that will execute when the store dispatches.
const render = () => {
  ReactDOM.render(
    <News news={ store.getState() } />,
    document.getElementById('news')
  );
};

// Entry point.
store.subscribe(render);
render();

इसके अलावा, ये वीडियो आगे विस्तार से प्रदर्शित करते हैं कि कैसे अपरिवर्तनीयता प्राप्त की जाए:


1
प्रतिक्रिया के लिए @naomik धन्यवाद! मेरा इरादा अवधारणा को स्पष्ट करना था और स्पष्ट रूप से यह दिखाना था कि वस्तुओं को उत्परिवर्तित नहीं किया जा रहा है और जरूरी नहीं कि यह दिखाया जाए कि इसे कैसे लागू किया जाए। हालाँकि, मेरा उदाहरण थोड़ा भ्रमित करने वाला हो सकता है, मैं इसे थोड़ा अपडेट करूँगा।
danillouz

2
@bozzmob आपका स्वागत है! नहीं, यह सही नहीं है, आपको reducer में अपरिवर्तनीयता को लागू करने की आवश्यकता है। इसका मतलब है कि आप वीडियो में प्रदर्शित की गई रणनीतियों का पालन कर सकते हैं या अपरिवर्तनीय जैसे पुस्तकालय का उपयोग कर सकते हैं। आप अधिक जानकारी यहाँ और यहाँ पा सकते हैं ।
danillouz

1
@naomik ES6 constअपरिवर्तनीयता के बारे में नहीं है। मैथियास ब्यनेंस ने इसके बारे में एक महान ब्लॉग लेख लिखा था ।
ली रोज़ेमा

1
@terabaud लिंक साझा करने के लिए धन्यवाद। मैं मानता हूं कि यह एक महत्वपूर्ण अंतर है। ^ _ ^
धन्यवाद

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

142

अपरिवर्तनीयता का एक विपरीत दृष्टिकोण

TL / DR: अपरिवर्तनशीलता जावास्क्रिप्ट में एक आवश्यकता से अधिक एक फैशन प्रवृत्ति है। यदि आप प्रतिक्रिया का उपयोग कर रहे हैं, तो यह राज्य प्रबंधन में कुछ भ्रमित डिजाइन विकल्पों के लिए एक साफ-सुथरा काम प्रदान करता है । हालांकि अधिकांश अन्य स्थितियों में यह उस जटिलता का पर्याप्त मूल्य नहीं जोड़ सकता है जो इसे पेश करता है, एक वास्तविक ग्राहक की आवश्यकता को पूरा करने के लिए एक फिर से शुरू करने के लिए अधिक सेवा प्रदान करता है।

लंबे उत्तर: नीचे पढ़ें।

जावास्क्रिप्ट में अपरिवर्तनशीलता इतनी महत्वपूर्ण (या आवश्यक) क्यों है?

खैर, मुझे खुशी है कि आपने पूछा है!

पहले एक बहुत प्रतिभाशाली बुलाया पुरुष कुछ समय दान अब्रामोव लिखा नामक एक जावास्क्रिप्ट राज्य प्रबंधन पुस्तकालय Redux जो शुद्ध कार्य करता है और अचल स्थिति का उपयोग करता है। उन्होंने कुछ बहुत अच्छे वीडियो बनाए, जिन्होंने इस विचार को समझना (और बेचना) को वास्तव में आसान बना दिया।

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

दुःख की बात यह है कि, जावास्क्रिप्ट की दुनिया में शासन चलता है। अब अब्रामोव को एक लोकतंत्र के रूप में प्रतिष्ठित किया जा रहा है और हम सभी लोगों को नश्वरता के प्रति अपने आप को अधीन करना होगा ... वेदर यह समझ में आता है या नहीं।

वस्तुओं को बदलने में क्या गलत है?

कुछ भी तो नहीं!

वास्तव में प्रोग्रामर एर के लिए वस्तुओं को म्यूट करते रहे हैं ... जब तक कि वस्तुओं को म्यूट करना है। दूसरे शब्दों में आवेदन के विकास के 50+ वर्ष

और चीजों को जटिल क्यों? जब आपके पास वस्तु है catऔर यह मर जाता है, तो क्या आपको वास्तव catमें परिवर्तन को ट्रैक करने के लिए दूसरे की आवश्यकता है ? ज्यादातर लोग बस कहते हैं cat.isDead = trueऔर इसके साथ किया जाएगा।

चीजों को सरल नहीं बनाता है?

हाँ! .. बिलकुल यह करता है!

विशेष रूप से जावास्क्रिप्ट में, जो व्यवहार में सबसे उपयोगी है कुछ राज्य के दृश्य को प्रस्तुत करने के लिए उपयोग किया जाता है जो कहीं और (जैसे डेटाबेस में) बनाए रखा जाता है।

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

ठीक है, आप पारंपरिक दृष्टिकोण पर जा सकते हैं और Newsऑब्जेक्ट को अपडेट कर सकते हैं , इसलिए आपका उस ऑब्जेक्ट का इन-मेमोरी प्रतिनिधित्व बदल जाता है (और उपयोगकर्ता को प्रदर्शित किया गया दृश्य, या ऐसा करने की उम्मीद है) ...

या वैकल्पिक रूप से ...

आप सेक्सी FP / Immutability दृष्टिकोण की कोशिश कर सकते हैं और हर ऐतिहासिक परिवर्तन को ट्रैक करने वाली एक सरणी में Newsऑब्जेक्ट में अपने परिवर्तनों को जोड़ सकते हैं ताकि आप सरणी के माध्यम से पुनरावृति कर सकें और यह पता लगा सकें कि सही राज्य प्रतिनिधित्व क्या होना चाहिए (phew!)।

मैं सीखने की कोशिश कर रहा हूं कि यहां क्या है। कृपया मुझे बताएं :)

दोस्त आते हैं और जाते हैं। एक बिल्ली की त्वचा के कई तरीके हैं।

मुझे खेद है कि आपको प्रोग्रामिंग प्रतिमानों के लगातार बदलते सेट का भ्रम सहना पड़ता है। लेकिन अरे, क्लब में आपका स्वागत है !!

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

1) बहु-थ्रेडेड वातावरणों में दौड़ की स्थिति से बचने के लिए इम्युनिटी कमाल की है

बहु-थ्रेडेड वातावरण (जैसे C ++, जावा और C #) वस्तुओं को लॉक करने के अभ्यास के लिए दोषी हैं जब एक से अधिक धागा उन्हें बदलना चाहते हैं। यह प्रदर्शन के लिए बुरा है, लेकिन डेटा भ्रष्टाचार के विकल्प से बेहतर है। और फिर भी सब कुछ अपरिवर्तनीय बनाने में उतना अच्छा नहीं है (प्रभु स्तुति हास्केल!)।

लेकिन अफसोस! जावास्क्रिप्ट में आप हमेशा एक ही धागे पर काम करते हैं । यहां तक ​​कि वेब कर्मचारी (प्रत्येक एक अलग संदर्भ के अंदर चलता है )। इसलिए जब से आप अपने निष्पादन संदर्भ (उन सभी प्यारे वैश्विक चर और करीबी) के अंदर एक थ्रेड से संबंधित दौड़ की स्थिति नहीं रख सकते हैं, तो Immutability के पक्ष में मुख्य बिंदु खिड़की से बाहर चला जाता है।

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

2) अपरिहार्यता (किसी तरह) आपके ऐप की स्थिति में दौड़ की स्थिति से बच सकती है।

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

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

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

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

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

3) दौड़ की स्थिति स्पष्ट रूप से खराब है।

ठीक है, वे हो सकता है अगर आप प्रतिक्रिया का उपयोग कर रहे हैं। लेकिन वे दुर्लभ हैं यदि आप एक अलग रूपरेखा उठाते हैं।

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

तुम्हे पता हैं। वास्तविकता। लेकिन हे, कौन परवाह करता है?

4) हर राज्य परिवर्तन पर नज़र रखने के प्रदर्शन प्रभाव को कम करने के लिए अपरिवर्तनीयता संदर्भ प्रकारों का उपयोग करती है

क्योंकि गंभीरता से, यदि आप हर बार अपने राज्य में परिवर्तन करने वाले सामान की प्रतिलिपि बनाने जा रहे हैं, तो आप बेहतर तरीके से सुनिश्चित करते हैं कि आप इसके बारे में स्मार्ट हैं।

5) अपरिवर्तनीयता आपको UNDO सामान की अनुमति देती है

क्योंकि एर .. यह नंबर एक फीचर है जो आपके प्रोजेक्ट मैनेजर के लिए पूछने जा रहा है, है ना?

6) अपरिवर्तनीय स्थिति में वेबसॉकेट के साथ संयोजन में बहुत सारी संभावनाएं हैं

अंतिम लेकिन कम से कम, राज्य डेल्टास का संचय वेबस्केट के साथ संयोजन में एक बहुत ही सम्मोहक मामला बनाता है, जो अपरिवर्तनीय घटनाओं के प्रवाह के रूप में राज्य के एक आसान उपभोग के लिए अनुमति देता है ...

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

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


अब कुछ सलाह के लिए, क्या आपको इसे स्वीकार करना चाहिए।

एफपी / इम्यूटेबिलिटी का उपयोग करके जावास्क्रिप्ट लिखने का विकल्प आपके आवेदन कोड-बेस को बड़ा, अधिक जटिल और प्रबंधन करने के लिए कठिन बनाने के लिए भी एक विकल्प है। मैं आपके Redux रिड्यूसर्स तक इस दृष्टिकोण को सीमित करने के लिए दृढ़ता से तर्क दूंगा, जब तक कि आप नहीं जानते कि आप क्या कर रहे हैं ... और यदि आप आगे बढ़ने वाले हैं और बिना किसी परवाह के उपयोग करते हैं, तो अपने पूरे आवेदन स्टैक में अपरिवर्तनीय स्थिति लागू करें , और न केवल क्लाइंट-साइड, जैसा कि आप इसका वास्तविक मूल्य याद कर रहे हैं अन्यथा।

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

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


अब स्व-चिकित्सा के इस सत्र के बाद मैं यह बताना चाहूंगा कि मैंने इसे अपने ब्लॉग में एक लेख = = जावास्क्रिप्ट में अपरिवर्तनीयता: एक कंट्रेरियन व्यू के रूप में जोड़ा है । अगर आप अपनी छाती को भी बंद करना चाहते हैं, तो मजबूत भावनाओं को महसूस करने के लिए बेझिझक जवाब दें।


10
हैलो स्टीवन, हाँ। जब मुझे अपरिवर्तनीय माना जाता था, तो मुझे ये सभी संदेह थे। लेकिन, आपका जवाब आश्चर्यजनक है! यह हर एक बिंदु को संबोधित करने के लिए बहुत अधिक मूल्य और धन्यवाद जोड़ता है, जिस पर मुझे संदेह था। अपरिवर्तनीय वस्तुओं पर महीनों तक काम करने के बाद भी यह बहुत अधिक स्पष्ट / बेहतर है।
बूजमोब

5
मैं दो वर्षों के लिए फ्लक्स / रिडक्स के साथ रिएक्ट का उपयोग कर रहा हूं और मैं आपके साथ, महान प्रतिक्रिया से सहमत नहीं हो सका!
पावेल लेसिक

6
मुझे दृढ़ता से संदेह है कि टीम और कोडबेस आकारों के लिए बड़े करीने से अपरिवर्तनीयता पर विचार होता है, और मुझे नहीं लगता कि यह कोई संयोग है कि मुख्य प्रस्तावक एक सिलिकॉन वैली विशाल है। कहा जा रहा है, मैं सम्मानपूर्वक असहमत हूं: अपरिवर्तनीयता एक उपयोगी अनुशासन है जैसे कि गोटो का उपयोग नहीं करना एक उपयोगी अनुशासन है। या इकाई परीक्षण। या टीडीडी। या स्थिर प्रकार का विश्लेषण। इसका मतलब यह नहीं है कि आप उन्हें हर समय, हर बार (हालांकि कुछ करते हैं) करते हैं। मैं यह भी कहूंगा कि उपयोगिता का प्रचार करने के लिए ऑर्थोगोनल है: उपयोगी / शानदार और सेक्सी / उबाऊ के एक मैट्रिक्स में प्रत्येक के बहुत सारे उदाहरण हैं। "hyped" !== "bad"
जारेड स्मिथ

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

4
जानकारीपूर्ण, और शानदार शीर्षक से। जब तक मुझे यह जवाब नहीं मिला, मुझे लगा कि मैं एक समान दृश्य रखने वाला एकमात्र व्यक्ति हूं। मैं अपरिवर्तनीयता के मूल्य को पहचानता हूं, लेकिन जो मुझे परेशान करता है वह यह है कि यह एक ऐसी अन्य-तकनीक-उत्पीड़क हठधर्मिता है (उदाहरण के लिए 2-वे बाइंडिंग के अवरोधन जो इनपुट स्वरूपण के लिए बेहद उपयोगी है जैसा कि नॉटआउट जेएस में लागू किया गया है)।
Tyblitz

53

सवाल यह है कि अपरिवर्तनशीलता इतनी महत्वपूर्ण क्यों है? वस्तुओं को बदलने में क्या गलत है? क्या यह चीजों को सरल नहीं बनाता है?

वास्तव में, विपरीत सच है: परिवर्तनशीलता चीजों को अधिक जटिल बनाती है, कम से कम लंबे समय में। हां, इससे आपकी शुरुआती कोडिंग आसान हो जाती है क्योंकि आप बस अपनी इच्छानुसार चीजों को बदल सकते हैं, लेकिन जब आपका कार्यक्रम बड़ा हो जाता है तो यह एक समस्या बन जाती है - यदि कोई मूल्य बदल गया, तो क्या बदल गया?

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

सीधे शब्दों में कहें: यदि आप अपरिवर्तनीय मूल्यों का उपयोग करते हैं, तो यह आपके कोड के बारे में तर्क करना बहुत आसान बनाता है: हर किसी को आपके डेटा की एक अद्वितीय * प्रतिलिपि मिलती है, इसलिए यह इसके साथ फ्यूज़ नहीं कर सकता है और आपके कोड के अन्य भागों को तोड़ सकता है। कल्पना करें कि यह बहु-थ्रेडेड वातावरण में काम करना कितना आसान है!

नोट 1: आप जो कर रहे हैं, उसके आधार पर अपरिवर्तनीयता के लिए एक संभावित प्रदर्शन लागत है, लेकिन Immutable.js जैसी चीजें सबसे अच्छा कर सकती हैं।

नोट 2: अप्रत्याशित घटना में आप निश्चित नहीं थे, Immutable.js और ES6 constबहुत अलग चीजों का मतलब है।

सामान्य स्थिति में, मैं ऑब्जेक्ट को केवल सरणी में जोड़ सकता था। मैं इस मामले में कैसे हासिल करूं? दुकान हटाएं और इसे फिर से बनाएँ? सरणी के लिए एक वस्तु को जोड़ना एक कम महंगा ऑपरेशन नहीं है? पुनश्च: यदि उदाहरण अपरिवर्तनीयता को समझाने का सही तरीका नहीं है, तो कृपया मुझे बताएं कि सही व्यावहारिक उदाहरण क्या है।

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

var originalItems = Immutable.List.of(1, 2, 3);
var newItems = originalItems.push(4, 5, 6);

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

1
मुझे खुशी है कि उत्तर उपयोगी था! अपने नए प्रश्न के बारे में: सिस्टम के बारे में अनुमान लगाने की कोशिश न करें :) इस सटीक मामले में, "स्ट्रक्चरल शेयरिंग" नामक चीज़ जीसी थ्रेशिंग को नाटकीय रूप से कम कर देती है - यदि आपके पास किसी सूची में 10,000 आइटम हैं और 10 और जोड़ते हैं, तो मेरा मानना ​​है कि अपरिवर्तनीय है। जेएस पिछले ढांचे को फिर से इस्तेमाल करने की कोशिश करेगा क्योंकि यह सबसे अच्छा हो सकता है। चलो Immutable.js स्मृति के बारे में चिंता करते हैं और संभावना है कि आप पाएंगे कि यह बेहतर है।
स्ट्रॉ

6
Imagine how much easier this makes working in a multi-threaded environment!-> अन्य भाषाओं के लिए ठीक है लेकिन यह एकल-थ्रेडेड जावास्क्रिप्ट में एक फायदा नहीं है।
स्टीवन डी सलास

1
@StevendeSalas ध्यान दें कि जावास्क्रिप्ट मुख्य रूप से अतुल्यकालिक और घटना से प्रेरित है। यह दौड़ की स्थिति के लिए बिल्कुल भी प्रतिरक्षा नहीं है।
जेरेड स्मिथ

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

37

यद्यपि अन्य उत्तर ठीक हैं, एक व्यावहारिक उपयोग के मामले के बारे में आपके प्रश्न को संबोधित करने के लिए (अन्य उत्तरों पर टिप्पणियों से) एक मिनट के लिए आपके रनिंग कोड के बाहर कदम रखें और अपनी नाक के नीचे सर्वव्यापी उत्तर को देखें: git । अगर हर बार जब आप एक कमेटी को धक्का देते हैं तो रिपॉजिटरी में डेटा को ओवरराइड करने से क्या होगा ?

अब हम उन समस्याओं में से एक हैं जो अपरिवर्तनीय संग्रह का सामना करते हैं: मेमोरी ब्लोट। हर बार जब आप बदलाव करते हैं तो हर बार फ़ाइलों की नई प्रतियां न बनाने के लिए Git काफी स्मार्ट है, यह बस डिफरेंसेस का ट्रैक रखता है

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

यह रणनीति इन-मेमोरी डेटा संरचनाओं के लिए भी यथोचित प्रदर्शन कर रही है क्योंकि इसमें प्रसिद्ध वृक्ष-संचालन एल्गोरिदम हैं जो लघुगणकीय समय में काम करते हैं।

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

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


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

3
सिर्फ इसलिए कि एक पैटर्न git में समझदारी का मतलब यह नहीं है कि हर जगह एक ही चीज समझ में आती है। वास्तव में आप संग्रहीत सभी इतिहास के बारे में परवाह करते हैं और आप विभिन्न शाखाओं को मर्ज करने में सक्षम होना चाहते हैं। सीमांत में आप राज्य के अधिकांश इतिहास की परवाह नहीं करते हैं और आपको इस जटिलता की आवश्यकता नहीं है।
स्की

2
@Ski यह केवल जटिल है क्योंकि यह डिफ़ॉल्ट नहीं है। मैं आमतौर पर अपनी परियोजनाओं में मोरी या अपरिवर्तनीय का उपयोग नहीं करता हूं: मैं हमेशा थर्ड-पार्टी डिपो लेने में संकोच करता हूं। लेकिन अगर वह डिफ़ॉल्ट (एक ला क्लोजरस्क्रिप्ट) या कम से कम एक ऑप्ट-इन देशी विकल्प था, तो मैं इसे हर समय उपयोग करूंगा, क्योंकि जब मैं क्लोजर में कार्यक्रम पसंद करता हूं तो मैं तुरंत सब कुछ परमाणुओं में नहीं भरता हूं।
जेरेड स्मिथ

जो आर्मस्ट्रांग कहते हैं कि प्रदर्शन के बारे में चिंता न करें, बस कुछ साल इंतजार करें और मूर का कानून आपके लिए ध्यान रखेगा।
ximo

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

8

सवाल यह है कि अपरिवर्तनशीलता इतनी महत्वपूर्ण क्यों है? वस्तुओं को बदलने में क्या गलत है? क्या यह चीजों को सरल नहीं बनाता है?

उत्परिवर्तन के बारे में

तकनीकी दृष्टिकोण से परिवर्तनशीलता में कुछ भी गलत नहीं है। यह तेज है, यह मेमोरी का फिर से उपयोग कर रहा है। डेवलपर्स शुरुआत से इसका उपयोग कर रहे हैं (जैसा कि मुझे याद है)। समस्या उत्परिवर्तन और परेशानियों के उपयोग में मौजूद है जो यह उपयोग ला सकता है।

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

सुस्ती सिरदर्द

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

अगली बार म्यूटेशन के साथ समस्या भ्रष्ट स्थिति है। दूषित अवस्था तब हो सकती है जब उत्परिवर्तन प्रक्रिया बीच में विफल हो जाती है, और कुछ क्षेत्रों को संशोधित किया गया और कुछ को नहीं।

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

अंत में, म्यूटेशन ट्रस्ट घाटे का कारण है। आप यह कैसे सुनिश्चित कर सकते हैं कि कुछ संरचना का मूल्य है, अगर इसे उत्परिवर्तित किया जा सकता है।

const car = { brand: 'Ferrari' };
doSomething(car);
console.log(car); // { brand: 'Fiat' }

जैसा कि ऊपर दिए गए उदाहरणों से पता चलता है कि अलग-अलग संरचना होने से हमेशा परिवर्तनशील संरचना समाप्त हो सकती है। फ़ंक्शन doSomething बाहर से दी गई विशेषता को बदल रहा है। कोड के लिए कोई भरोसा नहीं है, आप वास्तव में नहीं जानते कि आपके पास क्या है और आपके पास क्या होगा। ये सभी समस्याएं होती हैं क्योंकि: म्यूटेबल संरचनाएं मेमोरी को पॉइंटर्स का प्रतिनिधित्व कर रही हैं।

अपरिवर्तनीयता मूल्यों के बारे में है

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

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

अपरिवर्तनीय संरचनाएं मूल्यों का प्रतिनिधित्व कर रही हैं।

मैं इस विषय में मध्यम लेख में और भी अधिक गोता लगा रहा हूं - https://medium.com/@macsikora/the-state-of-immutability-169d2cd11310


6

जावास्क्रिप्ट में अपरिवर्तनशीलता इतनी महत्वपूर्ण (या आवश्यक) क्यों है?

अपरिवर्तनीयता को विभिन्न संदर्भों में ट्रैक किया जा सकता है, लेकिन सबसे महत्वपूर्ण यह होगा कि इसे एप्लिकेशन स्थिति और एप्लिकेशन UI के विरुद्ध ट्रैक किया जाए।

मैं जावास्क्रिप्ट Redux पैटर्न को बहुत फैशनेबल और आधुनिक दृष्टिकोण के रूप में मानूंगा और क्योंकि आपने इसका उल्लेख किया है।

UI के लिए हमें इसे पूर्वानुमानित करने की आवश्यकता है । यह अनुमानित होगा यदि UI = f(application state)

अनुप्रयोग (जावास्क्रिप्ट में) Reducer फ़ंक्शन का उपयोग करके कार्यान्वित किए गए कार्यों के माध्यम से राज्य को बदलते हैं ।

Reducer फ़ंक्शन केवल कार्रवाई और पुरानी स्थिति लेता है और पुराने राज्य को बरकरार रखते हुए, नया राज्य लौटाता है।

new state  = r(current state, action)

यहां छवि विवरण दर्ज करें

लाभ यह है: आप सभी राज्य वस्तुओं को सहेजे जाने के बाद से राज्यों की यात्रा करते हैं, और आप किसी भी राज्य में एप्लिकेशन को प्रस्तुत कर सकते हैं UI = f(state)

तो आप आसानी से पूर्ववत / फिर से कर सकते हैं।


इन सभी राज्यों का निर्माण होना अभी भी स्मृति के अनुकूल हो सकता है, Git के साथ एक सादृश्य महान है, और हमारे पास Linux OS में प्रतीकात्मक लिंक (इनोड्स के आधार पर) के समान समानता है।


5

जावास्क्रिप्ट में इम्युनिटी का एक और लाभ यह है कि यह टेम्पोरल कपलिंग को कम करता है, जिसमें आम तौर पर डिजाइन के लिए पर्याप्त लाभ हैं। दो तरीकों से किसी वस्तु के इंटरफेस पर विचार करें:

class Foo {

      baz() {
          // .... 
      }

      bar() {
          // ....
      }

}

const f = new Foo();

ऐसा हो सकता है कि किसी कॉल को सही ढंग से काम baz()करने के लिए एक वैध अवस्था में वस्तु प्राप्त करने के लिए कॉल करना आवश्यक हो bar()। लेकिन आप यह कैसे जानते हैं?

f.baz();
f.bar(); // this is ok

f.bar();
f.baz(); // this blows up

यह पता लगाने के लिए आपको क्लास के इन्टर्नल को जांचने की आवश्यकता है क्योंकि यह सार्वजनिक इंटरफ़ेस की जांच करने से तुरंत स्पष्ट नहीं है। यह समस्या बहुत सारे उत्परिवर्ती राज्य और कक्षाओं के साथ एक बड़े कोडबेस में विस्फोट हो सकती है।

यदि Fooअपरिवर्तनीय है तो यह अब कोई समस्या नहीं है। यह मानना ​​सुरक्षित है कि हम कॉल कर सकते हैं bazया barकिसी भी क्रम में क्योंकि कक्षा की आंतरिक स्थिति नहीं बदल सकती है।


4

एक बार, थ्रेड्स के बीच डेटा सिंक्रनाइज़ेशन के साथ एक समस्या थी। यह समस्या एक महान दर्द थी, 10+ समाधान थे। कुछ लोगों ने इसे मौलिक रूप से हल करने की कोशिश की। यह एक ऐसी जगह थी जहाँ कार्यात्मक प्रोग्रामिंग का जन्म हुआ था। यह मार्क्सवाद की तरह ही है। मैं समझ नहीं पा रहा था कि दान अब्रामोव ने जेएस में इस विचार को कैसे बेचा, क्योंकि यह एकल पिरोया हुआ है। वह जीनियस हैं।

मैं एक छोटा सा उदाहरण दे सकता हूं। __attribute__((pure))Gcc में एक विशेषता है। कंपाइलर यह हल करने की कोशिश करता है कि आपका फ़ंक्शन शुद्ध है या नहीं यदि आप इसे विशेष रूप से घोषित नहीं करेंगे। आपका कार्य शुद्ध हो सकता है यहां तक ​​कि आपका राज्य भी परिवर्तनशील है। अपरिवर्तनीयता केवल 100+ तरीकों में से एक है जो आपको गारंटी देती है कि आप कार्य शुद्ध होंगे। वास्तव में आपके 95% कार्य शुद्ध होंगे।

यदि आपको वास्तव में कोई गंभीर कारण नहीं है, तो आपको किसी भी सीमा (जैसे अपरिवर्तनीयता) का उपयोग नहीं करना चाहिए। यदि आप कुछ राज्य "पूर्ववत करें" करना चाहते हैं, तो आप लेनदेन बना सकते हैं। यदि आप संचार को सरल बनाना चाहते हैं, तो आप घटनाओं को अपरिवर्तनीय डेटा के साथ भेज सकते हैं। यह आप पर निर्भर है।

मैं यह संदेश पोस्ट मार्क्सवाद गणराज्य से लिख रहा हूं। मुझे यकीन है कि किसी भी विचार का कट्टरपंथीकरण एक गलत तरीका है।


तीसरा पैराग्राफ बहुत मायने रखता है। उसके लिये आपका धन्यवाद। 'यदि आप कुछ राज्य को "पूर्ववत" करना चाहते हैं, तो आप लेनदेन बना सकते हैं' !!
बूजमोब

मार्क्सवाद की तुलना OOP के लिए भी की जा सकती है, वैसे। जावा याद है? जैक, जावास्क्रिप्ट में जावा के विषम बिट्स? प्रचार कभी अच्छा नहीं होता है, यह कट्टरता और ध्रुवीकरण का कारण बनता है। ऐतिहासिक रूप से, OOP, Redux के फेसबुक के सम्मोहन से बहुत अधिक सम्मोहित था। हालांकि उन्होंने सुनिश्चित किया कि वे अपना सर्वश्रेष्ठ प्रयास करें।
ximo

4

एक अलग लो ...

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

टी एल; डॉ

यहां तक ​​कि छोटी परियोजनाओं में अपरिवर्तनीयता उपयोगी हो सकती है, लेकिन यह मत मानो कि यह मौजूद है क्योंकि यह आपके लिए है।

बहुत, बहुत लंबा जवाब

नोट: इस उत्तर के प्रयोजन के लिए मैं कुछ लाभ के लिए आत्म-वंचना का अर्थ 'अनुशासन' शब्द का उपयोग कर रहा हूं।

यह एक अन्य प्रश्न के रूप में समान है: "क्या मुझे टाइपस्क्रिप्ट का उपयोग करना चाहिए? जावास्क्रिप्ट में प्रकार इतने महत्वपूर्ण क्यों हैं?"। इसका एक समान उत्तर भी है। इस परिदृश्य पर विचार करें:

आप कुछ 5000 लाइनों के जावास्क्रिप्ट / सीएसएस / HTML कोडबेस के एकमात्र लेखक और अनुरक्षक हैं। आपका अर्ध-तकनीकी बॉस टाइपस्क्रिप्ट-ए-न्यू-हॉटनेस के बारे में कुछ पढ़ता है और सुझाव देता है कि हम इसे स्थानांतरित करना चाहते हैं, लेकिन निर्णय आपको छोड़ देता है। तो आप इसके बारे में पढ़ें, इसके साथ खेलें, आदि।

तो अब आपके पास बनाने के लिए एक विकल्प है, क्या आप टाइपस्क्रिप्ट में जाते हैं?

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

प्रश्न पर वापस, उपरोक्त पैराग्राफ के संदर्भ में कहा गया: क्या यह इसके लायक है ?

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

परिदृश्य B:

आप नौकरी बदलते हैं और अब फू कॉर्प पर एक लाइन-ऑफ-बिजनेस प्रोग्रामर हैं। आप 90000 एलओसी (और गिनती) पर 10 की एक टीम के साथ काम कर रहे हैं, बबेल, वेबपैक से जुड़े काफी जटिल बिल्ड पाइपलाइन के साथ जावास्क्रिप्ट / HTML / CSS कोडबेस है , पॉलीफ़िल का एक सूट, विभिन्न प्लगइन्स, एक राज्य प्रबंधन प्रणाली, ~ 20 तीसरे पक्ष के पुस्तकालय, ~ 10 आंतरिक पुस्तकालय, संपादक प्लग इन जैसे इन-हाउस स्टाइल गाइड, आदि के लिए नियमों के साथ प्रतिक्रिया करें।

जब आप 5k एलओसी के लड़के / लड़की थे, तो बस इतना ही मायने नहीं रखता था। यहां तक ​​कि प्रलेखन भी इतना बड़ा सौदा नहीं था , यहां तक ​​कि 6 महीने के बाद कोड के एक विशेष हिस्से में वापस आने पर आप इसे आसानी से समझ सकते हैं। लेकिन अब अनुशासन अच्छा नहीं बल्कि आवश्यक है । यह अनुशासन टाइपस्क्रिप्ट को शामिल नहीं कर सकता है, लेकिन इसमें कुछ हद तक स्थिर विश्लेषण के साथ-साथ कोडिंग अनुशासन (प्रलेखन, स्टाइल गाइड, बिल्ड स्क्रिप्ट, रिग्रेशन टेस्टिंग, CI) के अन्य सभी रूप शामिल होंगे । अनुशासन अब विलासिता नहीं है , यह एक आवश्यकता है

यह सब GOTO1978 में लागू किया गया था: सी में आपका डंकी थोड़ा लाठी खेल GOTOएस और स्पेगेटी तर्क का उपयोग कर सकता था और यह सिर्फ इतना बड़ा नहीं था कि इसके माध्यम से अपना रास्ता खुद ही चुना जाए, लेकिन जैसे-जैसे कार्यक्रम बड़े होते गए और अधिक महत्वाकांक्षी, अच्छी तरह से, अनुशासनहीन उपयोग को GOTOबनाए नहीं रखा जा सकता है। और यह सब आज अपरिवर्तनीयता पर लागू होता है।

स्थैतिक प्रकारों की तरह, यदि आप इंजीनियरों की एक टीम के साथ एक बड़े कोडबेस पर काम नहीं कर रहे हैं / इसका विस्तार कर रहे हैं, तो अपरिवर्तनीयता का उपयोग करने का विकल्प व्यावहारिक से अधिक सौंदर्यवादी है: यह लाभ अभी भी हैं लेकिन लागतों को आगे नहीं बढ़ा सकते हैं।

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


1
+1 मुझे अच्छा लगता है। बिंदु जारेड पर बहुत अधिक। और फिर भी अपरिहार्यता एक टीम को अनुशासन की कमी से नहीं बचाएगी। 😉
स्टीवन डी सलास

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

0

मैंने उत्परिवर्तनीय (या अपरिवर्तनीय) अवस्था के लिए एक फ्रेमवर्क एग्नोस्टिक ओपन सोर्स (एमआईटी) लिब बनाया है, जो उन सभी अपरिवर्तनीय स्टोरेज को बदल सकता है, जैसे लिबास (रिड्यूक्स, वीयूएक्स आदि ...)।

अपरिवर्तनीय स्थिति मेरे लिए बदसूरत थी क्योंकि बहुत काम करना था (सरल पढ़ने / लिखने के कार्यों के लिए बहुत सारी क्रियाएं), कोड कम पठनीय था और बड़े डेटासेट के लिए प्रदर्शन स्वीकार्य नहीं था (संपूर्ण घटक फिर से प्रस्तुत करना: /)।

साथ गहरे राज्य पर्यवेक्षक मैं डॉट नोटेशन और उपयोग वाइल्डकार्ड के साथ केवल एक नोड अद्यतन कर सकते हैं। मैं केवल उन ठोस मूल्यों को रखते हुए राज्य का इतिहास (पूर्ववत / पुनः / समय यात्रा) भी बना सकता हूं जिन्हें बदल दिया गया है {path:value}= कम स्मृति उपयोग।

साथ गहरे राज्य पर्यवेक्षक मैं फ़ाइन-ट्यून बातें कर सकते हैं और मैं घटक व्यवहार पर अनाज नियंत्रण है तो प्रदर्शन काफी सुधार किया जा सकता। कोड अधिक पठनीय है और रीफैक्टरिंग एक बहुत आसान है - बस पथ स्ट्रिंग्स को खोजें और बदलें (कोड / तर्क को बदलने की कोई आवश्यकता नहीं है)।


-1

मुझे लगता है कि मुख्य कारण समर्थक अपरिवर्तनीय वस्तुएं हैं, जो वस्तु की स्थिति को वैध रखती है।

मान लीजिए कि हमारे पास एक ऑब्जेक्ट है जिसे कहा जाता है arr। यह ऑब्जेक्ट तब मान्य होता है जब सभी आइटम एक ही अक्षर होते हैं।

// this function will change the letter in all the array
function fillWithZ(arr) {
    for (var i = 0; i < arr.length; ++i) {
        if (i === 4) // rare condition
            return arr; // some error here

        arr[i] = "Z";
    }

    return arr;
}

console.log(fillWithZ(["A","A","A"])) // ok, valid state
console.log(fillWithZ(["A","A","A","A","A","A"])) // bad, invalid state

यदि arrएक अपरिवर्तनीय वस्तु बन जाती है, तो हम सुनिश्चित करेंगे कि गिरफ्तारी हमेशा एक वैध स्थिति में हो।


मुझे लगता arrहै कि हर बार जब आप कॉल करते हैं तो उत्परिवर्तित हो जाता हैfillWithZ
रॉडरिगो-सिलवीरा

यदि आप अपरिवर्तनीय का उपयोग करते हैं। आप हर बार जब आप इसे बदलते हैं, तो आपको ऑब्जेक्ट की एक नई प्रति मिल जाएगी। इसलिए मूल वस्तु अछूती रहती है
शयनागार
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.