"डेटा का प्रतिनिधित्व करने के लिए कक्षा के बजाय मानचित्र का उपयोग करें" -हिच हिकी


19

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

उदाहरण :

PersonAPI {
    Person addPerson(Person obj);
    Map<String, Object> addPerson(Map<String, Object> personMap);
}

दूसरे फ़ंक्शन में एपीआई उपयोगकर्ता कैसे जान सकता है कि किसी व्यक्ति को बनाने के लिए इनपुट क्या हैं?



मैं यह भी जानना चाहूंगा और मुझे लगता है कि उदाहरण के सवाल का बहुत जवाब नहीं है।
9

मुझे पता है कि मैंने इस चर्चा को एसई पर कहीं से पहले देखा है। मेरा मानना ​​है कि यह जावास्क्रिप्ट के संदर्भ में था, लेकिन तर्क समान थे। हालांकि यह नहीं मिल सकता है।
सेबेस्टियन रेडल

2
चूंकि क्लीजुर एक लिस्प है, इसलिए आपको लिस्प के लिए उपयुक्त चीजें करनी चाहिए। जब आप जावा का उपयोग करते हैं, तो कोड ... अच्छी तरह से जावा।
AK_

जवाबों:


12

अतिशयोक्तिपूर्ण सारांश (TM)

आपको कुछ चीजें मिलती हैं।

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

एक घातक दोष है।

  • कंपाइलर आपके लिए गलत वर्तनी वाले तारों की जांच नहीं करता है।
  • स्वचालित रीफ़ैक्टरिंग उपकरण आपके लिए संपत्ति के प्रमुख नामों का नाम नहीं बदलेंगे - जब तक आप फैंसी लोगों के लिए भुगतान नहीं करते हैं।

बात यह है कि, आप ओउम, आत्मनिरीक्षण का उपयोग करके आत्मनिरीक्षण प्राप्त कर सकते हैं। यह आमतौर पर होता है:

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

दूसरे शब्दों में, यदि आपको कभी भी एफपी के साथ इंटरफेस करने की आवश्यकता नहीं है, तो आपको रिच हिकी की सलाह नहीं लेनी है।

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

एंड्रॉयड, Google इंक का ट्रेडमार्क है।


आप दोनों दुनियाओं को भी खुश कर सकते हैं।

जावा दुनिया के लिए, हमेशा की तरह गेटर्स और सेटरर्स को लागू करें।

एफपी दुनिया के लिए, लागू करें

  • Object getPropertyByName(String name)
  • void setPropertyByName(String name, Object value) throws IllegalPropertyChangeException
  • List<String> getPropertyNames()
  • Class<?> getPropertyValueClass(String name)

इन फ़ंक्शन के अंदर, हाँ, बदसूरत कोड, लेकिन आईडीई प्लगइन्स हैं जो आपके लिए इसे भर देंगे ... उह, एक स्मार्ट प्लगइन जो आपके कोड को पढ़ता है

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

दुनिया का एफपी पक्ष जो भी "लेट" कोड लिख सकता है, वे चाहते हैं और कोड धीमा होने के बारे में वे आमतौर पर आपको चिल्लाते नहीं हैं।


सामान्य तौर पर, ऑब्जेक्ट के स्थान पर एक मैप (प्रॉपर्टी बैग) का उपयोग करना सॉफ्टवेयर विकास में आम बात है। यह कार्यात्मक प्रोग्रामिंग या किसी विशेष प्रकार की भाषाओं के लिए अद्वितीय नहीं है। यह किसी भी भाषा के लिए एक मुहावरेदार दृष्टिकोण नहीं हो सकता है, लेकिन ऐसी परिस्थितियां हैं जो इसके लिए कॉल करती हैं।

विशेष रूप से, सीरियलाइज़ेशन / डिसेरिएलाइज़ेशन में अक्सर एक समान तकनीक की आवश्यकता होती है।

