कम से कम ज्ञान का सिद्धांत


32

मैं कम से कम ज्ञान के सिद्धांत के पीछे के मकसद को समझता हूं , लेकिन अगर मुझे अपने डिजाइन में इसे लागू करने की कोशिश की जाए तो मुझे कुछ नुकसान हैं।

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

लेकिन ऐसा लगता है कि कभी-कभी ऐसी क्षमता का उपयोग करने की बहुत आवश्यकता होती है।

उदाहरण के लिए: मेरे पास कई वर्ग हैं: वीडियो-कैप्चर क्लास, एनकोडर क्लास, स्ट्रीमर क्लास, और वे सभी कुछ बुनियादी अन्य क्लास, वीडियोफ्रेम का उपयोग करते हैं, और चूंकि वे एक दूसरे के साथ बातचीत करते हैं, इसलिए वे उदाहरण के लिए कुछ ऐसा कर सकते हैं:

streamer कक्षा का कोड

...
frame = encoder->WaitEncoderFrame()
frame->DoOrGetSomething();
....

जैसा कि आप देख सकते हैं, यह सिद्धांत यहां लागू नहीं है। क्या इस सिद्धांत को यहां लागू किया जा सकता है, या यह है कि इस सिद्धांत को हमेशा इस तरह डिजाइन में लागू नहीं किया जा सकता है?




4
यह शायद एक करीब डुप्लिकेट है।
रॉबर्ट हार्वे

1
संबंधित: क्या कोड इस तरह है "ट्रेन मलबे" (कानून के उल्लंघन में)? (पूर्ण प्रकटीकरण: अपने ही सवाल है कि)
एक CVN

जवाबों:


21

आप जिस कार्य के लिए सिद्धांत (जिसे लॉ ऑफ डेमेटर के रूप में जाना जाता है ) के बारे में बात कर रहे हैं वह आपके स्टीमर में एक और सहायक विधि जोड़कर लागू किया जा सकता है जैसे

  {
    frame = encoder->WaitEncoderFrame()
    DoOrGetSomethingForFrame(frame); 
    ...
  }

  void DoOrGetSomethingForFrame(Frame *frame)
  {
     frame->DoOrGetSomething();
  }  

अब, प्रत्येक फ़ंक्शन केवल "दोस्तों से बात करता है", "दोस्तों के दोस्तों" के लिए नहीं।

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


इस दृष्टिकोण से इकाई परीक्षण, डिबग, और आपके कोड के बारे में बहुत आसान बनाने का लाभ होता है।
अक्टूबर को प्रातः

+1। हालाँकि, इस कोड में बदलाव करने का एक बहुत अच्छा कारण यह है कि क्लास इंटरफ़ेस उन तरीकों से फूला हुआ हो सकता है, जिनका काम केवल एक या कुछ कॉल कई अन्य तरीकों (और अतिरिक्त तर्क के बिना) में हो सकता है। कुछ प्रकार के प्रोग्रामिंग वातावरण में, C ++ COM (विशेष रूप से WIC और DirectX) का कहना है, अन्य भाषाओं की तुलना में COM इंटरफ़ेस के लिए प्रत्येक एकल विधि को जोड़ने के साथ उच्च लागत है।
rwong

1
C ++ COM इंटरफ़ेस डिज़ाइन में, बड़ी कक्षाओं को छोटी कक्षाओं में विभाजित करना (जिसका अर्थ है कि आपके पास कई ऑब्जेक्ट्स पर बात करने का एक उच्च मौका है) और इंटरफ़ेस विधियों की संख्या को कम करना गहरी समझ के आधार पर वास्तविक लाभ (लागत में कमी) के साथ दो डिज़ाइन लक्ष्य हैं आंतरिक यांत्रिकी (वर्चुअल टेबल, कोड पुन: प्रयोज्य, कई अन्य चीजें)। इसलिए C ++ COM प्रोग्रामर को आमतौर पर LoD को नजरअंदाज करना चाहिए।
rwong

10
+1: कानून के कानून को वास्तव में डिमेटर का सुझाव
बाइनरी वॉरियर

