सदस्य: डोमेन आईडी बनाम यूनिक आईडी का उपयोग करें


10

क्या मुझे डोमेन ऑब्जेक्ट या विधि / फ़ंक्शन पैरामीटर के रूप में एक अद्वितीय आईडी का उपयोग करना चाहिए, इस पर उपयोगी उत्तर के बाद, पहचानकर्ता बनाम डोमेन ऑब्जेक्ट को विधि पैरामीटर के रूप में , मेरे पास एक समान प्रश्न फिर से है: सदस्य (पिछले प्रश्न चर्चा में प्रबंधन नहीं किया गया था) इसको ढँक दो)। सदस्य के रूप में सदस्य बनाम ऑब्जेक्ट के रूप में अद्वितीय आईडी का उपयोग करने के पेशेवरों और विपक्ष क्या हैं। मैं स्कैला / सी # / जावा जैसी जोरदार टाइप की गई भाषाओं के संदर्भ में पूछ रहा हूं। क्या मुझे (1) चाहिए

User( id: Int, CurrentlyReadingBooksId: List[Int])
Book( id: Int, LoanedToId: Int )

या (2), (1) के लिए तरजीह देने के बाद: क्या हमें हर चीज के लिए प्रकार परिभाषित करना चाहिए?

User( id: UserId, CurrentlyReadingBooksId: List[ BookId] )
Book( id: BookId, LoanedToId: UserId )

या (3)

User( id: Int, CurrentlyReadingBooks: List[Book]) 
Book( id: Int, LoanedTo: User)

जब मैं ऑब्जेक्ट (3) होने के लाभों के बारे में नहीं सोच सकता, तो आईडी (2) और (1) होने का एक लाभ यह है कि जब मैं DB से उपयोगकर्ता ऑब्जेक्ट बना रहा हूं, तो मुझे बुक ऑब्जेक्ट बनाने की ज़रूरत नहीं है, जो बदले में एक अंतहीन श्रृंखला बनाते हुए, उपयोगकर्ता ऑब्जेक्ट पर ही निर्भर हो सकता है। क्या RDBMS और No-SQL दोनों के लिए इस समस्या का एक सामान्य समाधान है (यदि वे अलग हैं)?

अब तक के कुछ जवाबों के आधार पर, मेरे प्रश्न का पुन: वर्णन: (आईडी के उपयोग से लिपटे हुए प्रकारों में होना चाहिए) 1) हमेशा आईडी आईडी? 2) हमेशा वस्तुओं का उपयोग करें? ३) क्रमांकन और डीसर्लाइज़िंग में पुनरावृत्ति का खतरा होने पर आईडी का उपयोग करें, लेकिन वस्तुओं का उपयोग करें अन्यथा? 4) कुछ और?

संपादित करें: यदि आप उत्तर देते हैं कि वस्तुओं को हमेशा या कुछ मामलों के लिए इस्तेमाल किया जाना चाहिए, तो कृपया यह सुनिश्चित करें कि सबसे बड़ी चिंता का उत्तर अन्य उत्तरदाताओं ने पोस्ट किया है => डीबी से डेटा कैसे प्राप्त करें


1
अच्छे प्रश्न के लिए धन्यवाद, रुचि के साथ इसका अनुसरण करने के लिए तत्पर हैं। थोड़ी शर्म की बात है कि आपका उपयोगकर्ता नाम "user18151" है, इस तरह के उपयोगकर्ता नाम वाले लोगों को कुछ लोगों द्वारा नजरअंदाज कर दिया जाता है :)
bjfletcher

@bjfletcher धन्यवाद। मैंने खुद को उस नकारात्मक धारणा के बारे में बताया था, लेकिन मेरे साथ ऐसा कभी नहीं हुआ!
0fnt

जवाबों:


7

आईडी के रूप में डोमेन ऑब्जेक्ट कुछ जटिल / सूक्ष्म समस्याएं पैदा करते हैं:

क्रमबद्धता / Deserialization

यदि आप ऑब्जेक्ट को कुंजियों के रूप में संग्रहीत करते हैं तो यह ऑब्जेक्ट ग्राफ को बहुत जटिल बना देगा। stackoverflowपुनरावृत्ति के कारण JSON या XML के लिए एक भोली सीरियलाइज़ेशन करते समय आपको त्रुटियाँ मिलेंगी । फिर आपको एक कस्टम धारावाहिक लिखना होगा, जो ऑब्जेक्ट को क्रमबद्ध करने और पुनरावृत्ति बनाने के बजाय अपनी आईडी का उपयोग करने के लिए वास्तविक वस्तुओं को परिवर्तित करता है।

