क्या कोई ओओ-सिद्धांत हैं जो व्यावहारिक रूप से जावास्क्रिप्ट के लिए लागू हैं?


79

जावास्क्रिप्ट एक प्रोटोटाइप-आधारित ऑब्जेक्ट ओरिएंटेड भाषा है, लेकिन कई तरह से वर्ग-आधारित बन सकता है:

  • कार्यों को स्वयं द्वारा कक्षाओं के रूप में उपयोग करने के लिए लिखना
  • एक फ्रेम में निफ्टी क्लास सिस्टम का उपयोग करें (जैसे कि म्यूटूल क्लास.क्लास )
  • इसे कॉफ़ीस्क्रिप्ट से उत्पन्न करें

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

  • Async प्रोग्रामिंग, कॉलिंग / ईवेंट का उपयोग करने वाले लेखन कोड का उपयोग करना और लिखना
  • आवश्यकता के साथ लोड हो रहा है मॉड्यूल (ताकि वे वैश्विक नाम स्थान पर लीक न हों)
  • कार्यात्मक प्रोग्रामिंग अवधारणाएं जैसे सूची समझ (मानचित्र, फ़िल्टर, आदि)
  • अन्य बातों के अलावा

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

क्या कोई सिद्धांत या पैटर्न हैं जो केवल जावास्क्रिप्ट के लिए विशिष्ट हैं? कॉलबैक नरक , बुराई से बचने , या किसी अन्य विरोधी पैटर्न आदि से बचने के लिए सिद्धांत ।

जवाबों:


116

कई संपादनों के बाद, यह उत्तर लंबाई में एक राक्षस बन गया है। मैं पहले ही माफी माँगता हूं।

eval()उदाहरण के लिए, आलसी-मूल्यांकन में उपयोग किए जाने पर सबसे पहले, हमेशा खराब नहीं होता है, और प्रदर्शन में लाभ ला सकता है। आलसी-मूल्यांकन आलसी-लोडिंग के समान है, लेकिन आप अनिवार्य रूप से स्ट्रिंग्स के भीतर अपने कोड को स्टोर करते हैं, और फिर कोड का मूल्यांकन evalया उपयोग new Functionकरते हैं। यदि आप कुछ तरकीबों का उपयोग करते हैं, तो यह बुराई की तुलना में बहुत अधिक उपयोगी हो जाएगा, लेकिन यदि आप नहीं करते हैं, तो यह खराब चीजों को जन्म दे सकता है। आप इस पैटर्न का उपयोग करने वाले मेरे मॉड्यूल सिस्टम को देख सकते हैं: https://github.com/TheHydroImpulse/resolve.js । Resolve.js new Functionमुख्य रूप से प्रत्येक मॉड्यूल में उपलब्ध CommonJS exportsऔर moduleचर को मॉडल करने के बजाय eval का उपयोग करता है , और new Functionएक अनाम फ़ंक्शन के भीतर आपके कोड को लपेटता है, हालांकि, मैं अंत में प्रत्येक मॉड्यूल को एक फ़ंक्शन में लपेटता हूं जो मैं eval के साथ संयोजन में मैन्युअल रूप से करता हूं।

आप इसके बारे में निम्नलिखित दो लेखों में पढ़ते हैं, बाद में पहले का भी जिक्र करते हैं।

सद्भाव पैदा करने वाले

अब जब जनरेटर अंततः V8 में और इस तरह से Node.js में एक झंडे ( --harmonyया --harmony-generators) के तहत उतरा है । ये आपके पास कॉलबैक नरक की मात्रा को बहुत कम कर देते हैं। यह अतुल्यकालिक कोड लिखना वास्तव में महान बनाता है।

जनरेटर का उपयोग करने का सबसे अच्छा तरीका कुछ प्रकार के नियंत्रण-प्रवाह पुस्तकालय को नियोजित करना है। यह जनरेटर के भीतर उपज जारी रखने के लिए प्रवाह करने में सक्षम होगा।