कानून का कानून वास्तुशिल्प विकल्प बनाने के लिए एक सलाह है, जबकि आप एक कॉस्मेटिक बदलाव का सुझाव देते हैं, तो ऐसा लगता है कि आप उस 'कानून' का पालन करते हैं। यह एक गलत धारणा होगी, क्योंकि एक वाक्यात्मक परिवर्तन का मतलब अचानक सब कुछ ठीक नहीं है। जहां तक ​​मुझे पता है कि लोकतंत्र के नियम का मूल रूप से मतलब है: यदि आप ओओपी करना चाहते हैं, तो हर जगह गेट्स फ़ंक्शन के साथ prodecural कोड लिखना बंद कर दें।
user2180613

39

कम से कम ज्ञान या लॉ ऑफ डेमेटर का सिद्धांत आपके वर्ग को अन्य वर्गों के विवरण के साथ उलझाने के खिलाफ एक चेतावनी है जो परत के साथ परत को पार करता है। यह आपको बताता है कि केवल अपने "दोस्तों" के साथ बात करना बेहतर है और "दोस्तों के दोस्तों" के साथ नहीं।

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

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

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

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

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

यदि आप इस समस्या का समाधान नहीं कर सकते हैं तो इस सिद्धांत का पालन करने की संभावना है कि आप गायब हैं।

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

यह वास्तव में एक और सिद्धांत का पालन करता है: निर्माण से अलग उपयोग।

frame = encoder->WaitEncoderFrame()

इस कोड का उपयोग करके आपने किसी तरह से प्राप्त करने की जिम्मेदारी ली है Frame। आपने अभी तक किसी से बात करने की जिम्मेदारी नहीं ली है Frame

frame->DoOrGetSomething(); 

अब आपको यह जानना है कि कैसे बात की जाए Frame, लेकिन उसके साथ बदलें:

new FrameHandler(frame)->DoOrGetSomething();

और अब आपको केवल यह जानना है कि अपने दोस्त से कैसे बात करें, फ्रेमहैंडलर।

इसे प्राप्त करने के कई तरीके हैं और यह, शायद, सबसे अच्छा नहीं है, लेकिन यह दिखाता है कि सिद्धांत का पालन करना समस्या को कैसे हल नहीं करता है। यह सिर्फ आपसे और काम की मांग कर रहा है।

हर अच्छे नियम में एक अपवाद होता है। सबसे अच्छा उदाहरण मुझे पता है कि आंतरिक डोमेन विशिष्ट भाषाएँ हैं । एक DSL s विधि श्रृंखलाहर समय डिमेटर के कानून का दुरुपयोग करने के लिए लगता है क्योंकि आप लगातार ऐसे तरीकों को बुला रहे हैं जो विभिन्न प्रकारों को वापस करते हैं और सीधे उनका उपयोग करते हैं। यह ठीक क्यों है? क्योंकि एक डीएसएल में जो कुछ भी दिया जाता है वह सावधानी से बनाया गया मित्र होता है जिसे आप सीधे बात करने के लिए कहते हैं। डिज़ाइन के अनुसार, आपको डीएसएल की विधि श्रृंखला को बदलने की उम्मीद नहीं करने का अधिकार दिया गया है। आपके पास यह अधिकार नहीं है कि यदि आप कोड बेतरतीब ढंग से कोड बेस में एक साथ जो कुछ भी आप पाते हैं में तल्लीन करते हैं। सबसे अच्छा DSLs बहुत पतली प्रतिनिधित्व या अन्य वस्तुओं के लिए इंटरफेस है कि आप की संभावना या तो में तल्लीन नहीं होना चाहिए। मैं केवल इस बात का उल्लेख करता हूं क्योंकि मैंने पाया कि मैंने एक बार जब मैंने सीखा कि डीएसआर एक अच्छा डिज़ाइन है, तो मैंने लोकतंत्र के कानून को बेहतर तरीके से समझा। कुछ लोग तो यहां तक ​​कहते हैं कि डीएसएल भी लोकतंत्र के वास्तविक कानून का उल्लंघन नहीं करता है।

एक और उपाय यह है कि आप कुछ और इंजेक्शन दें frame। यदि frameएक सेटर या अधिमानतः एक कंस्ट्रक्टर से आया है तो आप एक फ्रेम के निर्माण या अधिग्रहण के लिए कोई जिम्मेदारी नहीं ले रहे हैं। इसका मतलब यह है कि आप यहां भूमिका निभा रहे हैं और बहुत कुछ FrameHandlersऐसा होने जा रहा है। इसके बजाय अब आप वह हो गए हैं, जिसके साथ Frameकुछ और बात करने और यह पता लगाने का तरीका है कि कैसे प्राप्त किया जा सकता Frame है।