टाइप सेफ्टी के लिए ऑब्जेक्ट्स में पास करें, लेकिन केवल आईडी स्टोर करें, तो आपके पास एक एक्सेसर विधि हो सकती है जो आलसी संबंधित इकाई को लोड करती है जब इसे कहा जाता है। दूसरे स्तर की कैशिंग बाद की कॉलों का ध्यान रखेगी।

सूक्ष्म संदर्भ लीक:

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

आदर्श स्थिति:

अपारदर्शी आईडी बनाम इंट / लंबे:

एक idपूरी तरह से अपारदर्शी पहचानकर्ता होना चाहिए जो इसकी पहचान के बारे में कोई जानकारी नहीं रखता है। लेकिन इसे कुछ सत्यापन की पेशकश करनी चाहिए कि यह अपने सिस्टम में एक मान्य पहचानकर्ता है।

कच्चे प्रकार इसे तोड़ते हैं:

int, longऔर StringRDBMS सिस्टम में पहचानकर्ताओं के लिए सबसे अधिक इस्तेमाल होने वाले कच्चे प्रकार हैं। व्यावहारिक कारणों का एक लंबा इतिहास है जो दशकों पहले से हैं और वे सभी समझौता करते हैं जो या तो बचत spaceया बचत में फिट होते हैं timeया दोनों।

अनुक्रमिक आईडी सबसे खराब अपराधी हैं:

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

String फ़ील्ड समस्याग्रस्त हैं क्योंकि भोले डिजाइनर सामग्री में जानकारी पैक करेंगे, आमतौर पर अस्थायी शब्दार्थ भी।

ये एक वितरित डेटा प्रणाली बनाने के लिए असंभव है, क्योंकि 12437379123यह विश्व स्तर पर अद्वितीय नहीं है । जब एक सिस्टम में पर्याप्त डेटा प्राप्त होता है, तो वितरित सिस्टम में एक और नोड एक समान संख्या के साथ एक रिकॉर्ड बनाएगा, इसकी बहुत अधिक गारंटी है।

फिर हैक्स इसके चारों ओर काम करना शुरू कर देते हैं और पूरी चीज भाप में गड़बड़ी के ढेर में बदल जाती है।

विशाल वितरित सिस्टम ( क्लस्टर ) को अनदेखा करना यह एक पूर्ण दुःस्वप्न बन जाता है जब आप डेटा को अन्य सिस्टम के साथ भी साझा करना शुरू करते हैं। खासकर तब जब दूसरी प्रणाली आपके नियंत्रण में नहीं है।

आप एक ही समस्या के साथ अंत करते हैं, कि कैसे अपनी आईडी को विश्व स्तर पर अद्वितीय बनाया जाए।

UUID को एक कारण के लिए बनाया और मानकीकृत किया गया था:

UUIDऊपर सूचीबद्ध उन सभी समस्याओं से पीड़ित हो सकते हैं जिनके आधार पर Versionआप उपयोग करते हैं।

Version 1एक अद्वितीय आईडी बनाने के लिए एक मैक पते और समय का उपयोग करता है। यह बुरा है क्योंकि यह स्थान और समय के बारे में अर्थ संबंधी जानकारी देता है। यह अपने आप में एक समस्या नहीं है, यह तब है जब भोले डेवलपर्स व्यापार तर्क के लिए उस जानकारी पर भरोसा करना शुरू करते हैं। यह उन सूचनाओं को भी लीक करता है जिनका किसी भी घुसपैठ के प्रयासों में फायदा उठाया जा सकता है।

Version 2का उपयोग करता है एक उपयोगकर्ता UIDया GIDऔर डोमेन के UIDया GUIसमय के स्थान पर Version 1इस बस के रूप में के रूप में बुरा है Version 1डेटा रिसाव के लिए और इस जानकारी को खतरे में डालकर व्यापार तर्क में इस्तेमाल किया जाएगा।