संक्षिप्त / अवलोकन:

यदि आप जनरेटर से अपरिचित हैं, तो वे विशेष कार्यों (जिन्हें जनरेटर कहा जाता है) के निष्पादन को रोकने का अभ्यास करते हैं। इस अभ्यास को कीवर्ड का उपयोग करके उपज कहा जाता है yield

उदाहरण:

function* someGenerator() {
  yield []; // Pause the function and pass an empty array.
}

इस प्रकार, जब भी आप पहली बार इस फ़ंक्शन को कॉल करते हैं, तो यह एक नया जनरेटर उदाहरण लौटाएगा। इससे आप next()जनरेटर को शुरू करने या फिर से शुरू करने के लिए उस ऑब्जेक्ट पर कॉल कर सकते हैं।

var gen = someGenerator();
gen.next(); // { value: Array[0], done: false }

आप रिटर्न मिलने nextतक फोन करते रहेंगे । इसका मतलब यह है कि जनरेटर पूरी तरह से समाप्त हो गया है, यह निष्पादन है, और अधिक विवरण नहीं हैं ।donetrueyield

बहाव को काबू करें:

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

उदाहरण:

var co = require('co');

co(function*() {
  yield query();
  yield query2();
  yield query3();
  render();
});

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

जेनरेटर अभी भी बहुत नए हैं, और इसके लिए Node.js> = v11.2 की आवश्यकता है। जैसा कि मैं यह लिख रहा हूं, v0.11.x अभी भी अस्थिर है और इस प्रकार कई देशी मॉड्यूल टूट गए हैं और v0.12 तक हो जाएंगे, जहां देशी एपीआई शांत हो जाएगा।


मेरे मूल उत्तर में जोड़ने के लिए:

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

उदाहरण के लिए एक दृश्य प्रणाली (क्लाइंट या सर्वर) लें।

view('home.welcome');

पढ़ने या अनुसरण करने में बहुत आसान है:

var views = {};
views['home.welcome'] = new View('home.welcome');

viewसमारोह बस की जाँच करता है एक ही दृश्य पहले से ही एक स्थानीय मानचित्र में मौजूद रहने पर। यदि दृश्य मौजूद नहीं है, तो यह एक नया दृश्य बना देगा और नक्शे में एक नई प्रविष्टि जोड़ देगा।

function view(name) {
  if (!name) // Throw an error

  if (view.views[name]) return view.views[name];

  return view.views[name] = new View({
    name: name
  });
}

// Local Map
view.views = {};

बेहद बुनियादी, सही? मुझे लगता है कि यह नाटकीय रूप से सार्वजनिक इंटरफ़ेस को सरल करता है और इसका उपयोग करना आसान बनाता है। मैं भी श्रृंखला-क्षमता को रोजगार ...

view('home.welcome')
   .child('menus')
   .child('auth')

टॉवर, एक फ्रेमवर्क जो मैं (किसी और के साथ) विकसित कर रहा हूं या अगले संस्करण (0.5.0) को विकसित कर रहा हूं, इसमें से अधिकांश में यह कार्यात्मक दृष्टिकोण का उपयोग करेगा।

कुछ लोग "कॉलबैक नरक" से बचने के तरीके के रूप में तंतुओं का लाभ उठाते हैं। यह जावास्क्रिप्ट के लिए एक अलग दृष्टिकोण है, और मैं इसका बहुत बड़ा प्रशंसक नहीं हूं, लेकिन कई फ्रेमवर्क / प्लेटफॉर्म इसका उपयोग करते हैं; उल्का सहित, क्योंकि वे Node.js को एक थ्रेड / प्रति कनेक्शन प्लेटफॉर्म के रूप में मानते हैं।

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

// app/config/server/routes.js
App.Router = Tower.Router.extend({
  root: Tower.Route.extend({
    route: '/',
    enter: function(context, next) {
      context.postsController.page(1).all(function(error, posts) {
        context.bootstrapData = {posts: posts};
        next();
      });
    },
    action: function(context, next) {
      context.response.render('index', context);
      next();
    },
    postRoutes: App.PostRoutes
  })
});

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

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

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

