2014-09-24 9 views
12

मैं कल छुट्टी से काम करने के लिए वापस आ गया है, और हमारे दैनिक स्टैंडअप में, अपनी टीम के साथियों का उल्लेख किया है वे सभी getters और setters हटाने और मॉडल बनाने के लिए हमारे जावा कोड में मॉडल वस्तुओं के सभी पुनर्रचना गया खेतों सभी सार्वजनिक वस्तुओं के बजाय, ऐसा करने से क्योंकिडेटा मॉडल के साथ Demeter के कानून वस्तुओं

Demeter के कानून के हमारे पालन की सुविधा के लिए के लिए कारण के रूप में Demeter के कानून लागू: एक मॉड्यूल 'वस्तुओं' यह manipulates के धर्मशाला के बारे में पता नहीं करना चाहिए। के बाद से डेटा संरचनाओं कोई व्यवहार होते हैं, वे स्वाभाविक रूप से उनके आंतरिक संरचना को उजागर करता है। तो उस मामले में, डेमेटर लागू नहीं होता है।

मुझे स्वीकार है कि मुझे एलओडी के बारे में अपने ज्ञान पर ब्रश करना पड़ा, लेकिन मेरे जीवन के लिए मुझे यह संकेत देने के लिए कुछ भी नहीं मिला कि यह कानून की भावना में है। टिककर खेल में से कोई भी/हमारे मॉडल में setters किसी भी व्यापार तर्क है, जो इस ताकि इन वस्तुओं में से ग्राहकों को समझने के लिए कर रही है या नहीं, वहाँ कुछ व्यापार तर्क प्राप्त/सेट तरीकों के भीतर निष्पादित किया जा रहा है की जरूरत नहीं है के लिए अपने औचित्य है होते हैं।

मुझे लगता है कि यह एक वस्तु संरचना के आंतरिक ज्ञान की आवश्यकता के लिए क्या गलत है, या कम से कम इसे सचमुच ले रहा है और प्रक्रिया में एक सुंदर मानक सम्मेलन तोड़ रहा है।

तो मेरे सवाल है, यह वास्तव मॉडल लोद के नाम पर आंतरिक संरचना वस्तुओं के बजाय सीधे getters/setters के माध्यम से पर्दाफाश करने के लिए कोई मतलब है है?

+6

ऐसा लगता है जैसे आपके साथियों के पास पर्याप्त काम नहीं है। – Sneftel

+1

हाँ, यह समस्या है .. हमारे पास काम करने का एक टन है, और यह एक बड़ी रिफैक्टर है और 100 फाइलों की तरह छूता है। मैं वापस पुश करने के लिए जा रहा हूँ, और मैं सिर्फ यकीन है कि मैं सिर्फ से अधिक है बनाना चाहते "यह समय की बर्बादी है" (जो है, हालांकि यह के दम पर पर्याप्त होना चाहिए) – alexD

+0

सौभाग्य से आप ग्रूवी जहां 'x.getStuff उपयोग नहीं कर रहे() 'और' x.stuff' हैं अविवेच्य (और जहां क्षेत्र 'stuff' भी कॉल समय में मौजूद हो सकता है नहीं ...) –

उत्तर

14

है कि इस को शामिल किया गया एक किताब रॉबर्ट मार्टिन द्वारा स्वच्छ कोड कहा जाता है।

अध्याय 6 (वस्तुओं और डेटा संरचनाएं) में उन्होंने वस्तुओं और डेटा संरचनाओं के बीच मूलभूत अंतर के बारे में बात करती है। वस्तुओं कैप्सूलीकरण से लाभ, डेटा संरचनाओं नहीं है।

Demeter के कानून के बारे में एक वर्ग है:

एक प्रसिद्ध अनुमानी Law of Demeter कि एक मॉड्यूल वस्तुओं यह manipulates के धर्मशाला के बारे में पता नहीं करना चाहिए कहते हैं कहा जाता है। जैसा कि हमने पिछले खंड में देखा था, वस्तुएं अपना डेटा छिपाती हैं और संचालन का पर्दाफाश करती हैं। इसका मतलब यह है कि एक वस्तु इसकी आंतरिक संरचना accessors के माध्यम से इसकी आंतरिक संरचना का खुलासा नहीं करना चाहिए, क्योंकि ऐसा करने के लिए बेनकाब करने के लिए है, को छिपाने के लिए के बजाय,।

दरअसल, Demeter के कानून का कहना है कि एक विधि एक वर्ग सी के च केवल इन के तरीकों बुलाना चाहिए:

  • सी
  • च द्वारा बनाई गई एक वस्तु
  • एक वस्तु के रूप में पारित च
  • एक वस्तु सी

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

