क्या यह कोड एक "ट्रेन मलबे" (कानून के उल्लंघन में) की तरह है?


23

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

service.setLocation(this.configuration.getLocation().toString());

इस मामले में, serviceविधि के भीतर घोषित एक ज्ञात प्रकार का एक उदाहरण चर है। this.configurationक्लास कंस्ट्रक्टर में पास होने से आता है, और एक विशिष्ट इंटरफ़ेस को लागू करने वाले क्लास का एक उदाहरण है (जो एक सार्वजनिक getLocation()पद्धति को अनिवार्य करता है )। इसलिए, अभिव्यक्ति this.configuration.getLocation()का वापसी प्रकार ज्ञात है; विशेष रूप से इस मामले में, यह एक है java.net.URL, जबकि service.setLocation()एक चाहता है String। चूंकि दो प्रकार के स्ट्रिंग और URL सीधे संगत नहीं हैं, इसलिए गोल छेद में वर्गाकार खूंटी को फिट करने के लिए किसी प्रकार के रूपांतरण की आवश्यकता होती है।

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

क्या कोई मान्य तर्क है कि ऊपर की तरह एक कॉल, सूचीबद्ध बाधाओं को देखते हुए, हतोत्साहित या अस्वीकृत भी किया जाना चाहिए? या मैं सिर्फ अत्यधिक नाइटी हूं?

अगर मैं एक ऐसी विधि लागू करने वाला था, URLToString()जो toString()किसी URLऑब्जेक्ट पर कॉल करता है (जैसे कि उसके द्वारा लौटाया गया getLocation()) एक पैरामीटर के रूप में उसके पास जाता है, और परिणाम देता है, तो मैं getLocation()कॉल को उसी परिणाम को प्राप्त करने के लिए लपेट सकता हूं ; प्रभावी रूप से, मैं सिर्फ रूपांतरण को एक कदम आगे बढ़ाऊंगा। क्या यह किसी तरह स्वीकार्य होगा? ( मुझे ऐसा लगता है, सहज रूप से, कि इसे किसी भी तरह से कोई फर्क नहीं पड़ना चाहिए, क्योंकि यह सब चीजों को थोड़ा-बहुत घुमाता है। हालांकि, कानून के कानून के पत्र के रूप में उद्धृत किया गया है, यह स्वीकार्य होगा, क्योंकि मैं। फिर एक फंक्शन के लिए एक पैरामीटर पर सीधे काम करेगा।)

क्या इससे कोई फर्क पड़ेगा अगर यह toString()मानक प्रकार पर कॉल करने की तुलना में कुछ अधिक विदेशी था ?

उत्तर देते समय, इस बात का ध्यान रखें कि serviceचर के व्यवहार या एपीआई को परिवर्तित करना व्यावहारिक नहीं है। इसके अलावा, तर्क के लिए, मान लें कि रिटर्न प्रकार को बदलना getLocation()भी अव्यावहारिक है।

जवाबों:


34

समस्या यहाँ है के हस्ताक्षर setLocation। यह कड़ाई से टाइप किया गया है

विस्तृत करने के लिए: यह क्यों उम्मीद करेगा String? A किसी भी तरह के टेक्स्ट डेटा काString प्रतिनिधित्व करता है । यह संभावित रूप से एक मान्य स्थान पर कुछ भी हो सकता है।

वास्तव में, यह एक सवाल है: एक स्थान क्या है? मुझे आपके कोड को देखे बिना कैसे पता चलेगा? यदि यह एक URLसे अधिक था, तो मुझे इस पद्धति के बारे में बहुत कुछ पता होगा।
शायद यह एक कस्टम वर्ग होने के लिए अधिक समझ में आता है Location। ठीक है, मुझे पहले नहीं पता होगा कि क्या है, लेकिन कुछ बिंदु पर (शायद लिखने से पहले this.configuration.getLocation()मुझे यह पता लगाने में एक मिनट लगेगा कि यह विधि क्या है)।
दी, दोनों मामलों में मुझे यह समझने के लिए कुछ और जगह देखने की जरूरत है कि क्या उम्मीद है। हालांकि बाद के मामले में, अगर मैं समझता हूं, कि क्या Locationहै, तो मैं आपके एपीआई का उपयोग कर सकता हूं, पूर्व मामले में, अगर मैं समझता हूं, क्या Stringहै (जो उम्मीद की जा सकती है), मुझे अभी भी नहीं पता है कि आपका एपीआई क्या उम्मीद करता है।