function Controller() {
    this.resource = get('resource');
}

Controller.prototype.index = function(req, res, next) {
    next();
};

Ember.js शुरू हुआ, मेरे लिए कम से कम, वस्तुओं के निर्माण के लिए एक अलग दृष्टिकोण का उपयोग करके। प्रत्येक प्रोटोटाइप विधियों का निर्माण स्वतंत्र रूप से करने के बजाय, आप एक मॉड्यूल जैसे इंटरफ़ेस का उपयोग करेंगे।

Ember.Controller.extend({
   index: function() {
      this.hello = 123;
   },
   constructor: function() {
      console.log(123);
   }
});

ये सभी अलग-अलग "कोडिंग" शैली हैं, लेकिन अपने कोड आधार में जोड़ते हैं।

बहुरूपता

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

घटना / घटक आधारित डिजाइन

इवेंट-आधारित और घटक-आधारित मॉडल विजेता IMO हैं, या काम करने में सबसे आसान हैं, खासकर जब Node.js के साथ काम करते हैं, जिसमें एक अंतर्निहित EventEmitter घटक होता है, हालांकि, ऐसे उत्सर्जकों को लागू करना तुच्छ है, यह सिर्फ एक अच्छा जोड़ है ।

event.on("update", function(){
    this.component.ship.velocity = 0;
    event.emit("change.ship.velocity");
});

बस एक उदाहरण है, लेकिन यह काम करने के लिए एक अच्छा मॉडल है। विशेष रूप से एक खेल / घटक उन्मुख परियोजना में।

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

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

पब / उप पैटर्न

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

model.subscribe("message", function(event){
    console.log(event.params.message);
});

model.publish("message", {message: "Hello, World"});

देखने वाला

यह एक व्यक्तिपरक हो सकता है, जैसा कि कुछ लोग ऑब्जर्वर पैटर्न को पब / उप के रूप में सोचने के लिए चुनते हैं, लेकिन उनके मतभेद हैं।

"ऑब्जर्वर एक डिज़ाइन पैटर्न है जहां एक ऑब्जेक्ट (एक विषय के रूप में जाना जाता है) ऑब्जेक्ट्स की एक सूची को इस पर निर्भर करता है (पर्यवेक्षक), स्वचालित रूप से उन्हें राज्य में किसी भी बदलाव के बारे में सूचित करता है।" - ऑब्जर्वर पैटर्न

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

प्रतिक्रियाशील प्रोग्रामिंग

प्रतिक्रियाशील प्रोग्रामिंग एक छोटी, अधिक अज्ञात अवधारणा है, विशेष रूप से जावास्क्रिप्ट में। एक ढांचा / पुस्तकालय है (जो मुझे पता है) कि इस "प्रतिक्रियाशील प्रोग्रामिंग" का उपयोग करने के लिए एपीआई के साथ काम करना आसान है।

प्रतिक्रियाशील प्रोग्रामिंग पर संसाधन:

असल में, यह डेटा समन्वयित करने का एक सेट है (यह चर, फ़ंक्शन, आदि ..)।

 var a = 1;
 var b = 2;
 var c = a + b;

 a = 2;

 console.log(c); // should output 4

मेरा मानना ​​है कि प्रतिक्रियात्मक प्रोग्रामिंग काफी छिपी हुई है, विशेष रूप से अनिवार्य भाषाओं में। यह विशेष रूप से Node.js. में एक अद्भुत शक्तिशाली प्रोग्रामिंग प्रतिमान है। उल्का ने खुद का रिएक्टिव इंजन बनाया है जिसमें मूल रूप से फ्रेमवर्क आधारित है। उल्का की प्रतिक्रियाशीलता पर्दे के पीछे कैसे काम करती है? यह आंतरिक रूप से कैसे काम करता है, इसका एक बड़ा अवलोकन है।