अंकल बॉब एक ​​लोद उल्लंघन का एक उदाहरण देता है:

final String outputDir = ctxt.getOptions().getScratchDir().getAbsolutePath(); 

क्या यह Demeter का उल्लंघन किया जाए या नहीं ctxt, विकल्प पर निर्भर करता है, और ScratchDir वस्तुओं या डेटा संरचनाओं हैं। यदि वे वस्तुएं हैं, तो उनकी आंतरिक संरचना को उजागर करने के बजाय छुपाया जाना चाहिए, और इसलिए उनके अंदरूनी ज्ञान का ज्ञान डेमेटर के कानून का स्पष्ट उल्लंघन है। दूसरी तरफ, यदि सीटीटीटी, विकल्प, और स्क्रैचडियर केवल डेटा संरचनाएं हैं, तो वे स्वाभाविक रूप से अपनी आंतरिक संरचना का पर्दाफाश करते हैं, और इसलिए डेमेटर लागू नहीं होता है।

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

final String outputDir = ctxt.options.scratchDir.absolutePath; 

तो यह शायद जहां अपने सहकर्मियों से आ रहे है। मुझे लगता है कि तर्क "हमें ऐसा करना है क्योंकि LoD" सर्वोत्तम रूप से कमजोर है। केंद्रीय मुद्दा लोड इतना नहीं है कि एपीआई में ऑब्जेक्ट्स या डेटा स्ट्रक्चर शामिल हैं या नहीं। ऐसा लगता है कि जब अधिक दबाव वाली चीजें होती हैं तो यह एक अनावश्यक और त्रुटि-प्रवण परिवर्तन की तरह प्रतीत होता है।

+2

समझ में आता है .. उसकी मेज पर बैठे "स्वच्छ कोड" की एक प्रति है। लगता है कि वह यह हाल ही में पढ़ रहा था :) – alexD

+0

मैं सहमत नहीं हैं। मुझे लगता है कि यह अभी भी एक समस्या है।इस बारे में सोचें - अगर आपको आउटपुट डीआईआर का उपयोग करके कक्षा का परीक्षण करने की ज़रूरत है, तो क्या आप वास्तव में पूरे ऑब्जेक्ट ट्री - सीटीटीटी, विकल्प और स्क्रैच को तुरंत चालू करना चाहते हैं? इसके बारे में एक महान बात - https://www.youtube.com/watch?v=RlfLCWKxHJ0 – alexandroid

+0

रॉबर्ट मार्टिन का "ऑब्जेक्ट्स" और "डेटा स्ट्रक्चर" के बीच भेद प्रासंगिक नहीं लगता है। "ऑब्जेक्ट्स" "डेटा संरचनाएं" हैं, "डेटा संरचनाएं" ऑब्जेक्ट्स हैं। कोड रिफैक्टरिंग के साथ-साथ "किसी अन्य परिप्रेक्ष्य से कोड को देखकर" एक दूसरे में बदल जाएगा। हो सकता है कि "डेटा संरचना" को "कंटेनर" प्रकार जैसे मानचित्र, सूची, सेट इत्यादि समझा जा सके। –

13

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

public boolean hasUnderageDrivers(Customer customer) { 
    for (Vehicle vehicle : customer.getPolicy().getVehicles()) { 
     for (Driver driver : vehicle.getDrivers()) { 
      if (driver.getAge() < 18) { 
       return true; 
      } 
     } 
    } 
    return false; 
} 

इसका कारण यह है इस कोड को अब internals के ज्ञान यह पता करने की जरूरत नहीं है कि है Demeter के कानून का उल्लंघन होगा: आप निम्नलिखित कोड कल्पना कर सकता। यह जानता है कि बीमा पॉलिसी को पूरी तरह से बीमा पॉलिसी को सौंपने के बजाय वाहनों को सौंपा गया है। यदि, भविष्य में, बीमा कंपनी ने फैसला किया कि ड्राइवर विशेष रूप से विशेष वाहनों को सौंपे जाने के बजाय नीति पर होंगे, तो इस कोड को बदलना होगा।

समस्या यह अपने पैरामीटर, getPolicy() की एक विधि कॉल, और फिर एक और, getVehicles(), और फिर एक और, getDrivers(), और फिर एक और, getAge() है। Demeter के कानून का कहना है कि एक वर्ग की एक विधि पर ही तरीकों बुलाना चाहिए:

  • ही
  • इसका क्षेत्रों
  • इसके मापदंडों
  • वस्तुओं यह

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

