गेटर्स में कितना लॉजिक है


46

मेरे सहकर्मी मुझे बताते हैं कि गेटर्स और सेटर में जितना संभव हो उतना कम तर्क होना चाहिए।

फिर भी, मुझे विश्वास है कि कार्यान्वयन विवरण से उपयोगकर्ताओं / प्रोग्रामरों को ढालने के लिए ढेर सारा सामान गेटर्स में छिपाया जा सकता है।

मैं क्या करूं इसका एक उदाहरण:

public List<Stuff> getStuff()
{
   if (stuff == null || cacheInvalid())
   {
       stuff = getStuffFromDatabase();
   }
   return stuff;
}

काम कैसे करने के लिए कहता है इसका एक उदाहरण (वे अंकल बॉब से 'क्लीन कोड' उद्धृत करते हैं):

public List<Stuff> getStuff()
{
    return stuff;
}

public void loadStuff()
{
    stuff = getStuffFromDatabase();
}

सेटर / गेटटर में कितना तर्क उचित है? डेटा को छिपाने के अलावा खाली गेटर्स और सेटर का उपयोग क्या है?


6
यह मेरे लिए TryGetStuff () की तरह दिखता है ...
Bill Michell

16
यह कोई 'गेट्टर' नहीं है। इस शब्द का उपयोग किसी संपत्ति के रीड एक्सेसर के लिए किया जाता है, न कि एक विधि से जिसे आपने गलती से नाम में 'प्राप्त' कर लिया है।
बोरिस यांकोव 20

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

@BorisYankov खैर ... दूसरा तरीका है। public List<Stuff> getStuff() { return stuff; }
आर। श्मिट

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

जवाबों:


71

काम करने का तरीका बताता है कि यह काम लंगड़ा है।

अंगूठे के एक नियम के रूप में, मैं जिस तरह से चीजें करता हूं वह इस प्रकार है: यदि सामान प्राप्त करना कम्प्यूटेशनल रूप से सस्ता है, (या अगर अधिकांश संभावना है कि यह कैश में मिल जाएगा), तो आपके गेटस्टफ () की शैली ठीक है। यदि सामान प्राप्त करना कम्प्यूटेशनल रूप से महंगा माना जाता है, इतना महंगा है कि इंटरफ़ेस पर इसकी विस्तारशीलता का विज्ञापन करना आवश्यक है, तो मैं इसे गेटस्टफ () नहीं कहूंगा, मैं इसे कैलक्स्टस्टफ () या ऐसा कुछ कहूंगा, ताकि संकेत मिल सके। कुछ काम करना होगा।

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


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

6
मैं आमतौर पर "यदि यह वास्तव में सस्ता है, तो एक संपत्ति पाने वाले का उपयोग करें। यदि यह महंगा है, तो एक फ़ंक्शन का उपयोग करें" के नियम का पालन करें। यह आमतौर पर मुझे अच्छी तरह से कार्य करता है, और उचित रूप से नाम देने पर जैसे आपने जोर देने के लिए संकेत दिया कि यह मुझे भी अच्छा लगता है।
डेनिस ट्रोलर

3
अगर यह विफल हो सकता है - यह एक गटर नहीं है। ऐसे में अगर DB लिंक डाउन हो जाए तो क्या होगा?
मार्टिन बेकेट

6
+1, मैं इस बात से सदमे में हूं कि कितने गलत उत्तर पोस्ट किए गए हैं। कार्यान्वयन विवरण को छिपाने के लिए गेटर्स / सेटर्स मौजूद हैं, अन्यथा चर को केवल सार्वजनिक किया जाना चाहिए।
इजाकाता

2
यह मत भूलो कि loadStuff()फ़ंक्शन से पहले फ़ंक्शन को कॉल करने की आवश्यकता है getStuff()इसका मतलब यह भी है कि वर्ग ठीक से अमूर्त नहीं है जो हुड के नीचे चल रहा है।
rjzii

23

गेटर्स में लॉजिक पूरी तरह से ठीक है।

लेकिन एक डेटाबेस से डेटा प्राप्त करना "तर्क" की तुलना में बहुत अधिक है। इसमें बहुत महंगे संचालन की एक श्रृंखला शामिल है जहां बहुत सारी चीजें गलत हो सकती हैं, और गैर-नियतात्मक तरीके से। मैं संकोच करता हूँ कि एक गटर में निहित है।