Meteor.autosubscribe(function() {
   console.log("Hello " + Session.get("name"));
});

यह सामान्य रूप से निष्पादित करेगा, के मान को प्रदर्शित करता है name, लेकिन अगर हम इसे बदलते हैं

सत्र।सेट ('नाम', 'बॉब');

यह कंसोल.लॉगिंग को री-आउटपुट करेगा Hello Bob। एक मूल उदाहरण, लेकिन आप इस तकनीक को वास्तविक समय के डेटा मॉडल और लेनदेन पर लागू कर सकते हैं। आप इस प्रोटोकॉल के पीछे बेहद शक्तिशाली सिस्टम बना सकते हैं।

उल्का के ...

प्रतिक्रियाशील पैटर्न और ऑब्जर्वर पैटर्न काफी समान हैं। मुख्य अंतर यह है कि पर्यवेक्षक पैटर्न आमतौर पर संपूर्ण वस्तुओं / वर्गों के साथ डेटा-प्रवाह का वर्णन करता है बनाम प्रतिक्रियाशील प्रोग्रामिंग विशिष्ट गुणों के बजाय डेटा-प्रवाह का वर्णन करता है।

उल्का प्रतिक्रियाशील प्रोग्रामिंग का एक शानदार उदाहरण है। जावास्क्रिप्ट के देशी मूल्य परिवर्तन की घटनाओं की कमी (सद्भाव परदे के पीछे परिवर्तन) के कारण यह रनटाइम थोड़ा जटिल है। अन्य क्लाइंट साइड चौखटे, Ember.js और AngularJS भी प्रतिक्रियाशील प्रोग्रामिंग का उपयोग (कुछ विस्तार करने के लिए)।

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

वादे

कॉलबैक के लिए ठीक नहीं है, लेकिन कुछ इंडेंटेशन निकालता है, और नेस्टेड कार्यों को न्यूनतम रखता है। यह समस्या के लिए कुछ अच्छा वाक्यविन्यास भी जोड़ता है।

fs.open("fs-promise.js", process.O_RDONLY).then(function(fd){
  return fs.read(fd, 4096);
}).then(function(args){
  util.puts(args[0]); // print the contents of the file
});

आप कॉलबैक फ़ंक्शंस भी फैला सकते हैं ताकि वे इनलाइन न हों, लेकिन यह एक और डिज़ाइन निर्णय है।

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

सिंगल फंक्शन फंक्शन

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

अंत में, मैं एक छोटे से "फ्रेमवर्क" के विकास, या उपयोग करने का सुझाव दूंगा, मूल रूप से आपके आवेदन के लिए सिर्फ एक रीढ़ की हड्डी, और अमूर्त बनाने के लिए समय लगेगा, एक घटना-आधारित प्रणाली, या "छोटे मॉड्यूल के भार" पर निर्णय लें स्वतंत्र "प्रणाली। मैंने कई Node.js परियोजनाओं के साथ काम किया है जहाँ कोड विशेष रूप से कॉलबैक नरक के साथ बेहद गड़बड़ था, लेकिन कोडिंग शुरू करने से पहले विचार की कमी भी थी। एपीआई, और वाक्यविन्यास के संदर्भ में विभिन्न संभावनाओं के माध्यम से सोचने के लिए अपना समय लें।

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

नियंत्रण का उलटा

हालांकि कॉलबैक नरक से बिल्कुल संबंधित नहीं है, यह आपको समग्र वास्तुकला में मदद कर सकता है, खासकर इकाई परीक्षणों में।

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

