क्लास कंस्ट्रक्टर में डेटा (बनाम व्यवहार) को इंजेक्ट करने का क्या मतलब है, और इसे बुरा अभ्यास क्यों माना जाता है?


10

मैं रेमो जानसन की किताब "लर्निंग टाइपस्क्रिप्ट" पढ़ रहा हूं। एक खंड में लेखक यह वर्णन करता है कि एक बहुत ही सरल प्रूफ-ऑफ-कॉन्सेप्ट MVC फ्रेमवर्क कैसे बनाया जाए, जिसमें Modelक्लास कैसे बनाएं और निम्नलिखित बातें कहते हैं:

एक मॉडल को उस वेब सेवा के URL के साथ प्रदान करना होगा जिसे वह उपभोग करता है। हम उपभोग किए जाने वाले सेवा का URL सेट करने के लिए ModelSettings नामक एक वर्ग सज्जाकार का उपयोग करने जा रहे हैं। हम इसके निर्माणकर्ता के माध्यम से सेवा URL को इंजेक्ट कर सकते हैं, लेकिन इसे एक कक्षा के माध्यम से डेटा को इंजेक्ट करने के लिए एक बुरा व्यवहार माना जाता है (एक व्यवहार के विपरीत)

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

class Person {
  constructor(name) {
    this.name = name;
  }
}

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

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


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

@ModelSettings("./data/nasdaq.json")
class NasdaqModel extends Model implements IModel {
  constructor(metiator : IMediator) {
    super(metiator);
  }
...
}

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

constructor(metiator : IMediator, serviceUrl : string) {...

मेरा सुझाव है कि आप निर्भरता इंजेक्शन के बारे में Google पर त्वरित खोज करें । यह सवाल पूछने का सही मंच नहीं है। :)
टॉस्क

1
मैं आपकी प्रतिक्रिया को दिल से लगाऊंगा, लेकिन मैंने Google को खोजा है, और निर्भरता इंजेक्शन की चर्चाओं का सामना किया है। क्या "निर्भरता इंजेक्शन" और "डेटा इंजेक्शन" एक ही बात का जिक्र कर रहे हैं? इसके अलावा, यह मेरी धारणा है कि "निर्भरता इंजेक्शन" एक "अच्छी बात है" (या कम से कम एक "वैकल्पिक चीज"), जबकि मेरे द्वारा प्रदान की गई बोली में "डेटा इंजेक्शन" की चर्चा इसे "बुरी चीज" लगती है। ।

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

1
"डेटा इंजेक्शन" हमले हैं, मेरा मानना ​​है कि एक बहुत अलग जानवर है कि उद्धृत पुस्तक के लेखक के बारे में क्या बात करता है जब वह "डेटा इंजेक्ट करता है"। यही कारण है कि मैं इस पर Google खोजों से निराश हूं। यहां तक ​​कि अगर मुझे समझने की आवश्यकता है, उदाहरण के लिए, SOLID सिद्धांतों को बेहतर ढंग से, मुझे समझ में नहीं आता है कि एक "व्यक्ति" रचनाकार के लिए एक पैरामीटर के रूप में "नाम" कैसे सामान्य और ठीक है, लेकिन "मॉडल" के लिए एक पैरामीटर के रूप में "सर्विस यूआरएल" प्रदान करना है। कंस्ट्रक्टर अनुचित है, या यह "नाम" / "व्यक्ति" उदाहरण से कैसे अलग है।

7
मुझे लगता है कि रेमो से गलती हुई है। पैरामीटर हैं डेटा, कोई फर्क नहीं पड़ता कि वह क्या कहते हैं। जो डेटा इंजेक्ट किया जाता है, उसमें हमेशा एक प्रकार होता है, और सभी प्रकार की ऑब्जेक्ट-ओरिएंटेड भाषाओं में किसी प्रकार का व्यवहार होता है।
रॉबर्ट हार्वे

जवाबों:


5

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

मेरे सिर के ऊपर से, मैं विभिन्न स्थितियों के बारे में सोच सकता हूं जहां निर्माणकर्ता के माध्यम से डेटा पास करना अच्छा है, कुछ जो तटस्थ हैं, लेकिन कोई भी ऐसा नहीं है जहां यह खराब है।

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

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

यदि आप चाहते हैं कि उत्परिवर्तित वस्तुएं हैं, तो भी यह कैसे बुरा है:

var blah = new Rectangle(x,y,width,height);

पक्ष में:

var blah = new Rectangle();
blah.X = x;
blah.Y = y;
blah.Width = width;
blah.Height = height;

क्या लेखक वास्तव में सोचता है कि पहला बुरा अभ्यास है और मुझे हमेशा विकल्प 2 के साथ जाना चाहिए? मुझे लगता है कि वह पागल बात है।

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


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

0

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

स्टेटलेस सर्विस के कई फायदे हैं, उदाहरण के लिए, सर्विस मेथड कॉल पढ़ने वाले किसी व्यक्ति को यह देखने की जरूरत नहीं है कि सर्विस का निर्माण सेवा के विवरण का पता लगाने के लिए किया गया है। सभी विवरण विधि कॉल (दूरस्थ url को छोड़कर) में उपयोग किए जा रहे तर्कों में दिखाए गए हैं।


हां, मॉडल को डेटा को पुनः प्राप्त करने की आवश्यकता है (अंततः एक दूरस्थ वेब सेवा से जैसा कि आप सुझाव देते हैं, लेकिन पुस्तक में यह सिर्फ एक डेमो है, इसलिए यह शुरू में सिर्फ सीधे इनलाइन कोड किए गए डेटा को नकली करता है)। मैं डेटा को "वेब सेवा के तरीकों में" तर्क के रूप में पारित करने के बारे में आपके सुझाव को नहीं समझ रहा हूँ। मैं एक डेकोरेटर के लिए एक कंस्ट्रक्टर बनाम (2) के लिए मापदंडों (1) के रूप में डेटा को अलग करने के बारे में पूछ रहा था। आप वेब सेवा की एक विधि के लिए पैरामीटर / तर्कों के रूप में डेटा, यानी एक 3 विकल्प का सुझाव दे रहे हैं। क्या मुझे आपकी बात याद आ रही है?
एंड्रयू विल्म्स

0

सिर्फ अनुमान।

अगर मैं 'व्यवहार को इंजेक्ट करता हूं, डेटा को नहीं', तो मैं ऐसा करने के बजाय सोचूंगा:

(छद्मकोश में उदाहरण के लिए क्षमा करें):

class NoiseMaker{
  String noise;
  NoiseMaker(String noise){
     this.noise = noise;
  }
  void soNoise(){
    writeToOutput(noise)
  }
}

यह करने के लिए:

interface Noise{
  String getAudibleNoise();
}

class PanicYell implements Noise{
   String getAudibleNoise(){
       return generateRandomYell();
   }
   .....
}



class WhiteNoise implements Noise{
   String getAudibleNoise(){
       return generateNoiseAtAllFrequences();
   }
   .....
}

class NoiseMaker{
  Noise noise;
  NoiseMaker(Noise noise){
     this.noise = noise;
  }
  void soNoise(){
    writeToOutput(noise.getAudibleNoise())
  }
}

इस तरह आप हमेशा शोर के व्यवहार को बदल सकते हैं, इसे यादृच्छिक बना सकते हैं, एक आंतरिक चर पर निर्भर ...

मुझे लगता है कि यह सब 'वंशानुक्रम पर समग्रता' के नियम के बारे में है। जो एक महान नियम है, मुझे कहना होगा।

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

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