साधारण डोमेन ऑब्जेक्ट का प्रतिनिधित्व करने के लिए आदिम बनाम वर्ग?


14

डोमेन-स्पेसिफिक ऑब्जेक्ट बनाम सादे स्ट्रिंग या नंबर का उपयोग करने के लिए सामान्य दिशानिर्देश या नियम क्या हैं?

उदाहरण:

  • आयु वर्ग बनाम पूर्णांक?
  • FirstName वर्ग बनाम स्ट्रिंग?
  • यूनिकआईडी बनाम स्ट्रिंग
  • PhoneNumber वर्ग बनाम स्ट्रिंग बनाम लंबा?
  • डोमेननाम वर्ग बनाम स्ट्रिंग?

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

मैं "आयु" वर्ग में कभी नहीं आया, लेकिन कोई यह तर्क दे सकता है कि यह समझ में आता है कि यह गैर-नकारात्मक होना चाहिए (ठीक है मुझे पता है कि आप नकारात्मक युगों के लिए बहस कर सकते हैं लेकिन यह एक अच्छा उदाहरण है कि यह एक आदिम पूर्णांक के लगभग बराबर है)।

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

क्या उत्तर पर्यावरण पर निर्भर करता है? मैं मुख्य रूप से उद्यम / उच्च-मूल्य वाले सॉफ़्टवेयर से संबंधित हूं जो एक दशक से अधिक समय तक जीवित रहेगा और बनाए रखा जाएगा।

शायद मैं इसे उखाड़ फेंक रहा हूं, लेकिन मैं यह जानना चाहूंगा कि क्या किसी के पास वर्ग बनाम आदिम चुनने के नियम हैं।


2
आयु वर्ग एक अच्छा विचार नहीं है यदि इसे पूर्णांक द्वारा प्रतिस्थापित किया जा सकता है। यदि यह कंस्ट्रक्टर में जन्म की तारीख लेता है और getCurrentAge () और getAgeAt (डेट की तारीख) के तरीके हैं तो क्लास का अर्थ है। लेकिन इसे एक पूर्णांक द्वारा प्रतिस्थापित नहीं किया जा सकता है।
कीवरोन

5
"एक स्ट्रिंग कभी-कभी एक स्ट्रिंग नहीं होती है। तदनुसार इसे मॉडल करें।" मार्क सीमैन द्वारा 'आदिम जुनून' के बारे में एक अच्छी पोस्ट है: blog.ploeh.dk/2015/01/19/…
Serhii Shushliapin

4
वास्तव में एक आयु वर्ग कुछ अजीब तरीके से कुछ समझ में आता है। आयु की सामान्य पश्चिमी परिभाषा जन्म के समय शून्य है और आपके अगले जन्मदिन पर 1 जोड़ेगी। पूर्व एशियाई पद्धति यह है कि आप जन्म के समय 1 हैं और अगले नए साल में 1 जोड़ा जाता है। इस प्रकार आपके स्थान के आधार पर, आपकी आयु की गणना अलग-अलग की जा सकती है। ई.ग. से en.wikipedia.org/wiki/East_Asian_age_reckoning people may be one or two years older in Asian reckoning than in the western age system
पीटर एम

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

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

जवाबों:


20

डोमेन-स्पेसिफिक ऑब्जेक्ट बनाम सादे स्ट्रिंग या नंबर का उपयोग करने के लिए सामान्य दिशानिर्देश या नियम क्या हैं?

सामान्य दिशानिर्देश यह है कि आप अपने डोमेन को एक डोमेन विशिष्ट भाषा में मॉडलिंग करना चाहते हैं।

विचार करें: हम पूर्णांक का उपयोग क्यों करते हैं? हम सभी पूर्णांकों को स्ट्रिंग के साथ आसानी से दर्शा सकते हैं। या बाइट्स के साथ।

यदि हम एक डोमेन अज्ञेय भाषा में प्रोग्रामिंग कर रहे थे जिसमें पूर्णांक और आयु के लिए आदिम प्रकार शामिल थे , तो आप किसे चुनेंगे?

यह वास्तव में नीचे आता है कुछ प्रकार की "आदिम" प्रकृति हमारे कार्यान्वयन के लिए भाषा की पसंद का एक दुर्घटना है।

