Demeter के कानून के अनुसार, क्या किसी वर्ग को उसके किसी सदस्य को वापस करने की अनुमति है?


13

मेरे पास Demeter कानून से संबंधित तीन प्रश्न हैं।

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

छद्म कोड में:

class A {}

class B {

    private A a;

    public A getA() {
        return this.a;
    }
}

class C {

    private B b;
    private X x;

    public void main() {
        // Is it okay for B.getA to exist?
        A a = this.b.getA();

        a.doSomething();

        x.doSomethingElse(a);
    }
}

मुझे संदेह है कि डेमेटर का कानून उपरोक्त जैसे पैटर्न को मना करता है। doSomethingElse()कानून (3) का उल्लंघन न करते हुए यह सुनिश्चित करने के लिए मैं क्या कर सकता हूं ?


9
बहुत सारे लोग (विशेष रूप से कार्यात्मक प्रोग्रामर) लॉ ऑफ़ डेमेटर को एक विरोधी पैटर्न के रूप में देखते हैं। अन्य इसे "कभी-कभी उपयोगी सुझाव के रूप में देखते हैं।"
डेविड हैमेन

1
मैं इस सवाल को उठाने जा रहा हूं क्योंकि यह गैर-कानूनी लोगों के कानून को दर्शाता है। हां, LoD "कभी-कभार उपयोगी" है, लेकिन इसका आमतौर पर बेवकूफ है।
user949300

कैसे xसेट हो रहा है?
कैंडिड_ओरेंज

@ कॉन्डिडऑरेन्ज xसिर्फ एक अलग संपत्ति है जिसका मूल्य सिर्फ कुछ वस्तु है जो आह्वान करने में सक्षम है doSomethingElse
user2180613

1
आपका उदाहरण LOD का उल्लंघन नहीं करता है। एलओडी किसी वस्तु के ग्राहकों को युग्मन से उस वस्तु के आंतरिक विवरण या सहयोगियों को रोकने के बारे में है। आप जैसी चीजों से बचना चाहते हैं user.currentSession.isLoggedIn()। क्योंकि यह userन केवल userअपने सहयोगी, बल्कि इसके ग्राहकों को भी जोड़ेगा session। इसके बजाय आप लिखना चाहते हैं user.isLoggedIn()। यह आमतौर पर एक isLoggedInविधि को जोड़कर प्राप्त किया जाता है userजिसके कार्यान्वयन को प्रतिनिधि करता है currentSession
योना

जवाबों:


7

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

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

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

एग्रीगेट तक पहुंचने के नियमों के रूप में सरलीकृत एलओडी डीडीडी में बहुत बेहतर है । किसी भी बाहरी वस्तु को समुच्चय के सदस्यों के संदर्भ में नहीं रखना चाहिए। केवल एक रूट संदर्भ आयोजित किया जाना चाहिए।

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

यह भी हमेशा याद रखें कि ये सभी नियम जटिलता का प्रबंधन करने के लिए हैं, न कि खुद को हैमस्ट्रिंग करने के लिए।


1
क्या DDD कोई नियम प्रदान करता है जैसे कि कक्षा के सदस्यों जैसे डेटा को उजागर किया जा सकता है (यानी गेटर्स मौजूद होना चाहिए)? सभी चर्चाएं चारों ओर Law of Demeter, tell, don't ask, getters are evil, object encapsulationऔर single responsibility principleके रूप में वस्तु के मूल्य में हो रही है और इसके साथ कुछ करने के लिए विरोध किया जब एक डोमेन वस्तु को प्रतिनिधिमंडल इस्तेमाल किया जाना चाहिए: इस सवाल का नीचे उबालने के लिए लग रहे हैं? उन स्थितियों में अति-योग्य योग्यता लागू करने में सक्षम होना बहुत उपयोगी होगा जहां इस तरह का निर्णय किया जाना चाहिए।
user2180613

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

उस बिंदु पर विस्तार करने के लिए, जब आप बहुत सारे गेटर्स / आस्कर्स का उपयोग करते हैं, तो आमतौर पर इसका मतलब है कि आपके पास कहीं न कहीं एक बड़ी विधि है जो सब कुछ ऑर्केस्ट्रेट कर रही है, जिसे फाउलर लेनदेन स्क्रिप्ट कहते हैं। इससे पहले कि आप एक गटर का उपयोग करना शुरू करें, अपने आप से पूछें ... मैं ऑब्जेक्ट से यह डेटा क्यों मांग रहा हूं? ऑब्जेक्ट पर एक विधि में यह कार्यक्षमता क्यों नहीं है? यदि यह इस कार्यक्षमता को लागू करने के लिए इस वर्ग की जिम्मेदारी नहीं है, तो आगे बढ़ें और एक गेट्टर का उपयोग करें। Fowler द्वारा पुस्तक [Refactoring] ( martinfowler.com/books/refactoring.html ) इस तरह के सवालों के लिए सांख्यिकी पर एक पुस्तक है।
जेरेमी