दूसरी ओर, अधिकांश ORM संग्रह के आलसी लोडिंग का समर्थन करते हैं, जो मूल रूप से वास्तव में आप क्या कर रहे हैं।


18

मुझे लगता है कि 'क्लीन कोड' के अनुसार इसे जितना संभव हो उतना विभाजित किया जाना चाहिए:

public List<Stuff> getStuff() {
   if (hasStuff()) {
       return stuff;
   }
   loadStuff();
   return stuff;
}

private boolean hasStuff() {
    if (stuff == null) {
       return false;
    }
    if (cacheInvalid()) {
       return false;        
    }
    return true;
} 

private void loadStuff() {
    stuff = getStuffFromDatabase();
}

बेशक, यह पूरी तरह से बकवास है, यह देखते हुए कि सुंदर रूप, जो आपने लिखा था, कोड के एक अंश के साथ सही काम करता है जिसे कोई भी एक नज़र में समझता है:

public List<Stuff> getStuff() {
   if (stuff == null || cacheInvalid()) {
       stuff = getStuffFromDatabase();
   }
   return stuff;
}

यह कॉलर के सिरदर्द नहीं होना चाहिए कि सामान को हुड के नीचे कैसे रखा गया है, और विशेष रूप से यह कॉलर का सिरदर्द नहीं होना चाहिए ताकि कुछ मनमाने "सही क्रम" में चीजों को याद कर सकें।


8
-1। असली सिरदर्द तब होगा जब कॉल करने वाला फंस गया हो कि एक साधारण गेट्टर कॉल के कारण धीमे-धीमे नरक में प्रवेश कैसे हुआ।
डोमोनिक

14
@ डोमिनिक: डेटाबेस एक्सेस वैसे भी किया जाना है, आप ऐसा नहीं करके किसी भी प्रदर्शन को बचा रहे हैं। यदि आपको इसकी आवश्यकता है List<Stuff>, तो इसे प्राप्त करने का केवल एक ही तरीका है।
डेडएमजेड डीएएम 23'11

4
@ लुकास: धन्यवाद, मुझे 'क्लीन' कोड में इस्तेमाल किए जाने वाले सभी ट्रिक्स याद नहीं थे, जो अब एक पंक्ति के ट्राइवियल बिट्स को एक पंक्ति में बनाते हैं; अब;
जूनास पुलकाका

2
आप रॉबर्ट मार्टिन की निंदा कर रहे हैं। वह नौ लाइन फ़ंक्शन में एक साधारण बूलियन डिसंक्शन का विस्तार कभी नहीं करेगा। आपका फ़ंक्शन hasStuffक्लीन कोड के विपरीत है।
केविन क्लाइन

2
मैंने इस उत्तर की शुरुआत को पढ़ा, और मैं इसे दरकिनार करने जा रहा था, यह सोचकर कि "एक और पुस्तक उपासक चला जाता है", और फिर "बेशक, यह पूरी बकवास है" भाग ने मेरी आंख पकड़ ली। खूब कहा है! C -: =
माइक नाकिस

8

वे मुझे बताते हैं कि गेटर्स और सेटर में जितना संभव हो उतना कम तर्क होना चाहिए।