"ऑब्जेक्ट के रूप में मैप" के बारे में बस कुछ सामान्य विचार।

  1. आपको अभी भी इस तरह के "ऑब्जेक्ट के रूप में मैप" को मान्य करने के लिए एक फ़ंक्शन प्रदान करना होगा। अंतर यह है कि "ऑब्जेक्ट के रूप में नक्शा" अधिक लचीले (कम प्रतिबंधात्मक) सत्यापन मानदंडों के लिए अनुमति देता है।
  2. आप आसानी से "ऑब्जेक्ट के रूप में मैप" में अतिरिक्त फ़ील्ड जोड़ सकते हैं।
  3. एक वैध वस्तु की न्यूनतम आवश्यकता का विनिर्देश प्रदान करने के लिए, आपको निम्नलिखित की आवश्यकता होगी:
    • मैप में अपेक्षित कुंजियों के "न्यूनतम आवश्यक" सेट को सूचीबद्ध करें
    • प्रत्येक कुंजी के लिए जिसका मान मान्य होना आवश्यक है, मान सत्यापन फ़ंक्शन प्रदान करें
    • यदि सत्यापन नियम हैं जिन्हें कई प्रमुख मूल्यों की जांच करने की आवश्यकता है, तो वह भी प्रदान करें।
    • फायदा क्या है? विनिर्देश प्रदान करना इस तरह से आत्मनिरीक्षण है: आप कुंजियों के न्यूनतम आवश्यक सेट को क्वेरी करने के लिए और प्रत्येक कुंजी के लिए सत्यापन फ़ंक्शन प्राप्त करने के लिए एक कार्यक्रम लिख सकते हैं।
    • OOP में, इन सभी को "इनकैप्सुलेशन" के नाम से एक ब्लैक बॉक्स में रोल किया जाता है। मशीन-पठनीय सत्यापन तर्क के स्थान पर, कॉलर केवल मानव-पठनीय "एपीआई प्रलेखन" पढ़ सकता है (यदि सौभाग्य से यह मौजूद है)।

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

@ टेलस्टाइन यह "एक हजार सांपों का बदसूरत सिर" आम तौर पर दो प्रणालियों के बीच संचार सीमा पर होता है, जहां किसी कारण से संचार या अंतर-प्रक्रिया चैनल वस्तुओं को टेलीपोर्ट किए जाने की अनुमति नहीं देते हैं। मुझे लगता है कि नई तकनीकें जैसे प्रोटोकॉल बफ़र्स ने ऑब्जेक्ट के रूप में नक्शे के इस पुरातन उपयोग के मामले को लगभग समाप्त कर दिया है। अभी भी अन्य वैध उपयोग के मामले हो सकते हैं, लेकिन मुझे इसके बारे में बहुत कम जानकारी है।
रवांग