अपनी किताब इंप्लीमेंटिंग डोमेन-ड्रिवेन डिज़ाइन में, वॉन वर्नॉन में लॉ ऑफ़ डेमेटर एंड टेल, डोन्ट आस्क इन च 10, पीपी 382 का उल्लेख है। यदि आपके पास इसकी पहुँच है तो यह देखने लायक हो सकता है।
जेरेमी

6

Demeter के कानून के अनुसार, क्या किसी वर्ग को उसके किसी सदस्य को वापस करने की अनुमति है?

हाँ, यह निश्चित रूप से है।

आइए मुख्य बिंदुओं को देखें :

  • प्रत्येक इकाई को केवल अन्य इकाइयों के बारे में सीमित ज्ञान होना चाहिए: केवल इकाइयां वर्तमान इकाई से संबंधित "बारीकी से"।
  • प्रत्येक इकाई को केवल अपने दोस्तों से बात करनी चाहिए; अजनबियों से बात न करें।
  • केवल अपने तात्कालिक दोस्तों से बात करें।

जिनमें से तीन आपको एक सवाल पूछते हुए छोड़ देते हैं: कौन दोस्त है?

जब फैसला करना है कि क्या वापस लौटना है, तो द लॉ ऑफ डेमेटर या कम से कम ज्ञान (एलओडी) का सिद्धांत यह निर्धारित नहीं करता है कि आप कोडर्स के खिलाफ बचाव करते हैं जो इसका उल्लंघन करने पर जोर देते हैं। यह हुक्म देता है कि आप कोडर्स को इसका उल्लंघन करने के लिए मजबूर न करें।

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

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

लंबी श्रृंखला के लिए डिज़ाइन किया जा सकता है। धाराप्रवाह इंटरफेस, iDSL, Java8 के बहुत, और अच्छे पुराने StringBuilder आप लंबी श्रृंखलाओं का निर्माण करने के लिए हैं। वे LoD का उल्लंघन नहीं करते हैं क्योंकि श्रृंखला में सब कुछ एक साथ काम करने के लिए है और एक साथ काम करने का वादा किया है। आप एक साथ सामान की श्रृंखला है जब आप एक दूसरे के बारे में कभी नहीं सुना है कि लोकतंत्र का उल्लंघन करते हैं। मित्र वे हैं जिन्होंने आपकी श्रृंखला को काम करने का वादा किया है। फ्रेंड्स ऑफ फ्रेंड्स नहीं किया।

वर्गों के अलावा जो विशेष रूप से वस्तुओं को वापस करने के लिए नियुक्त किए गए थे - जैसे कि कारखाना और बिल्डर कक्षाएं - क्या किसी वस्तु को वापस करने की विधि के लिए ठीक है, उदाहरण के लिए किसी वर्ग के गुणों में से किसी एक वस्तु को रखा जाता है या जो लोकतंत्र के कानून का उल्लंघन करता है (1) ?

यह केवल लोकतंत्र का उल्लंघन करने का अवसर पैदा करता है। यह उल्लंघन नहीं है। यह जरूरी भी बुरा नहीं है।

और अगर यह लोकतंत्र के कानून का उल्लंघन करता है, तो क्या इससे कोई फर्क पड़ेगा कि लौटाई गई वस्तु एक अपरिवर्तनीय वस्तु है जो डेटा के एक टुकड़े का प्रतिनिधित्व करती है और इस डेटा के लिए कुछ भी नहीं है (2)?

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

छद्म कोड में:

मुझे संदेह है कि डेमेटर का कानून उपरोक्त जैसे पैटर्न को मना करता है। मैं यह सुनिश्चित करने के लिए क्या कर सकता हूं कि कानून का उल्लंघन न करते हुए doSomethingElse () कहा जा सकता है?

इससे पहले कि मैं x.doSomethingElse(a)यह समझूं कि आपने मूल रूप से लिखा है

b.getA().doSomething()

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

तुम सिर्फ हाथ करने के लिए कुछ करने के लिए कहा था, तो आप एक Aबात है कि आप इस्तेमाल कर सकते हैं Aऔर परवाह नहीं होता वह कहाँ से आया और Bहो रही है के साथ एक जीवन सुखी और अपने जुनून की मुक्त रह सकता है Aसे B