ठोस सिद्धांतों बड़ा मेरे द्वारा पालन करने की कोशिश कर रहे हैं। यहां सम्मानित होने वाले दो सिंगल रिस्पॉन्सिबिलिटी और डिपेंडेंसी इनवर्जन प्रिंसिपल हैं। इन दोनों का सम्मान करना वास्तव में कठिन है और फिर भी यह कानून के कानून का उल्लंघन करता है।

Demeter का उल्लंघन करने वाली मानसिकता एक बुफे रेस्तरां में खाने की तरह है, जहां आप बस जो चाहें ले लो। एक छोटे से काम के साथ आप अपने आप को एक मेनू और एक सर्वर प्रदान कर सकते हैं जो आपको आपकी पसंद का कुछ भी लाएगा। वापस बैठो, आराम करो, और अच्छी तरह से टिप।


2
"यह आपको बताता है कि केवल अपने" दोस्तों "के साथ बात करना बेहतर है और" दोस्तों के दोस्तों के साथ "नहीं। ++
रबरडैक

1
दूसरा पैराग्राफ, यह कि कहीं से चोरी हुई है, या आपने इसे बनाया है? इससे मुझे अवधारणा पूरी तरह समझ में आ गई । इससे यह स्पष्ट हो गया कि "मित्र के मित्र" क्या हैं, और बहुत सी कक्षाओं (जोड़ों) को उलझाने के लिए क्या कमियां हैं। A + बोली।
मर मौस

2
@diemaus अगर मैंने उस ढाल पैराग्राफ को कहीं से चुराया है जो मेरे स्रोत से लीक हो गया है। जिस समय मेरा दिमाग सिर्फ यह सोच रहा था कि वह चालाक है। मुझे जो याद है, वह यह है कि मैंने इसे बहुत सारे अपवॉट्स के बाद जोड़ा है, इसलिए इसे मान्य देखकर अच्छा लगता है। खुशी है कि यह मदद की।
कैंडिड_ओरेंज

19

कार्यात्मक डिजाइन वस्तु उन्मुख डिजाइन से बेहतर है? निर्भर करता है।

क्या MVVM MVC से बेहतर है? निर्भर करता है।

अमोस और एंडी या मार्टिन और लुईस? निर्भर करता है।

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

[कुछ किताब] कहती है कि [कुछ बात] गलत है।

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

इस विशेष मामले में - किसी अन्य विधि द्वारा लौटाए गए ऑब्जेक्ट पर एक विधि को कॉल करने का कार्य - चूंकि एक वास्तविक डिजाइन पैटर्न है जो इस अभ्यास (फैक्टरी) को संहिताबद्ध करता है, यह कल्पना करना मुश्किल है कि कोई यह कैसे स्पष्ट कर सकता है कि यह स्पष्ट है गलत।

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


2

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

वस्तुओं के पदानुक्रम को कम करने का एक वैकल्पिक तरीका है:

अपने तरीकों और गुणों के माध्यम से, प्रकारों के interfaceबजाय, प्रकारों को उजागर classकरें।

मूल पोस्टर (ओपी) के मामले में, के बजाय encoder->WaitEncoderFrame()वापस आ जाएगा , और परिभाषित करेगा कि क्या संचालन स्वीकार्य हैं।IEncoderFrameFrame


समाधान 1