2
घातक कमियों के लिए, सहमत हैं। लेकिन, अगर "आसान से गलत वर्तनी" और "हार्ड रिफ्लेक्टर के लिए" संपत्ति के प्रमुख नामों को रखा जाता है, तो जितना संभव हो, लगातार या एनम में , वह मुद्दा दूर हो जाता है। बेशक, यह कुछ हद तक विस्तार करता है :-(।
user949300

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

@NathanDavis (1) मैं स्वीकार करता हूं कि मेरा उत्तर एक स्थिर टाइपिंग परिप्रेक्ष्य (C #) से लिखा गया है और मैंने यह उत्तर इसलिए लिखा है क्योंकि मैं प्रश्नकर्ता के समान दृष्टिकोण को साझा करता हूं। मैं मानता हूं कि मेरे पास FP-केंद्रित दृष्टिकोण है। (२) एसईएसई में आपका स्वागत है, और चूंकि आप क्लीजुरे में एक सम्मानित व्यक्ति हैं, कृपया अपने स्वयं के उत्तर में लिखने के लिए समय निकालें, यदि मौजूदा वाले संतोषजनक नहीं हैं। डाउनवोट्स प्रतिष्ठा को घटाते हैं और नए उत्तर उत्थान को आकर्षित करते हैं जो प्रतिष्ठा को जल्दी से बढ़ाते हैं। (3) मैं देख सकता हूं कि "अधूरी वस्तुएं" कैसे उपयोगी हो सकती हैं - आप किसी दिए गए ऑब्जेक्ट (नाम, अवतार) के लिए 2 गुणों को क्वेरी कर सकते हैं और बाकी को छोड़ सकते हैं।
रवांग

9

यह किसी के द्वारा एक उत्कृष्ट बात है जो वास्तव में जानता है कि वह किस बारे में बात कर रहा है। मैं पाठकों को पूरी बात देखने की सलाह देता हूं। यह केवल 36 मिनट लंबा है।

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

उनका कहना है कि वर्ग का उपयोग करना एक उचित विकल्प हो सकता है, लेकिन यह एक जागरूक विकल्प होना चाहिए जो अपनी लागत के बारे में पूरी जागरूकता के साथ आता है, और प्रोग्रामर परंपरागत रूप से उन लागतों को नोट करने का एक बहुत खराब काम करते हैं, उन्हें अकेले ध्यान में रखते हैं। आपकी आवश्यकताओं के बढ़ने पर उस विकल्प को पुनः निर्धारित किया जाना चाहिए।

निम्नलिखित कुछ कोड परिवर्तन हैं (जिनमें से एक या दो का उल्लेख बात में किया गया था) जो Personवस्तुओं की सूची का उपयोग करने की तुलना में नक्शे की सूची का उपयोग करके संभावित रूप से सरल हैं:

  • किसी व्यक्ति को REST सर्वर पर भेजना। (एक Mapप्राइमेटिटिव को एक ट्रांसमिटेबल फॉर्मेट में डालने के लिए बनाया गया एक फ़ंक्शन अत्यधिक पुन: उपयोग योग्य है और यहां तक ​​कि एक लाइब्रेरी में भी प्रदान किया जा सकता है। एक Personवस्तु को एक ही काम को पूरा करने के लिए कस्टम कोड की आवश्यकता होती है)।
  • किसी रिलेशनल डेटाबेस क्वेरी से स्वचालित रूप से लोगों की सूची बनाएं। (फिर से, एक सामान्य और अत्यधिक पुन: प्रयोज्य कार्य)।
  • किसी व्यक्ति को प्रदर्शित और संपादित करने के लिए स्वचालित रूप से एक फ़ॉर्म जनरेट करें।
  • एक व्यक्ति बनाम एक कर्मचारी की तरह, व्यक्ति डेटा के साथ काम करने के लिए सामान्य कार्यों का उपयोग करें जो अत्यधिक गैर-सजातीय है।
  • उन सभी व्यक्तियों की सूची प्राप्त करें जो एक निश्चित ज़िप कोड में रहते हैं।
  • एक निश्चित ज़िप कोड में सभी व्यवसायों की सूची प्राप्त करने के लिए उस कोड का पुन: उपयोग करें।
  • अन्य ग्राहकों को प्रभावित किए बिना किसी व्यक्ति को ग्राहक-विशिष्ट फ़ील्ड जोड़ें।

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


क्या इसका कोई नाम है? कहो, ऑब्जेक्ट-प्रॉपर्टी मैपिंग या ऑब्जेक्ट-एट्रीब्यूटिंग मैपिंग (ORM जैसी ही लाइन के साथ)?
rwong

4
Choosing a class to represent a Person provides the immediate benefit of creating a statically-verifiable API... but that comes with the cost of limiting opportunities or increasing costs for change and reuse later on.गलत, और अविश्वसनीय रूप से निकृष्ट। यह बाद में बदलने के लिए आपके अवसर को बेहतर बनाता है , क्योंकि जब आप एक ब्रेकिंग परिवर्तन करते हैं, तो कंपाइलर स्वचालित रूप से आपके लिए हर स्थान को खोजेगा और इंगित करेगा, जिसे आपके संपूर्ण कोडबेस को गति तक लाने के लिए अद्यतन करने की आवश्यकता है। यह डायनामिक कोड में है, जहां आप ऐसा नहीं कर सकते हैं, कि आप वास्तव में पिछले विकल्पों के साथ मिल जाते हैं!
मेसन व्हीलर

4
@MasonWheeler: आप वास्तव में क्या कह रहे हैं कि आप अधिक गतिशील (और अधिक शिथिल-टाइप) डेटा संरचनाओं पर संकलन-समय प्रकार की सुरक्षा को महत्व देते हैं।
रॉबर्ट हार्वे

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

1
@GillBates आप ऐसा क्यों कहते हैं? आप बस उन वर्चुअल तरीकों को "मैप के अंदर" डालने का अवसर खो देते हैं - लेकिन वास्तव में रिच हिक्की के बारे में यही कहता है, "एक्टिवऑब्जेक्ट" वास्तव में एक विरोधी पैटर्न है। आपको डेटा के रूप में व्यवहार करना चाहिए कि यह क्या है (डेटा), और इसे व्यवहार के साथ नहीं मिलाएं। चिंताओं को अलग करके प्राप्त करने के लिए बड़ी सरलता लाभ हैं।
वर्जिल

4
  • यदि डेटा में बहुत कम या कोई व्यवहार नहीं है, तो लचीली सामग्री के साथ जो बदलने की संभावना है, एक मैप का उपयोग करें। IMO, एक विशिष्ट "जावाबीन" या "डेटा ऑब्जेक्ट" जिसमें एन फ़ील्ड, एन सेटर और एन गेटर्स के साथ एनीमिक डोमेन मॉडल शामिल है , समय की बर्बादी है। एक फैंसी स्माइली क्लास में लपेटकर अपनी महिमामयी संरचना से दूसरों को प्रभावित करने की कोशिश न करें। ईमानदार रहें, अपने इरादे स्पष्ट करें , और एक मानचित्र का उपयोग करें। (या, यदि यह आपके डोमेन, JSON या XML ऑब्जेक्ट के लिए कोई अर्थ रखता है)

  • यदि डेटा में महत्वपूर्ण वास्तविक व्यवहार है, उर्फ ​​तरीके ( बताओ, मत पूछो ), तो एक वर्ग का उपयोग करें। और असली ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग :-) का उपयोग करने के लिए खुद को पीठ पर थपथपाएं।

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

  • यदि डेटा में मध्यम मात्रा में सत्यापन व्यवहार है, तो यह सीमा रेखा है।

  • यदि डेटा संपत्ति परिवर्तन की घटनाओं को आग लगाता है, तो यह वास्तव में मानचित्र के साथ आसान और बहुत कम थकाऊ है। बस थोड़ा उपवर्ग लिखें।

  • एक मानचित्र का उपयोग करने का एक मुख्य दोष यह है कि उपयोगकर्ता को स्ट्रिंग्स, टोट्स, फोस इत्यादि के मूल्यों को डालना है, यदि यह अत्यधिक कष्टप्रद और त्रुटि-रहित है, तो एक वर्ग पर विचार करें। या एक सहायक वर्ग पर विचार करें जो प्रासंगिक गेटर्स के साथ मैप को लपेटता है।


1
वास्तव में, रिच हिकी का तर्क है कि यदि डेटा में महत्वपूर्ण वास्तविक व्यवहार है ... तो आप शायद पूरी "डिज़ाइन" चीज को गलत कर रहे हैं। डेटा "सूचना" है। सूचना, वास्तविक दुनिया में "एक जगह है जहाँ डेटा संग्रहीत है" नहीं है। सूचना में "ऑपरेशन नहीं होते हैं जो यह नियंत्रित करते हैं कि जानकारी कैसे बदलती है"। हम लोगों को यह बताकर जानकारी नहीं देते हैं कि यह कहाँ संग्रहीत है। ऑब्जेक्ट-ओरिएंटेड रूपक SOMETIMES दुनिया का एक उपयुक्त मॉडल हैं ... लेकिन अधिक बार नहीं, वे नहीं हैं। वह यही कहता है - "यपुर समस्या के बारे में सोचो"। सब कुछ एक वस्तु नहीं है - कुछ चीजें हैं।
वर्जिल

0

एपीआई के लिए mapदो स्तर हैं।

  1. नक्शे के लिए एपीआई।
  2. आवेदन की परंपराओं।

एपीआई सम्मेलन में मानचित्र द्वारा वर्णित किया जा सकता है। उदाहरण के लिए जोड़ी :api api-validateको मानचित्र में रखा जा सकता है या :api-foo validate-fooसम्मेलन हो सकता है। नक्शा भी स्टोर कर सकते हैंapi api-documentation-link

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

नक्शे के बारे में कुछ भी जादुई नहीं है और वस्तुओं के बारे में कुछ भी जादुई नहीं है। यह सब प्रेषण है।

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