असंभावित परिदृश्य में, कि कोई भी स्थान किसी भी तरह का टेक्स्ट डेटा है, मैं इसे किसी भी तरह के डेटा को पुन: व्याख्यायित करूंगा , जिसमें टेक्स्ट बनावट का प्रतिनिधित्व है । इस तथ्य को देखते हुए, कि Objectएक toStringविधि है, आप उस के साथ जा सकते हैं, हालांकि यह आपके कोड के ग्राहकों से विश्वास की एक छलांग की मांग करता है।

इसके अलावा, आपको यह विचार करना चाहिए कि यह वह जावा है जिसके बारे में आप बात कर रहे हैं, जिसमें डिजाइन की बहुत कम विशेषताएं हैं। यह वही है जो आपको वास्तव toStringमें अंत में कॉल करने के लिए मजबूर कर रहा है ।
यदि आप उदाहरण के लिए C # लेते हैं, जो सांख्यिकीय रूप से भी टाइप किया जाता है, तो आप वास्तव में एक निहित कलाकार के लिए व्यवहार को परिभाषित करके उस कॉल को छोड़ सकते हैं ।
गतिशील रूप से टाइप की गई भाषाओं में, जैसे कि Objective-C, आपको वास्तव में या तो रूपांतरण की आवश्यकता नहीं है, क्योंकि जब तक मान एक स्ट्रिंग की तरह व्यवहार करता है, तब तक हर कोई खुश रहता है।

कोई यह तर्क दे सकता है, कि अंतिम कॉल toStringकम कॉल है, वास्तव में जावा की खोजकर्ता की मांग से उत्पन्न शोर है। आप एक विधि को कॉल कर रहे हैं, जो कि किसी भी जावा ऑब्जेक्ट के पास है, इसलिए आप वास्तव में "दूर की इकाई" के बारे में किसी भी ज्ञान को सांकेतिक शब्दों में बदलना नहीं करते हैं और इस तरह से लिस्ट नॉलेज के सिद्धांत का उल्लंघन नहीं करते हैं। कोई रास्ता नहीं है, कोई फर्क नहीं पड़ता कि क्या getLocationरिटर्न, कि यह एक toStringविधि नहीं है ।

लेकिन कृपया, स्ट्रिंग्स का उपयोग न करें, जब तक कि वे वास्तव में सबसे अधिक प्राकृतिक विकल्प न हों (या जब तक आप किसी भाषा का उपयोग नहीं कर रहे हों, तब तक आपके पास एंम नहीं है ...)।


मैं आपसे सहमत होना चाहूंगा, लेकिन उसने पहले ही कहा कि वह सेवा एपीआई को संशोधित नहीं कर सकता।
झॉकिंग

1
@ हॉकिंग: उसने यह नहीं कहा कि वह नहीं कर सकता। उन्होंने कहा कि यह अव्यवहारिक है। मैं असहमत हूं। एपीआई डिजाइन में खामियों के आसपास काम करने वाले कोड के लिए सर्वोत्तम प्रथाओं को लागू करने की कोशिश करना वास्तव में केवल तभी समझ में आता है जब इस तरह के वर्कअराउंड एकमात्र संभव विकल्प हैं। हालांकि यहां एपीआई सीधे सेट करना सबसे अच्छा विकल्प है। कमियों को दूर करना हमेशा उनके आसपास काम करने के लिए बेहतर होता है।
Back2dos

वैसे भी +1 के लिए "जावा की खोज की मांग के कारण वास्तव में सिर्फ शोर से कम एक कॉल है"
झॉकिंग

1
मैं यह +1 देता हूँ, भले ही "कड़े टाइप" के लिए। मेरे कोड में, मैं उन प्रकारों को पारित करने की कोशिश करता हूं जो अर्थ / इरादे को जितना संभव हो सके व्यक्त करते हैं, लेकिन जब तीसरे पक्ष के पुस्तकालयों और एपीआई के साथ काम करते हैं, तो कभी-कभी आप उस एपीआई के लेखकों का उपयोग करके अटक जाते हैं। और IIRC, एक स्थान कर सकते हैं वास्तव में "टेक्स्ट का डेटा किसी भी तरह का" हो सकता है, लेकिन कार्यान्वयन के लिए मैं पर काम कर रहा हूँ, एक गैर URL स्थान पूरी तरह से व्यर्थ है।
एक CVn