Version 3ऐसा ही है, लेकिन मैक पते और समय को किसी चीज़ MD5के कुछ सरणी के हैश के साथ बदल देता है byte[]जिसका निश्चित रूप से अर्थ अर्थ है। चिंता करने के लिए कोई डेटा रिसाव byte[]नहीं है, से पुनर्प्राप्त नहीं किया जा सकता है UUID। यह आपको निश्चित UUIDरूप से उदाहरणों के रूप और कुछ प्रकार की बाहरी कुंजी बनाने का एक अच्छा तरीका देता है ।

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

Version 5के समान है, Version 4लेकिन sha1इसके बजाय का उपयोग करता है md5

डोमेन कुंजी और लेन-देन डेटा कुंजी

डोमेन ऑब्जेक्ट आईडी के लिए मेरी प्राथमिकता, किसी तकनीकी कारण का उपयोग करने से प्रतिबंधित Version 5या Version 3उपयोग Version 5करना है।

Version 3 लेनदेन डेटा के लिए बहुत अच्छा है जो कई मशीनों में फैला हो सकता है।

जब तक आप अंतरिक्ष के उपयोग के लिए विवश नहीं होते तब तक UUID का उपयोग करें:

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

Version 3,4,5 पूरी तरह से अपारदर्शी हैं और वे इस तरह से होना चाहिए।

आपके पास एक प्राथमिक के रूप में एक एकल कॉलम UUIDहो सकता है और फिर आपके पास एक प्राकृतिक समग्र प्राथमिक कुंजी क्या है के लिए अद्वितीय अनुक्रमित हो सकते हैं।

स्टोरेज भी नहीं होना है CHAR(36)। आप UUIDकिसी दिए गए डेटाबेस के लिए एक मूल बाइट / बिट / संख्या फ़ील्ड में स्टोर कर सकते हैं जब तक कि यह अभी भी अनुक्रमित है।

विरासत

यदि आपके पास कच्चे प्रकार हैं और उन्हें बदल नहीं सकते हैं, तो आप अभी भी उन्हें अपने कोड में दूर कर सकते हैं।

आप का उपयोग करते हुए एक Version 3/5के रूप UUIDमें Class.getName()+ में पारित कर सकते हैं और एक अपारदर्शी संदर्भ कुंजी है जो मनोरंजक और निर्धारक है।String.valueOf(int)byte[]


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

मैंने एक स्पष्ट विवरण जोड़ा।

इसे अब पा लिया है। उत्तर पर समय बिताने के लिए धन्यवाद।
0

1
Btw, AFAIK पीढ़ीगत कचरा संग्रहकर्ता (जो मुझे लगता है कि इन दिनों प्रमुख जीसी प्रणाली है) को जीसी के परिपत्र संदर्भों में बहुत अधिक कठिनाई नहीं होनी चाहिए।
0fnt

1
अगर C-> A -> B -> Aऔर Bएक में डाल दिया है Collectionतो Aऔर अपने सभी बच्चों को अभी भी पहुंचा जा सकता है, इन बातों को पूरी तरह से स्पष्ट नहीं हैं और सूक्ष्म को जन्म दे सकता लीकGCसमस्याओं का कम से कम, क्रमांकन और ग्राफ के deserialization जटिलता का एक बुरा सपना है।

2

हां, दोनों तरह से लाभ हैं, और एक समझौता भी है।

List<int>:

  • स्मृति को बचाओ
  • प्रकार का तेज़ आरंभ User
  • यदि आपका डेटा किसी रिलेशनल डेटाबेस (SQL) से आता है, तो आपको उपयोगकर्ताओं को, बस Usersतालिका प्राप्त करने के लिए दो तालिकाओं का उपयोग करने की आवश्यकता नहीं है

List<Book>:

  • पुस्तक तक पहुँचना उपयोगकर्ता से तेज़ है, पुस्तक को स्मृति में लोड किया गया है। यह अच्छा है यदि आप तेजी से बाद के संचालन को प्राप्त करने के लिए एक लंबी शुरुआत कर सकते हैं।
  • यदि आपका डेटा HBase या Cassandra जैसे डॉक्यूमेंट स्टोर डेटाबेस से आता है, तो पढ़ी जाने वाली पुस्तकों के मूल्य उपयोगकर्ता रिकॉर्ड पर होने की संभावना है, इसलिए आप आसानी से "उपयोगकर्ता प्राप्त करते समय" किताबें प्राप्त कर सकते थे।