संख्या, विशेष रूप से, आमतौर पर अतिरिक्त संदर्भ की आवश्यकता होती है। आयु केवल एक संख्या नहीं है, लेकिन इसमें आयाम (समय), इकाइयां (वर्ष?), नियम भी हैं! एक साथ उम्र जोड़ना एक तरह से समझ में आता है कि पैसे के लिए उम्र को जोड़ना नहीं है।

प्रकारों को विशिष्ट बनाने से हम एक असत्यापित ईमेल पते और सत्यापित ईमेल पते के बीच अंतरों को मॉडल कर सकते हैं ।

स्मृति में इन मूल्यों का प्रतिनिधित्व कैसे किया जाता है, इसकी दुर्घटना कम से कम दिलचस्प भागों में से एक है। डोमेन मॉडल की कोई परवाह नहीं CustomerIdहै एक int, या एक स्ट्रिंग, या एक UUID / GUID, या एक JSON नोड है। यह सिर्फ खर्च चाहता है।

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

1972 में परनास ने लिखा

हम इसके बजाय प्रस्तावित करते हैं कि कोई मुश्किल डिजाइन निर्णयों या डिजाइन निर्णयों की सूची के साथ शुरू होता है जो बदलने की संभावना है। प्रत्येक मॉड्यूल को इस तरह के निर्णय को दूसरों से छिपाने के लिए डिज़ाइन किया गया है।

एक अर्थ में, डोमेन विशिष्ट मूल्य प्रकार जो हम पेश करते हैं, वे मॉड्यूल हैं जो डेटा के अंतर्निहित प्रतिनिधित्व के हमारे निर्णय को अलग करते हैं।

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

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

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


छिपाने (या अमूर्त) के बारे में उत्कृष्ट बिंदु उन चीजों को जो मुश्किल और बदलने की संभावना है।
user949300 15

4

आप अमूर्त के बारे में सोच रहे हैं, और यह बहुत अच्छा है। हालाँकि, जो चीज़ें आपकी सूची में हैं, वे अधिकतर किसी चीज़ के व्यक्तिगत गुण हैं (सभी एक ही चीज़ के नहीं, बिल्कुल)।

जो मुझे लगता है कि अधिक महत्वपूर्ण यह है कि एब्सट्रैक्शन प्रदान करना है जो समूह एक साथ विशेषता रखते हैं और उन्हें एक उचित घर प्रदान करते हैं, जैसे कि एक व्यक्ति वर्ग, ताकि क्लाइंट प्रोग्रामर को कई विशेषताओं से निपटना न पड़े, बल्कि एक उच्च स्तर का एब्सट्रैक्शन हो।

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

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

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


1

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

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

Firstname के लिए मुझे बहुत अधिक लाभ नहीं दिखाई देते हैं, UniqueID भी, PhoneNumber थोड़ा, आप इसे उदाहरण के लिए देश और क्षेत्र को देने के लिए कह सकते हैं क्योंकि सामान्य PhoneNumber में देशों और क्षेत्रों को संदर्भित किया जाता है, कुछ ऑपरेटर मोबाइल को वर्गीकृत करने के लिए पूर्वनिर्धारित संख्या प्रत्यय का उपयोग करते हैं। , कार्यालय ... संख्याएँ, ताकि आप इन विधियों को उस वर्ग में जोड़ सकें, जो डोमेननाम के लिए समान हैं।

अधिक जानकारी के लिए मैं आपको DDD (डोमेन ड्रिवेन डिज़ाइन) में मूल्य वस्तुओं पर एक नज़र डालने की सलाह देता हूँ।


1

यह उस पर निर्भर करता है यदि आपके पास उस डेटा से संबंधित व्यवहार है (जिसे आपको बनाए रखने और / या बदलने की आवश्यकता है) या नहीं।

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

यदि, दूसरी ओर, आप पाते हैं कि, निर्णय लेने के लिए, आप अपने कोड में विभिन्न स्थानों पर इस डेटा की जाँच या हेरफेर कर रहे हैं, तो स्थान अक्सर एक-दूसरे के करीब नहीं होते हैं - फिर एक कक्षा को परिभाषित करके इसे एक उचित ऑब्जेक्ट में बदल दें। और तरीकों के रूप में इसके अंदर प्रासंगिक व्यवहार डाल रहा है। यदि किसी कारण से आपको लगता है कि इस तरह की कक्षा को परिभाषित करने का कोई मतलब नहीं है, तो एक विकल्प इस व्यवहार को किसी "सेवा" वर्ग में समेकित करना है जो इस डेटा पर काम करता है।