1
एपीआई बदलने के लिए के रूप में; यह कंप्यूटर सॉफ्टवेयर है, इसलिए चीजों को बदलना हमेशा संभव होता है । (यदि और कुछ नहीं तो आप हमेशा एक अमूर्त परत लिख सकते हैं।) हालांकि, कभी-कभी ऐसा करने में बहुत कम और दीर्घकालिक दोनों तरह के प्रयासों को उचित ठहराया जा सकता है। फिर, इस तरह के बदलाव करना पूरी तरह से संभव हो सकता है, लेकिन फिर भी अव्यवहारिक।
एक CVn

21

Demeter का कानून एक डिजाइन दिशानिर्देश है, न कि धार्मिक रूप से पालन किए जाने वाला कानून।

यदि आपको लगता है कि आपकी कक्षाएं पर्याप्त रूप से डिकॉप्ड हैं तो लाइन के साथ कुछ भी गलत नहीं है this.configuration.getLocation(), खासकर यदि आप कहते हैं, तो एपीआई के अन्य हिस्सों को बदलना अव्यावहारिक है।

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


1
चूंकि this.configurationएक ज्ञात इंटरफ़ेस का एक प्रकार का एक उदाहरण चर है, उस पर एक विधि को कॉल करना जो उस इंटरफ़ेस द्वारा परिभाषित किया गया है, एक सख्त व्याख्या के अनुसार भी ठीक लगता है। हाँ, मुझे पता है कि यह एक दिशानिर्देश है, बस KISS, ठोस, YAGNI और इतने पर की तरह। सामान्य सॉफ़्टवेयर विकास में वास्तव में कोई भी "कानून" (कानूनी अर्थ में) बहुत कम हैं।
बजे एक सीवीएन

4
+1 व्यावहारिक होने के लिए ;-)
ट्रेब

1
मुझे नहीं लगता कि कानून के कानून को इस तरह से भी लागू किया जाना चाहिए - कॉन्फ़िगरेशन मूल रूप से एक कंटेनर है। हर एपीआई में मैंने कभी कंटेनर के अंदर देखने के साथ काम किया है वह सामान्य और अपेक्षित व्यवहार है।
लोरेन Pechtel

2

केवल एक चीज मैं इस तरह से कोड नहीं लिखने के बारे में सोच सकता हूं यदि this.configuration.getLocation()रिटर्न शून्य है तो क्या होगा ? यह आपके आस-पास के कोड पर निर्भर करता है और इस कोड का उपयोग करके दर्शकों को लक्षित करता है। लेकिन जैसा कि मार्को कहते हैं - डेमेटर का नियम अंगूठे का नियम है - इसका पालन करना अच्छा है, लेकिन अनावश्यक रूप से ऐसा करने से आपकी पीठ नहीं टूटती है।


यदि this.configuration.getLocation()अशक्त हो जाएगा, तो हम या तो (ए) सबसे अधिक संभावना है कि अब तक कभी नहीं मिला होगा, या (बी) अंतरिम में कुछ विनाशकारी हुआ है, जिस स्थिति में मैं चाहता हूं कि कोड विफल हो जाए। तो जबकि यह निश्चित रूप से एक वैध बिंदु है, इस विशेष मामले में यह कहना काफी सुरक्षित है कि यह लागू नहीं होता है। इसके अलावा, इस सब के आसपास और भी बहुत कुछ अपवाद हैंडलर है जो विशेष रूप से अप्रत्याशित असफलताओं के उस प्रकार से निपटने के लिए डिज़ाइन किया गया है।
एक CVn

2

Demeter कानून का सख्ती से पालन करने का मतलब होगा कि आपको कॉन्फ़िगरेशन ऑब्जेक्ट में एक विधि को लागू करना चाहिए:

function getLocationAsString() {
  return getLocation().toString();
}

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


1
यहाँ वही सुझाया गया है: c2.com/cgi/wiki?TrainWreck "एक ऐसी विधि बनाएँ जो वांछित व्यवहार का प्रतिनिधित्व करती है और क्लाइंट को बताती है कि उसे क्या करना है। यह" बताओ, मत पूछो "सिद्धांत का
अनुसरण
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.