यदि आपके पास कोई मेमोरी या सीपीयू चिंता नहीं है, तो मैं उसके साथ जाऊँगा List<Book>, जो कोड Userइंस्टेंसेस का उपयोग करता है वह क्लीनर होगा।

समझौता:

Linq2SQL का उपयोग करते समय, इकाई के लिए उत्पन्न कोड उपयोगकर्ता के पास एक EntitySet<Book>आलसी लोड होगा जब आप इसे एक्सेस करते हैं। यह आपके कोड को साफ रखना चाहिए और उपयोगकर्ता का उदाहरण छोटा (मेमोरी फ़ुटप्रिंट वार) होना चाहिए।


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

Linq2SQL उदाहरण में आपको वास्तव में कोई प्रदर्शन लाभ नहीं मिलता है, बस क्लीनर कोड। कैसांद्रा / HBase जैसे डॉक्यूमेंट स्टोर से एक-से-कई इकाइयाँ प्राप्त करते समय, प्रसंस्करण समय का अधिकांश भाग रिकॉर्ड खोजने में व्यतीत किया जाता है, इसलिए हो सकता है कि आप वहाँ रहते हुए भी सभी कई संस्थाओं को प्राप्त कर सकें (किताबें, में यह उदाहरण)।
20ol पर ytoledano

क्या आपको यकीन है? भले ही मैं बुक और उपयोगकर्ताओं को अलग-अलग सामान्यीकृत करता हूं? मेरे लिए ऐसा लगता है कि यह केवल नेटवर्क विलंबता अतिरिक्त लागत होना चाहिए। किसी भी स्थिति में, कोई व्यक्ति RDBMS मामले को उदारतापूर्वक कैसे संभालता है? (मैंने स्पष्ट रूप से उल्लेख करने के लिए प्रश्न संपादित किया है)
0fnt

1

अंगूठे का छोटा और सरल नियम:

डीटीओ एस में आईडी का उपयोग किया जाता है ।
ऑब्जेक्ट संदर्भ आमतौर पर डोमेन लॉजिक / बिजनेस लॉजिक और यूआई लेयर ऑब्जेक्ट में उपयोग किए जाते हैं।

यही कारण है कि बड़े, enterprisey पर्याप्त परियोजनाओं में आम वास्तुकला है। आपके पास इन दो प्रकार की वस्तुओं का अनुवाद करने और उन्हें करने के लिए मैपर होंगे।


द्वारा उत्तर देने और उत्तर देने के लिए धन्यवाद। दुर्भाग्य से, जब मैं विकी लिंक के लिए धन्यवाद के अंतर को समझता हूं, तो मैंने इसे अभ्यास में कभी नहीं देखा (मुझे लगता है कि मैंने बड़ी दीर्घकालिक परियोजनाओं के साथ कभी काम नहीं किया है)। क्या आपके पास एक उदाहरण होगा जहां एक ही वस्तु का दो अलग-अलग उद्देश्यों के लिए दो तरीकों से प्रतिनिधित्व किया गया था?
0fnt

यहां मैपिंग से संबंधित एक वास्तविक प्रश्न है: stackoverflow.com/questions/9770041/dto-to-entity-mapping-tool - और इस तरह के महत्वपूर्ण लेख हैं: rogeralsing.com/2013/12/01/…
hermemeister

वास्तव में उपयोगी, धन्यवाद। दुर्भाग्य से मुझे अभी भी समझ में नहीं आया कि सर्कुलर रेफरेंस काम के साथ डेटा लोड कैसे होगा? उदाहरण के लिए यदि कोई उपयोगकर्ता किसी पुस्तक को संदर्भित करता है और पुस्तक उसी उपयोगकर्ता को संदर्भित करती है, तो आप इस वस्तु को कैसे बनाएंगे?
0fnt

में देखो भंडार पैटर्न । आप एक BookRepositoryऔर एक होगा UserRepository। आप हमेशा कॉल myRepository.GetById(...)या समान करेंगे , और रिपॉजिटरी या तो ऑब्जेक्ट बनाएगी और अपने मूल्यों को डेटा स्टोर से लोड करेगी, या कैश से प्राप्त करेगी। इसके अलावा, बाल वस्तुओं को ज्यादातर आलसी लोड किया जाता है, जो निर्माण समय पर प्रत्यक्ष परिपत्र संदर्भों से निपटने के लिए रोकता है।
हर्ज़ेमिस्टर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.