1

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

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

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

तो एक वर्ग के लिए एक आदिम को बढ़ावा देने के कारण हैं, लेकिन वे बहुत विशिष्ट अनुप्रयोग हैं। यहाँ कुछ उदाहरण हैं:

  • आपके पास विशेष सत्यापन तर्क है जिसे हर जगह लागू किया जाना है सूचना का प्रकार (जैसे फोन नंबर, ईमेल पते)।
  • आपके पास विशेष स्वरूपण तर्क है जो मनुष्यों को पढ़ने के लिए प्रस्तुत करने के लिए उपयोग किया जाता है (जैसे IP4 और IP6 पते)
  • आपके पास ऐसे फ़ंक्शन हैं जो सभी उस ऑब्जेक्ट प्रकार से संबंधित हैं
  • आपके पास समान मूल्य प्रकारों की तुलना करने के लिए विशेष नियम हैं

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


1

दिन के अंत में, एक वस्तु सिर्फ एक गवाह है कि कुछ प्रक्रिया वास्तव में दौड़ा मिला है

एक आदिम का intमतलब है कि कुछ प्रक्रिया ने 4 बाइट्स की मेमोरी को शून्य कर दिया, और फिर -2,147,483,648 से 2,147,483,647 की सीमा में कुछ पूर्णांक का प्रतिनिधित्व करने के लिए आवश्यक बिट्स को फ़्लिप किया; जो कि उम्र की अवधारणा के बारे में एक मजबूत कथन नहीं है। इसी तरह, (गैर-शून्य) का System.Stringअर्थ है कि कुछ बाइट्स आवंटित किए गए थे और बिट्स को कुछ एन्कोडिंग के संबंध में यूनिकोड वर्णों के अनुक्रम का प्रतिनिधित्व करने के लिए फ़्लिप किया गया था।

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

इसी तरह, एक Ageवस्तु को संभवतः एक गवाह होना चाहिए कि कुछ प्रक्रिया ने दो तिथियों के बीच अंतर की गणना की। चूंकि intsआम तौर पर दो तिथियों के बीच अंतर की गणना करने का परिणाम नहीं है, वे युगों का प्रतिनिधित्व करने के लिए अपर्याप्त हैं।

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

//hypothetical syntax
class Age = |start:date - end:date|.Years

(* ML-like syntax *)
type Age(x, y) = datediff(year, x, y)

//C#-like syntax with primary constructors and expression-bodied classes
class Age(DateTime x, DateTime y) => implicit operator int (Age a) => Abs((y - x).Years);

उदाहरण के लिए, F #, वास्तव में सक्रिय पैटर्न के रूप में इसके लिए एक अच्छा वाक्यविन्यास है :

//Impossible to produce an `Age` without first computing the difference of two dates
//But, any pair (tuple) of dates is implicitly converted to an `Age` when needed.

let (|Age|) (x, y) =  (date_diff y x).Days / 365

मुद्दा यह है कि सिर्फ इसलिए कि आपकी प्रोग्रामिंग भाषा डोमेन वस्तुओं को परिभाषित करने के लिए बोझिल बना देती है इसका मतलब यह नहीं है कि यह वास्तव में ऐसा करने के लिए कभी भी एक बुरा विचार है।


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


0

एक वर्ग बनाम एक आदिम का उपयोग करने से आपको क्या मिलता है, इसके बारे में सोचें। यदि एक वर्ग का उपयोग कर आप प्राप्त कर सकते हैं

  • मान्यता
  • स्वरूपण
  • अन्य उपयोगी तरीके
  • प्रकार की सुरक्षा (अर्थात PhoneNumber, एक वर्ग के साथ , मेरे लिए इसे स्ट्रिंग या एक यादृच्छिक स्ट्रिंग (यानी "ककड़ी") के लिए असाइन करना असंभव होना चाहिए, जहां मुझे फोन नंबर की उम्मीद है)
  • कोई अन्य लाभ

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

यह भी महसूस करें कि कभी-कभी अच्छा नामकरण केवल इसे संभाल सकता है (यानी। एक स्ट्रिंग जिसका नाम firstNameबनाम एक पूरी कक्षा है जो सिर्फ एक स्ट्रिंग संपत्ति लपेटता है)। कक्षाएं चीजों को हल करने का एकमात्र तरीका नहीं हैं।

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