वर्ग की जरूरतों को पूरा करने के लिए जितना तर्क आवश्यक है, उतना ही होना भी चाहिए। मेरी व्यक्तिगत प्राथमिकता यथासंभव कम है, लेकिन जब कोड बनाए रखते हैं, तो आपको आमतौर पर मूल इंटरफ़ेस को मौजूदा गेटर्स / सेटर्स के साथ छोड़ना पड़ता है, लेकिन नए व्यावसायिक तर्क को सही करने के लिए उनमें बहुत सारे तर्क दिए जाते हैं (उदाहरण के लिए, "ग्राहक" 911 के बाद के वातावरण में " गेट्टर को अपने ग्राहक को जानना है" और ओएफएसी नियमों को पूरा करना होगा, जो कि कुछ देशों के ग्राहकों को दिखने से रोकती है, जैसे कि [क्यूबा या ईरान]।

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


6

आप सही हैं, आपके सहयोगी गलत हैं।

एक विधि प्राप्त करने या नहीं करने के बारे में अंगूठे के सभी नियमों को भूल जाएं। एक वर्ग को किसी चीज का अमूर्तन प्रस्तुत करना चाहिए। आपकी कक्षा पठनीय है stuff। जावा में गुणों को पढ़ने के लिए 'प्राप्त' विधियों का उपयोग करना पारंपरिक है। अरबों रूपरेखाओं को stuffकॉल करके पढ़ने की अपेक्षा की गई है getStuff। यदि आप अपने फ़ंक्शन fetchStuffया इसके अलावा कुछ भी नाम देते हैं getStuff, तो आपका वर्ग उन सभी रूपरेखाओं के साथ असंगत होगा।

आप उन्हें हाइबरनेट को इंगित कर सकते हैं, जहां 'getStuff ()' कुछ बहुत ही जटिल चीजें कर सकता है, और विफलता पर एक RuntimeException फेंकता है।


हाइबरनेट एक ओआरएम है, इसलिए पैकेज खुद ही आशय व्यक्त करता है। यह आशय इतनी आसानी से नहीं समझा जा सकता है यदि पैकेज स्वयं एक ओआरएम नहीं है।
FMJaguar

@FMJaguar: यह पूरी तरह से आसानी से समझा जाता है। वस्तुओं के एक नेटवर्क को प्रस्तुत करने के लिए डेटाबेस के संचालन को हाइबरनेट करें। ओपी एक ऑब्जेक्ट को प्रस्तुत करने के लिए एक डेटाबेस ऑपरेशन को सार कर रहा है जिसमें एक संपत्ति है जिसका नाम है stuff। दोनों कॉलिंग कोड लिखना आसान बनाने के लिए विवरण छिपाते हैं।
केविन क्लाइन

यदि वह वर्ग एक ORM वर्ग है, तो इरादे पहले से ही व्यक्त किए जाते हैं, अन्य संदर्भों में: सवाल यह है कि: "एक अन्य प्रोग्रामर को गेटर को कॉल करने के दुष्प्रभावों को कैसे पता चलता है?"। यदि प्रोग्राम में 1k कक्षाएं और 10k गेटर्स शामिल हैं, तो एक नीति जो उनमें से किसी में डेटाबेस कॉल की अनुमति देती है
FMJaguar

4

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

List<String> names = clientRoster.getNames();
List<String> emails = clientRoster.getEmails();

विरोध के रूप में:

myObject.load();
List<String> names = clientRoster.getNames();
List<String> emails = clientRoster.getEmails();

या इससे भी बदतर:

myObject.loadNames();
List<String> names = clientRoster.getNames();
myOjbect.loadEmails();
List<String> emails = clientRoster.getEmails();

जो सिर्फ अन्य कोड को बहुत अधिक निरर्थक और पढ़ने में कठिन बनाता है क्योंकि आपको सभी समान कॉल के माध्यम से वैडिंग शुरू करना है। इसके अतिरिक्त, लोडर फ़ंक्शन या समान कॉलिंग OOP का उपयोग करने के पूरे उद्देश्य को भी तोड़ देती है जिसमें आप उस ऑब्जेक्ट के कार्यान्वयन विवरण से दूर नहीं रह जाते हैं जिसके साथ आप काम कर रहे हैं। यदि आपके पास कोई clientRosterऑब्जेक्ट है, तो आपको इस बात की परवाह नहीं करनी चाहिए कि कैसे getNamesकाम करता है, जैसा कि यदि आपको कॉल करना है loadNames, तो आपको बस यह पता होना चाहिए कि getNamesआपको List<String>क्लाइंट्स के नाम दिए गए हैं।

इस प्रकार, लगता है कि इस मुद्दे को शब्दार्थ के बारे में अधिक है और डेटा प्राप्त करने के लिए फ़ंक्शन का सबसे अच्छा नाम है। यदि कंपनी (और अन्य) के पास getऔर setउपसर्ग के साथ कोई समस्या है , तो फ़ंक्शन को retrieveNamesइसके बजाय कुछ कॉल करने के बारे में कैसे ? यह कहता है कि क्या हो रहा है, लेकिन इसका मतलब यह नहीं है कि यह ऑपरेशन तात्कालिक होगा क्योंकि एक getविधि की उम्मीद की जा सकती है ।

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


2

एक कॉल्टर को एक फ़ील्ड पढ़ने के समान व्यवहार प्रदर्शित करना चाहिए:

  • मान प्राप्त करने के लिए यह सस्ता होना चाहिए
  • यदि आप सेटर के साथ एक मान सेट करते हैं और फिर इसे गेटर से पढ़ते हैं, तो मान समान होना चाहिए
  • मूल्य प्राप्त करने का कोई दुष्प्रभाव नहीं होना चाहिए
  • इसे अपवाद नहीं फेंकना चाहिए

2
मैं इस पर पूरी तरह सहमत नहीं हूं। मैं मानता हूं कि इसका कोई साइड इफेक्ट नहीं होना चाहिए, लेकिन मुझे लगता है कि इसे इस तरह से लागू करना पूरी तरह से ठीक है जो इसे एक क्षेत्र से अलग करता है। .Net BCL को देखते हुए, गेट्स को देखते समय InvalidOperationException का व्यापक रूप से उपयोग किया जाता है। इसके अलावा, ऑर्डर ऑफ ऑपरेशंस पर माइक नैकिस का जवाब देखें।
अधिकतम

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

1
@TMN: एक बेहतरीन स्थिति में वर्ग को इस तरह से व्यवस्थित किया जाना चाहिए कि गेटर्स को अपवाद के संचालन में सक्षम संचालन चलाने की आवश्यकता न हो । उन जगहों को कम से कम करना जो अपवादों को फेंक सकते हैं, कम अप्रत्याशित आश्चर्य की ओर ले जाते हैं।
हुगोमग

8
मैं एक विशिष्ट उदाहरण के साथ दूसरे बिंदु से असहमत होने जा रहा हूं foo.setAngle(361); bar = foo.getAngle():। barहो सकता है 361, लेकिन यह वैध रूप से भी हो सकता है 1यदि कोण किसी सीमा से बंधे हों।
zzzzBov 15

1
-1। (1) है इस उदाहरण में सस्ते - आलसी लोड हो रहा है के बाद। (2) वर्तमान में उदाहरण में कोई "सेटर" नहीं है, लेकिन अगर कोई एक के बाद एक जोड़ता है, और यह बस सेट करता है stuff, तो गेट्टर उसी मान को लौटा देगा । (3) आलसी लोडिंग जैसा कि उदाहरण में दिखाया गया है "दृश्यमान" साइड इफेक्ट्स उत्पन्न नहीं करता है। (4) बहस करने योग्य है, शायद एक वैध बिंदु, क्योंकि "आलसी लोडिंग" शुरू करने के बाद पूर्व एपीआई अनुबंध को बदल सकता है - लेकिन किसी को निर्णय लेने के लिए उस अनुबंध को देखना होगा।
Doc Brown

2

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

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

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

जब वास्तव में आरंभीकरण होता है या महत्वपूर्ण नहीं हो सकता है।

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

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

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


0

जैसा कि @MikeNakis ने कहा है कि बस करो ... यदि आपको सामान मिलता है तो यह ठीक है ... यदि आप कुछ और करते हैं तो एक नया फ़ंक्शन बनाते हैं जो काम करता है और इसे सार्वजनिक करता है।

यदि आपकी प्रॉपर्टी / फंक्शन केवल वही कर रहा है जो उसका नाम बताता है, तो कॉम्प्लीकेशन बचे रहने की ज्यादा गुंजाइश नहीं है। सामंजस्य कुंजी IMO है


1
इस बारे में सावधान रहें, आप अपनी आंतरिक स्थिति को बहुत अधिक उजागर कर सकते हैं। आप खाली की एक बहुत कुछ के साथ समाप्त करना नहीं चाहते loadFoo()या preloadDummyReferences()या createDefaultValuesForUninitializedFields()तरीकों सिर्फ इसलिए कि अपने वर्ग के प्रारंभिक कार्यान्वयन उन्हें जरूरत है।
TMN

ज़रूर ... मैं सिर्फ यह बता रहा था कि अगर आप ऐसा करते हैं, तो नाम बताता है कि बहुत सी समस्याएं नहीं होनी चाहिए ... लेकिन जो आप कहते हैं वह पूरी तरह सच है ...
इवान क्रोक्ज़ करिक्यू

0

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


0

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

  1. सबसे पहले, इस बारे में सोचें कि क्या आपके कोड को पुनर्गठित करने का कोई तरीका है, इसलिए सभी आवश्यक लोड कॉल और कैश प्रबंधन को कंस्ट्रक्टर / इनिशियलाइज़र में किया जाता है। यदि यह संभव है, तो आप एक वर्ग बना सकते हैं, जिसका इनवेरिएंट आपको भाग 2 से जटिल गेट्टर की सुरक्षा के साथ भाग 2 से सरल गेट्टर की अनुमति देता है। (एक जीत-जीत परिदृश्य)

  2. यदि आप ऐसी कोई क्लास नहीं बना सकते हैं, तो तय करें कि क्या आपके पास एक ट्रेडऑफ है और यह तय करने की जरूरत है कि आप किस उपभोक्ता को कैश-चेकिंग कोड छोड़ना चाहते हैं या नहीं।

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

    2. यदि कैश चेक को छोड़ना ठीक है या यह बहुत महत्वपूर्ण है कि आपको गेट्टर में O (1) के प्रदर्शन की गारंटी है तो अलग कॉल का उपयोग करें।

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


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

@ डोमिनिक: यह एक शब्दार्थ और भाषा पर निर्भर मुद्दा है। वह बिंदु जो किसी वस्तु का उपयोग करने के लिए उपयुक्त है और उसके बाद और उसके बाद ही उपयुक्त आवेग प्रदान करता है।
हुगोमग

0

मेरी राय में, गेटर्स में बहुत सारे तर्क नहीं होने चाहिए। उनके साइड इफेक्ट्स नहीं होने चाहिए और आपको उनसे कभी भी अपवाद नहीं लेना चाहिए। जब तक निश्चित रूप से, आप जानते हैं कि आप क्या कर रहे हैं। मेरे अधिकांश गेटर्स का उनमें कोई तर्क नहीं है और बस एक फील्ड में जाते हैं। लेकिन उस के लिए उल्लेखनीय अपवाद एक सार्वजनिक एपीआई के साथ था जिसे उपयोग करने के लिए जितना संभव हो उतना सरल होना चाहिए। इसलिए मेरे पास एक गेटटर था जो विफल हो जाता अगर दूसरा गेट्टर नहीं कहा जाता। समाधान? कोड की एक पंक्ति जैसे var throwaway=MyGetter;कि उस पर निर्भर रहने वाले गटर में। मुझे इस पर गर्व नहीं है, लेकिन मैं अभी भी इसे करने के लिए एक क्लीनर तरीका नहीं देखता हूं


0

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

हो सकता है कि नाम getCachedStuff()पाने वाले के लिए एक नाम का उपयोग करना उचित हो क्योंकि इसमें लगातार निष्पादन का समय नहीं होगा।

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


0

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

कुछ इस तरह:

public List<Stuff> getStuff()
{
    return Collections.unmodifiableList(stuff);
}

के रूप में पानेवाला में कैशिंग के लिए, मुझे लगता है कि यह ठीक होगा, लेकिन मुझे कैश लॉजिक को स्थानांतरित करने के लिए लुभाया जा सकता है यदि कैश को महत्वपूर्ण समय लगता है। यानी यह निर्भर करता है।


0

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

interface StuffGetter {
     public List<Stuff> getStuff();
}

class StuffComputer implements StuffGetter {
     public List<Stuff> getStuff() {
         getStuffFromDatabase()
     }
}

class StuffCacher implements StuffGetter {
     private stuffComputer; // DI this
     private Cache<List<Stuff>> cache = new Cache<>();

     public List<Stuff> getStuff() {
         if cache.hasStuff() {
             return cache.getStuff();
         }

         List<Stuffs> stuffs = stuffComputer.getStuff();
         cache.store(stuffs);
         return stuffs;
     }
}

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


-1

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


+1: मैं आपसे सहमत हूँ! यदि ऑब्जेक्ट सिर्फ कुछ डेटा रखने के लिए है, तो गेटर्स को केवल ऑब्जेक्ट की वर्तमान सामग्री को वापस करना चाहिए। इस मामले में डेटा लोड करना कुछ अन्य ऑब्जेक्ट की जिम्मेदारी है। यदि अनुबंध कहता है कि ऑब्जेक्ट डेटाबेस रिकॉर्ड का प्रॉक्सी है, तो पाने वाले को मक्खी पर डेटा लाना चाहिए। यह और भी जटिल हो सकता है अगर डेटा लोड किया गया है, लेकिन आज तक नहीं है: क्या ऑब्जेक्ट को डेटाबेस में परिवर्तन के बारे में सूचित किया जाना चाहिए? मुझे लगता है कि इस सवाल का कोई अनूठा जवाब नहीं है।
जियोर्जियो
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.