सबसे आसान मामले में, Frameऔर Encoderकक्षाएं दोनों आपके नियंत्रण में हैं, IEncoderFrameविधियों का एक सबसेट है जो पहले से ही सार्वजनिक रूप से फ़्रेम करता है, और Encoderवर्ग वास्तव में परवाह नहीं करता है कि आप उस वस्तु का क्या करते हैं। फिर, कार्यान्वयन तुच्छ है ( c # में कोड ):

interface IEncoderFrame {
    void DoOrGetSomething();
}

class Frame : IEncoderFrame {
    // A method that already exists in Frame.
    public void DoOrGetSomething() { ... }
}

class Encoder {
    private Frame _frame;
    public IEncoderFrame TheFrame { get { return _frame; } }
    ...
}

समाधान २

एक मध्यवर्ती मामले में, जहां Frameपरिभाषा आपके नियंत्रण में नहीं है, या इसके IEncoderFrameतरीकों को जोड़ना उचित नहीं होगा Frame, तो एक अच्छा समाधान एक एडेप्टर है । यही कारण है कि CandiedOrange के उत्तर पर चर्चा की जाती है new FrameHandler( frame )। महत्वपूर्ण: यदि आप ऐसा करते हैं, तो यह अधिक लचीला है यदि आप इसे एक इंटरफ़ेस के रूप में उजागर करते हैं , एक वर्ग के रूप में नहीं । Encoderके बारे में पता है class FrameHandler, लेकिन ग्राहकों को केवल जानने की जरूरत है interface IFrameHandler। या जैसा कि मैंने इसे नाम दिया है, interface IEncoderFrame- यह इंगित करने के लिए कि यह विशेष रूप से फ़्रेम है जैसा कि एन्कोडर के पीओवी से देखा गया है :

interface IEncoderFrame {
    void DoOrGetSomething();
}

// Adapter pattern. Appropriate if no access needed to Encoder.
class EncoderFrameWrapper : IEncoderFrame {
    Frame _frame;
    public EncoderFrameWrapper( Frame frame ) {
        _frame = frame;
    }
    public void DoOrGetSomething() {
        _frame....;
    }
}

class Encoder {
    private Frame _frame;

    // Adapter pattern. Appropriate if no access needed to Encoder.
    public IEncoderFrame TheFrame { get { return new EncoderFrameWrapper( _frame ); } }

    ...
}

COST: एक नई वस्तु का आवंटन और GC, एनकोडरफ्रेमवर्पर, हर बार encoder.TheFrameकहा जाता है। (आप उस आवरण को कैश कर सकते हैं, लेकिन वह अधिक कोड जोड़ता है। और केवल मज़बूती से कोड करना आसान है यदि एनकोडर के फ़्रेम फ़ील्ड को एक नए फ्रेम के साथ प्रतिस्थापित नहीं किया जा सकता है।)


समाधान ३

अधिक कठिन मामले में, नए रैपर को दोनों के बारे में जानना होगा Encoderऔर Frame। वह वस्तु स्वयं LoD का उल्लंघन करेगी - यह एनकोडर और फ़्रेम के बीच एक संबंध में हेरफेर कर रहा है जो एनकोडर की जिम्मेदारी होनी चाहिए - और शायद सही होने के लिए दर्द हो। यदि आप उस सड़क को शुरू करते हैं तो क्या हो सकता है:

interface IEncoderFrame {
    void DoOrGetSomething();
}

// *** You will end up regretting this. See next code snippet instead ***
class EncoderFrameWrapper : IEncoderFrame {
    Encoder _owner;
    Frame _frame;
    public EncoderFrameWrapper( Encoder owner, Frame frame ) {
        _owner = owner;   _frame = frame;
    }
    public void DoOrGetSomething() {
        _frame.DoOrGetSomething();
        // Hmm, maybe this wrapper class should be nested inside Encoder...
        _owner... some work inside owner; maybe should be owner-internal details ...
    }
}

class Encoder {
    private Frame _frame;

    ...
}

वह बदसूरत हो गया। एक कम-जटिल कार्यान्वयन है, जब आवरण को अपने निर्माता / मालिक (एनकोडर) के विवरण को छूने की आवश्यकता होती है:

interface IEncoderFrame {
    void DoOrGetSomething();
}

class Encoder : IEncoderFrame {
    private Frame _frame;

    // HA! Client gets to think of this as "the frame object",
    // but its really me, intercepting it.
    public IEncoderFrame TheFrame { get { return this; } }

    // This is the method that the LoD approach suggests writing,
    // except that we are exposing it only when the instance is accessed as an IEncoderFrame,
    // to avoid extending Encoder's already large API surface.
    public void IEncoderFrame.DoOrGetSomething() {
        _frame.DoOrGetSomething();
       ... make some change within current Encoder instance ...
    }
    ...
}

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


अंतिम टिप्पणियाँ

इस पर विचार करें: यदि लागू करने वाले ने Encoderमहसूस किया कि एक्सपोज़िंग Frame frameउनकी समग्र वास्तुकला के लिए उपयुक्त था, या "LoD को लागू करने की तुलना में बहुत आसान था", तो यह ज्यादा सुरक्षित होता अगर वे पहले स्निपेट I शो करते - एक सीमित उपसमूह को बेनकाब करते। फ़्रेम, एक इंटरफ़ेस के रूप में। मेरे अनुभव में, यह अक्सर एक पूरी तरह से व्यावहारिक समाधान है। बस जरूरत के अनुसार इंटरफेस में तरीके जोड़ें। (मैं एक ऐसे परिदृश्य के बारे में बात कर रहा हूं जहां हम "जानते हैं" फ़्रेम में पहले से ही आवश्यक विधियां हैं, या वे जोड़ना आसान और गैर-विवादास्पद होगा। प्रत्येक विधि के लिए "कार्यान्वयन" कार्य इंटरफ़ेस परिभाषा में एक पंक्ति जोड़ रहा है।) और पता है कि सबसे खराब भविष्य के परिदृश्य में भी, एपीआई को काम पर रखना संभव है - यहाँ,IEncoderFrameFrameEncoder

यह भी ध्यान रखें कि यदि आप को जोड़ने के लिए अनुमति नहीं है IEncoderFrameकरने के लिए Frame, या जरूरत तरीकों सामान्य करने के लिए अच्छी तरह से फिट नहीं है Frameवर्ग, और समाधान # 2 शायद अतिरिक्त ऑब्जेक्ट निर्माण और विनाश के कारण, आप सूट नहीं करता है, समाधान # 3 को Encoderएलओडी को पूरा करने के तरीकों को व्यवस्थित करने के लिए बस एक तरीके के रूप में देखा जा सकता है । सिर्फ दर्जनों तरीकों से न गुजरें। उन्हें एक इंटरफ़ेस में लपेटें, और "स्पष्ट इंटरफ़ेस कार्यान्वयन" (यदि आप c # में हैं) का उपयोग करें, ताकि उन्हें केवल उस इंटरफ़ेस के माध्यम से देखे जाने पर एक्सेस किया जा सके।

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


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

@PeriataBreatta - मैं निश्चित रूप से इससे सहमत नहीं हूँ और इससे सहमत नहीं हूँ। लेकिन मैं एक बात बताना चाहूंगा: एक इंटरफेस , परिभाषा के अनुसार, यह दर्शाता है कि दो वर्गों के बीच सीमा पर क्या जानना चाहिए । यदि इसे "बदलने की आवश्यकता है", तो यह मौलिक है - कोई वैकल्पिक दृष्टिकोण किसी भी तरह से जादुई रूप से आवश्यक कोडिंग से बच सकता था। इसके विपरीत कि मैं जिन तीन स्थितियों का वर्णन करता हूं, उनमें से कोई भी एक इंटरफ़ेस का उपयोग नहीं कर रहा हूं - इसके बजाय, एक ठोस वर्ग लौटाएं। 1 में, फ़्रेम 2 में, एनकोडरफ्रेमवर्पर, 3 में, एनकोडर। आप अपने आप को उस दृष्टिकोण में बंद कर लेते हैं। इंटरफ़ेस उन सभी को अनुकूलित कर सकता है।
टूलमेकरसेव

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

@PeriataBreatta - और जब मैं कहता हूं "इंटरफ़ेस उन सभी को अनुकूलित कर सकता है", मैं नहीं कह रहा हूं "आह, इसकी अद्भुत है कि यह एक भाषा सुविधा इन विभिन्न मामलों को कवर कर सकती है"। मैं कह रहा हूं कि इंटरफेस को परिभाषित करना आपके द्वारा किए जा सकने वाले परिवर्तनों को कम करता है। सबसे अच्छे मामले में, डिजाइन सबसे कठिन मामले (समाधान 1) से सबसे कठिन मामले (समाधान 3) तक बदल सकता है, बिना इंटरफ़ेस बिल्कुल भी बदल सकता है - केवल निर्माता की आंतरिक आवश्यकताएं अधिक जटिल हो गई हैं। और यहां तक ​​कि जब परिवर्तन की आवश्यकता होती है, तब भी वे कम व्यापक, IMHO होते हैं।
टूलमेकर 19
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.