के रूप में x.doSomethingElse(a)जहां की जानकारी के बिना xसे आया है, लोद सब पर कुछ भी नहीं है इसके बारे में क्या कहना है।

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

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

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


मित्रता की कुछ धारणा के कारण धाराप्रवाह इंटरफेस एक अपवाद नहीं है .... एक धाराप्रवाह इंटरफ़ेस में, श्रृंखला के प्रत्येक तरीकों को एक ही वस्तु पर बुलाया जाता है, क्योंकि वे सभी स्व वापस कर देते हैं। settings.darkTheme().monospaceFont()के लिए सिर्फ वाक्य रचना चीनी हैsettings.darkTheme(); settings.monospaceFont();
जोनाह

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

2

वर्गों के अलावा जो विशेष रूप से वस्तुओं को वापस करने के लिए नियुक्त किए गए थे [...]

मैं इस तर्क को काफी नहीं समझता। कोई भी वस्तु एक वस्तु को एक संदेश आह्वान के परिणामस्वरूप वापस कर सकती है। खासकर यदि आप "वस्तु के रूप में सब कुछ" में सोचते हैं।

कक्षाएं, हालांकि, एकमात्र ऐसी वस्तुएं हैं जो "नई" संदेश भेजकर अपनी तरह की नई वस्तुओं को तुरंत भेज सकती हैं (या अक्सर सबसे आम ओओपी भाषाओं पर नए कीवर्ड के साथ बदल दिया जाता है)


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

और आप नहीं चाहेंगे कि सी वस्तु बी के कार्यान्वयन विवरण के बारे में जाने। यह सी वस्तु के नजरिए से ए वस्तु पर एक अवांछित निर्भरता है।

तो आप अपने आप से पूछना चाहते हैं कि क्या C, A को जानकर, LOD के स्वतंत्र रूप से उसके द्वारा किए जा रहे काम के लिए बहुत अधिक नहीं जान रहा है।

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

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


0

वर्गों के अलावा जो विशेष रूप से वस्तुओं को वापस करने के लिए नियुक्त किए गए थे - जैसे कि कारखाने और बिल्डर कक्षाएं - क्या किसी वस्तु को वापस करने की विधि के लिए ठीक है?

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


उदाहरण के बारे में निहित है b.getA().doSomething()औरx.doSomethingElse(b.getA())
user2180613

A a = b.getA(); a.DoSomething();- एक डॉट पर वापस।
रॉबर्ट हार्वे

2
@ user2180613 - यदि आप इसके बारे में पूछना चाहते हैं b.getA().doSomething()और x.doSomethingElse(b.getA())आपको इसके बारे में स्पष्ट रूप से पूछना चाहिए था। जैसा कि यह खड़ा है, आपके प्रश्न के बारे में प्रतीत होता है this.b.getA()
डेविड हैमेन

1
के रूप में Aकी सदस्य नहीं है C, में नहीं बनाया Cऔर करने के लिए नहीं प्रदान की C, ऐसा लगता है कि का उपयोग कर Aमें C(जो भी ढंग से) लोद उल्लंघन करती है। काउंटिंग डॉट्स वह नहीं है जो LoD के बारे में है, यह केवल एक इलस्ट्रेटिव टूल है। Driver().getCar().getSteeringWheel().getFrontWheels().toRight()अलग-अलग बयानों में परिवर्तित करना संभव है , जिनमें से प्रत्येक में एक डॉट होता है, लेकिन एलओडी का उल्लंघन अभी भी है। मैंने इस मंच पर कई पोस्टों में पढ़ा है कि प्रदर्शन करने वाले कार्यों को उस वस्तु को सौंप दिया जाना चाहिए जो वास्तविक व्यवहार को लागू करता है tell don't ask। मान लौटाना उस के साथ विरोध करने लगता है।
user2180613

1
मुझे लगता है कि यह सच है लेकिन यह सवाल का जवाब नहीं देता है।
user2180613

0

निर्भर करता है कि आप क्या कर रहे हैं। यदि आप अपनी कक्षा के किसी सदस्य को उजागर करते हैं, जब यह किसी का व्यवसाय नहीं है कि यह आपकी कक्षा का सदस्य है, या उस सदस्य का प्रकार क्या है, तो यह एक बुरी बात है। यदि आप उस सदस्य के प्रकार को बदलते हैं, और सदस्य को लौटाने वाले फ़ंक्शन का प्रकार, और सभी को अपना कोड बदलना पड़ता है, तो यह बुराई है।

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

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