हम Policy वस्तु में पारित कर सकते हैं hasUnderageDrivers() साथ समस्या को ठीक करने और हम कैसे जानता है कि चाहे नीति नाबालिग ड्राइवर हैं निर्धारित करने के लिए Policy पर एक विधि हो सकता है:

public boolean hasUnderageDrivers(Policy policy) { 
    return policy.hasUnderageDrivers(); 
} 

एक स्तर कॉलिंग नीचे, customer.getPolicy().hasUnderageDrivers(), शायद — है डेमेटर का कानून अंगूठे का नियम है, न कि कठिन और तेज़ नियम। आपको शायद उन चीजों के बारे में ज्यादा चिंता करने की ज़रूरत नहीं है जिन्हें बदलने की संभावना नहीं है; Driver शायद हमेशा जन्म तिथि और getAge() विधि जारी रखने जा रहा है।

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

public boolean hasUnderageDrivers(Customer customer) { 
    for (Vehicle vehicle : customer.policy.vehicles) { 
     for (Driver driver : vehicle.drivers) { 
      if (driver.age < 18) { 
       return true; 
      } 
     } 
    } 
    return false; 
} 

(। मैं भी, driver.age करने के लिए driver.getAge() परिवर्तित कर दिया है, हालांकि कि शायद नहीं बल्कि एक साधारण क्षेत्र से जन्म तिथि के आधार एक गणना होगा)

सूचना है कि embedding के साथ सटीक एक ही समस्या ऑब्जेक्ट ग्राफ़ को एकसाथ कैसे रखा जाता है (एक ग्राहक की नीति होती है जिसमें वाहन होते हैं) मौजूद होते हैं जब हम गेटर्स के बजाय सार्वजनिक फ़ील्ड के साथ कोड लिखते हैं। समस्याएं एक साथ रखी जाती हैं कि टुकड़ों को कैसे रखा जाता है, न कि गेटर्स को बुलाया जा रहा है या नहीं।

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

+2

मेरे पास आपके (उत्कृष्ट) नीति उदाहरण के बारे में कोई प्रश्न है। क्या आप अपनी पॉलिसी ऑब्जेक्ट में बहुत से कोड के साथ समाप्त नहीं होंगे। चूंकि बीमा अनुबंधों के बारे में कुछ भी जानना चाहते हैं, तो पहले पॉलिसी ऑब्जेक्ट से पूछना होगा? – markus

+2

@markus यह सच है, आप पॉलिसी क्लास में बहुत सारे कोड के साथ समाप्त हो सकते हैं। यदि आप 'पॉलिसी' में 'हैइन्डरेज ड्रायवर 'विधि को कुछ' वाहन 'संग्रह ऑब्जेक्ट पर समान नामित विधि पर ज़िम्मेदारी पास करते हैं, तो आप बहुत कम" अग्रेषण "विधियों के साथ भी समाप्त हो सकते हैं। –

+1

@ मार्कस विकिपीडिया [इसका जिक्र करें] (https://en.wikipedia.org/wiki/Law_of_Demeter#Disadvantages): _ "विधि स्तर पर, एलओडी संकीर्ण इंटरफेस की ओर जाता है, जितनी जरूरत हो उतनी जानकारी तक पहुंच प्रदान करता है अपनी नौकरी करने के लिए, क्योंकि प्रत्येक विधि को बारीकी से संबंधित वस्तुओं के तरीकों के एक छोटे से सेट के बारे में जानने की आवश्यकता होती है। ओटीओएच, कक्षा स्तर पर, एलओडी व्यापक (यानी विस्तारित) इंटरफेस की ओर जाता है, क्योंकि एलओडी के बजाय कई सहायक विधियों को शुरू करने की आवश्यकता होती है सीधे वस्तु संरचनाओं में खुदाई करना। विस्तारित वर्ग इंटरफेस की समस्या का एक समाधान पहलू उन्मुख दृष्टिकोण है ... "_ –

0

ऑब्जेक्ट्स के साथ काम करने के बारे में डेमेटर का कानून, डेटा संरचना नहीं, आपके मामले में डीटीओ जैसा मैं समझता हूं।

Demeter के नियम को स्पष्ट है कि आप कर रहे हैं वस्तुओं के तरीकों कॉल कर सकते हैं:

  1. विधि के अंदर
  2. Cleated स्थानीय स्तर पर बहस के रूप में उत्तीर्ण
  3. उदाहरण चर (वस्तु के क्षेत्रों)
  4. वैश्विक

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

संबंधित मुद्दे