किसी भी प्रकार का उलटा नियंत्रण नाटकीय रूप से आपके कोड को अलग-अलग मॉड्यूल में बदल देगा जिसे कभी भी मॉकडाउन या फेक किया जा सकता है। आपके रेंडरिंग इंजन का दूसरा संस्करण बनाया गया है? बहुत बढ़िया, बस पुराने इंटरफ़ेस को नए के लिए स्थानापन्न करें। सर्विस लोकेटर विशेष रूप से नए हार्मोनी प्रॉक्सिस के साथ दिलचस्प हैं, हालांकि, केवल Node.js के भीतर प्रभावी रूप से प्रयोग करने योग्य है, यह एक अच्छे एपीआई प्रदान करता है, बल्कि तब उपयोग Service.get('render');और इसके बजाय Service.render। मैं वर्तमान में इस तरह की प्रणाली पर काम कर रहा हूं: https://github.com/TheHydroImpulse/Ettore

हालांकि स्थिर टाइपिंग की कमी (जावा, C #, PHP में निर्भरता इंजेक्शन में प्रभावी उपयोग के लिए एक संभावित कारण होने के कारण स्थैतिक टाइपिंग - यह स्थिर टाइप नहीं है, लेकिन इसके प्रकार संकेत हैं।) को एक नकारात्मक बिंदु के रूप में देखा जा सकता है, आप। निश्चित रूप से इसे एक मजबूत बिंदु में बदल दें। क्योंकि सब कुछ गतिशील है, आप एक "नकली" स्टेटिक सिस्टम को इंजीनियर कर सकते हैं। सेवा लोकेटर के साथ संयोजन में, आप प्रत्येक घटक / मॉड्यूल / वर्ग / आवृत्ति को एक प्रकार से बांध सकते हैं।

var Service, componentA;

function Manager() {
  this.instances = {};
}

Manager.prototype.get = function(name) {
  return this.instances[name];
};

Manager.prototype.set = function(name, value) {
  this.instances[name] = value;
};

Service = new Manager();
componentA = {
  type: "ship",
  value: new Ship()
};

Service.set('componentA', componentA);

// DI
function World(ship) {
  if (ship === Service.matchType('ship', ship))
    this.ship = new ship();
  else
    throw Error("Wrong type passed.");
}

// Use Case:
var worldInstance = new World(Service.get('componentA'));

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

मॉडल-व्यू-नियंत्रक

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

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

यदि आप पारंपरिक प्रोटोटाइप इंटरफेस का उपयोग कर रहे हैं, तो आपके पास MVC के साथ काम करने के लिए एक कठिन समय एक वाक्य रचना चीनी या एक अच्छा एपीआई हो सकता है, जब तक कि आप कुछ मैनुअल काम नहीं करना चाहते। Ember.js इसे "क्लास" / ऑब्जेक्ट "सिस्टम बनाकर हल करता है। एक नियंत्रक जैसा दिख सकता है:

 var Controller = Ember.Controller.extend({
      index: function() {
        // Do something....
      }
 });

अधिकांश क्लाइंट-साइड लाइब्रेरीज़, व्यू-हेल्पर्स (व्यूइंग) और टेम्प्लेट्स (व्यूज़ बनने वाले) को पेश करके MVC पैटर्न का विस्तार करती हैं।


नई जावास्क्रिप्ट विशेषताएं:

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

यह संभवतया फ़ंक्शन नेस्टिंग के साथ अधिकांश मुद्दों को ठीक करेगा और फ़ंक्शन ओवरहेड की कमी के कारण थोड़ा बेहतर प्रदर्शन लाएगा।

मुझे यकीन नहीं है कि अगर V8 इस तरह से मूल रूप से समर्थन करता है, तो आखिरी बार मैंने आपको कुछ झंडे सक्षम करने की आवश्यकता की जांच की थी, लेकिन यह Node.js के एक बंदरगाह में काम करता है जो स्पाइडरमॉन्की का उपयोग करता है

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


2
अच्छा लिख ​​दिया। मैं व्यक्तिगत रूप से MV के लिए कोई उपयोग नहीं है? पुस्तकालयों। हमारे पास सब कुछ है जिसके लिए हमें अपने कोड को और अधिक जटिल ऐप्स के लिए व्यवस्थित करने की आवश्यकता है। वे सभी मुझे जावा और सी # की बहुत याद दिलाते हैं जो सर्वर-क्लाइंट संचार में वास्तव में क्या हो रहा था, इस पर अपने स्वयं के विभिन्न बकवास-पर्दे फेंकने की कोशिश कर रहे हैं। हमें एक DOM मिला। हमें इवेंट डेलिगेशन मिला। हमें OOP मिला। मैं डेटा परिवर्तन tyvm में अपनी स्वयं की घटनाओं को बांध सकता हूं।
एरिक रिपेन

2
"कॉलबैक नरक की एक बड़ी गड़बड़ी होने के बजाय, एक कार्य के लिए एक ही फ़ंक्शन रखें, और उस कार्य को अच्छी तरह से करें।" - कविता।
जिज्ञासुविकासकर्ता

1
जावास्क्रिप्ट जब 2000 की शुरुआत में बहुत कम उम्र के माध्यम से जब कुछ समझ में आया कि बड़े अनुप्रयोगों का उपयोग कैसे लिखना है। जैसे @ErikReppen कहता है, यदि आप पाते हैं कि JS एप्लिकेशन जावा या C # एप्लिकेशन की तरह दिख रहा है तो आप इसे गलत कर रहे हैं।
backpackcoder

3

डेनियल के जवाब में जोड़ना:

अवलोकनीय मूल्य / घटक

यह विचार MVVM फ्रेमवर्क नॉकआउट .JS ( ko.observable ) से उधार लिया गया है , इस विचार के साथ कि मूल्य और वस्तुएं अवलोकन योग्य विषय हो सकते हैं, और एक बार एक मूल्य या वस्तु में परिवर्तन होने पर यह स्वचालित रूप से सभी पर्यवेक्षकों को अपडेट कर देगा। यह मूल रूप से जावास्क्रिप्ट में लागू पर्यवेक्षक पैटर्न है, और इसके बजाय कि अधिकांश पब / उप ढांचे को कैसे लागू किया जाता है, "कुंजी" एक मनमानी वस्तु के बजाय विषय है।

उपयोग निम्नानुसार है:

// the subjects
// plain old javascript object with observable values
var shipComponent = {
    velocity : observable(0)
};

// the observer, a player user interface
// implemented with revealing module pattern
var playerUi = (function(ship) {

  var module = {
    setVelocity: function (x) { 
      // ... sets the velocity on the player user interface
    },

    // only called once
    init: function() {

      // subscribe to changes on the velocity value
      // using the module's function as callback
      module.velocity.onChange(playerUi.setVelocity);
    }
  };

  return module;
})(shipComponent).init();

// the player ui will change when the velocity value is changed
shipComponent.velocity.set(10);

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

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

अवलोकन समारोह का वास्तविक कार्यान्वयन वास्तव में लिखना और समझना आश्चर्यजनक रूप से आसान है (खासकर यदि आप जानते हैं कि जावास्क्रिप्ट और प्रेक्षक पैटर्न में सरणियों को कैसे संभालना है ):

var observable = function(v) {
    var val = v, subscribers = [];

    // the observable object,
    // as revealing module
    var output = {

        // subscribes to event
        onChange : function(func) {
            // idiomatic JS to add object to the
            // subscribers array
            subscribers.push(func);

            return output: // enables chaining
        },

        // the method that changes the observable object
        // and emits the event
        set : function(v) {
            var i;
            val = v;
            for (i = 0, i < subscribers.length; i++) {
                // this is hardly fault tolerant but as long
                // as subscribers are functions it'll work
                subscribers[i](v);
            }

            return output;
        }

    };

    return output;
};

मैंने JsFiddle में अवलोकनीय वस्तु का कार्यान्वयन किया है जो इस पर जारी है कि घटकों का अवलोकन किया जा रहा है और ग्राहकों को हटाने में सक्षम है। JsFiddle प्रयोग करने के लिए स्वतंत्र महसूस करें।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.