इस तथ्य को संबोधित करते हुए कि प्राथमिक कुंजी आपके व्यवसाय डोमेन का हिस्सा नहीं है


25

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

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

  1. Naively, डेटा ट्रांसफर ऑब्जेक्ट्स (DTO) जो विशेष रूप से डोमेन मॉडल के संयोजन से प्राप्त होते हैं, में प्राथमिक कुंजी नहीं होगी
  2. आने वाले डीटीओ की प्राथमिक कुंजी नहीं होगी

तो, क्या यह कहना सुरक्षित है कि यदि आप वास्तव में शुद्ध रहने वाले हैं और अपने डोमेन मॉडल में प्राथमिक कुंजियों को खत्म कर रहे हैं, तो आपको उस प्राथमिक कुंजी पर अद्वितीय सूचकांकों के संदर्भ में हर अनुरोध को संभालने में सक्षम होने के लिए तैयार रहना चाहिए?

दूसरे तरीके से रखें, डोमेन मॉडल में पीके को हटाने के बाद निम्नलिखित में से कौन सा समाधान विशेष वस्तुओं की पहचान करने से निपटने का सही तरीका है?

  1. उन वस्तुओं की पहचान करने में सक्षम होने से जिन्हें आपको अन्य विशेषताओं से निपटने की आवश्यकता है
  2. डीटीओ में प्राथमिक कुंजी वापस प्राप्त करना; यानी, डोमेन से हठ से मैपिंग करते समय पीके को खत्म करना, फिर डोमेन से डीटीओ को मैप करते समय पीके को फिर से जोड़ना?

संपादित करें: चलो यह ठोस बनाते हैं।

कहो मेरे डोमेन मॉडल है VoIPProviderजो जैसे क्षेत्रों में शामिल हैं Name, Description, URL, संदर्भ की तरह है और साथ ही ProviderType, PhysicalAddressऔर Transactions

अब कहते हैं कि मैं एक वेब सेवा बनाना चाहता हूं जिससे विशेषाधिकार प्राप्त उपयोगकर्ता एस का प्रबंधन कर सकेंगे VoIPProvider

शायद इस मामले में एक उपयोगकर्ता के अनुकूल आईडी बेकार है; आखिरकार, वीओआईपी प्रदाता ऐसी कंपनियां हैं जिनके नाम कंप्यूटर के अर्थों में अलग-अलग हैं और व्यावसायिक कारणों से मानवीय अर्थों में भी पर्याप्त हैं। तो यह कहने के लिए पर्याप्त हो सकता है कि एक अद्वितीय VoIPProviderपूरी तरह से निर्धारित होता है (Name, URL)। तो अब हम कहते हैं कि मुझे एक विधि की आवश्यकता है PUT api/providers/voipताकि विशेषाधिकार प्राप्त उपयोगकर्ता VoIPप्रदाताओं को अपडेट कर सकें । वे एक को भेजते हैं VoIPProviderDTO, जिसमें बहुत सारे शामिल हैं, लेकिन सभी क्षेत्रों से नहीं VoIPProvider, जिसमें कुछ समतल भी शामिल है। हालाँकि, मैं उनके दिमाग को नहीं पढ़ सकता, और उन्हें अभी भी मुझे यह बताने की ज़रूरत है कि हम किस प्रदाता के बारे में बात कर रहे हैं।

ऐसा लगता है कि मेरे पास 2 (शायद 3) विकल्प हैं:

  1. मेरे डोमेन मॉडल में एक प्राथमिक कुंजी या वैकल्पिक कुंजी शामिल करें और इसे डीटीओ को भेजें, और इसके विपरीत
  2. उस प्रदाता की पहचान करें जिसकी हम अद्वितीय सूचकांक के माध्यम से देखभाल करते हैं, जैसे (Name, Url)
  3. किसी प्रकार की मध्यवर्ती वस्तु का परिचय दें जो हमेशा दृढ़ता परत, डोमेन और डीटीओ के बीच मैप कर सकती है, जो दृढ़ता परत के बारे में कार्यान्वयन के विवरण को उजागर नहीं करती है - डोमेन से डीटीओ और वापस जाने पर एक इन-मेमोरी अस्थायी पहचानकर्ता को शुरू करने से कहें।

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

@ OR61852 ORM की परवाह किए बिना, भले ही आप वास्तव में निम्न-स्तर के हों, फिर भी आपको डेटाबेस लेयर के कार्यान्वयन में एक प्राथमिक कुंजी की आवश्यकता होती है। इसलिए मैं सहमत हूं कि सरोगेट पीके आपको एक विशिष्ट दृढ़ता तंत्र द्वारा उपयोग किए जाने वाले वास्तविक पीके पर लाभ देता है, लेकिन अगर वह पीके वास्तव में एक व्यावसायिक वस्तु का प्रतिनिधित्व कर रहा है जो कि सार्थक है, यह आवश्यक रूप से अद्वितीय है और इसलिए कम से कम एक अद्वितीय व्यवसाय से संबंधित संपत्ति को परिभाषित करता है यह, नहीं?
tacos_tacos_tacos

1
सरोगेट्स के सभी फायदे कंप्यूटर से संबंधित हैं और कोई भी मानव-संबंधित नहीं हैं।
ट्यूलेंस कोर्डोवा

2
@ user61852: मैं 100% सहमत हूं (क्या मैंने कुछ अलग लिखा है?)। संचार के साधनों के लिए, "व्यवसाय कुंजी" का उपयोग करें। किसी भी व्यावसायिक कुंजी के लिए अद्वितीय विरोधाभासों को भी जोड़ें। लेकिन वास्तव में अपने डेटाबेस संदर्भों को लागू करने के लिए व्यापार कुंजी के उपयोग से बचें।
डॉक्टर ब्राउन

2
व्यापार कुंजी अनंत रूप से अद्वितीय हैं - जब तक कि वे नहीं हैं। यदि आप ऐसा होने पर व्यावसायिक कुंजी का प्राथमिक रूप से उपयोग कर रहे हैं तो व्यावसायिक नियमों में परिवर्तन से अधिक सामान टूट जाता है।
psr

जवाबों:


31

यह तरीका है कि हम इसे कैसे हल करते हैं (15 से अधिक वर्षों से, जब "डोमेन संचालित डिजाइन" शब्द का भी आविष्कार नहीं किया गया था):

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

इसलिए जब भी आपको तकनीकी उद्देश्यों के लिए एक प्राथमिक कुंजी की आवश्यकता होती है (जैसे किसी डेटाबेस में संबंधों को मैप करना), आपके पास एक उपलब्ध है, लेकिन जब तक आप इसे "देखना" नहीं चाहते हैं, तब तक अपने स्तर को "डोमेन विशेषज्ञ मॉडल" में बदल दें। "। और आपको "दो मॉडल" (एक पीके के साथ और एक बिना) बनाए रखने की ज़रूरत नहीं है; इसके बजाय, केवल पीके के बिना एक मॉडल बनाए रखें और अपने DB के लिए DDL बनाने के लिए एक कोड जनरेटर का उपयोग करें, जो मैपिंग नियमों के अनुसार स्वचालित रूप से PK जोड़ता है।

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

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


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

1
@tacos_tacos_tacos: चलिए आपके वीओआईपीपॉइडर उदाहरण से चिपके रहते हैं। मैं वास्तव में आपके DTO में एक "VoIPProviderID" जोड़ूंगा, कम से कम "कार्यान्वयन पक्ष" पर (यदि आपके पास अपने डोमेन विशेषज्ञों के लिए एक चित्रमय संस्करण है, तो मैं शायद वहां नहीं दिखाऊंगा)। अद्यतन उद्देश्यों के लिए, डेटाबेस से tha डेटा खींचते समय एक विशिष्ट VoIPProvider की पहचान करने का मानक तरीका "VoIPProviderID" द्वारा प्राप्त किया जाना चाहिए। यदि आपके API के उपयोगकर्ता (नाम, URL) द्वारा पहचान पसंद करते हैं, तो अतिरिक्त रूप से प्रदान करें। ...
डॉक ब्राउन

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

1
प्राकृतिक कुंजी कभी-कभी वास्तव में सम्मोहक प्रतीत होती है, लेकिन इसे जलाना बहुत आसान है (जैसे, "वूप्स, अब मेरे पास कई किरायेदार हैं और यह अब अद्वितीय नहीं है")।
केसी

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

4

आपको कुछ अद्वितीय सूचकांक द्वारा कई वस्तुओं की पहचान करने में सक्षम होने की आवश्यकता है, और यह नहीं है कि एक प्राथमिक कुंजी क्या है (या कम से कम एक मौजूद है)।

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


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

क्या स्पष्ट v निहितार्थ समान अंतर का प्रश्न नहीं है? आपके पास एक पीके हो सकता है जो एक अद्वितीय सूचकांक की तरह, कई कॉलम फैलाता है। मुझे नहीं लगता कि आपके उद्देश्यों के लिए उनमें कोई अंतर है।
gbjbaanb

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

आप इसे खत्म कर रहे हैं। एक अद्वितीय सूचकांक डीके स्कीमा की उतनी ही कलाकृति है जितनी कि एक पीके है। इसे इस तरह से सोचें - एक पीके पहला (या प्राथमिक) अद्वितीय सूचकांक है। इसका 'विशेष' क्योंकि आपको आमतौर पर 1 ऐसे सूचकांक की आवश्यकता होती है।
gbjbaanb

सच है, लेकिन किसी भी सार्थक डोमेन ऑब्जेक्ट को कम से कम एक व्यवसाय से संबंधित क्षेत्रों से सख्ती से पहचाना जाना चाहिए, नहीं? तथ्य यह है कि यह डीबी में एक इंडेक्स को परिभाषित करता है प्रदर्शन कारणों के लिए डीबी को आसानी से क्वेरी करने के लिए उपयोग किया जाता है ... मैं 6-कॉलम वाले अद्वितीय इंडेक्स पर एक-कॉलम पीके पसंद करूंगा, और वे वास्तव में विभिन्न उद्देश्यों की सेवा करते हैं - डीबीए / डीबीडी की सुविधा के लिए एक पीके (या छोटी संख्या में क्षेत्रों के साथ सूचकांक) भी उपलब्ध है?
tacos_tacos_tacos 12

4

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

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


खैर, संदेश एक चरम उदाहरण है, लेकिन फिर भी हम जानते हैं MessageSender, MessageRecipient, TimeSent- कि अद्वितीय होना चाहिए।
tacos_tacos_tacos

1
@tacos_tacos_tacos, फिर आप अन्य तालिकाओं के लिए FKs कैसे बनाते हैं? यह MessageSenderId होना चाहिए, जो संभवतः UserId पर एक उपयोगकर्ता तालिका में मैप करता है। आप तालिका के बीच की कुंजी के रूप में UserName का उपयोग नहीं करना चाहेंगे, क्योंकि यह बदल सकता है और रखरखाव दुःस्वप्न बन सकता है। यही कारण है कि आप आम तौर पर केवल प्राथमिक कुंजी का उपयोग करते हुए तालिकाओं में शामिल होते हैं, न कि किसी अन्य स्तंभ (निश्चित रूप से अपवाद हैं)। इस db संरचना को अभी भी लागू किया जाना चाहिए। अब आप हमेशा अपने ऐप के लिए एक CQRS मॉडल पर जा सकते हैं ... जिस स्थिति में नियम बदलते हैं। खासकर अगर आप इवेंट सोर्सिंग का भी इस्तेमाल करते हैं।
कैफ़ीक्यूक

4

गैर-व्यवसाय से संबंधित पीके का उपयोग करने का कारण यह सुनिश्चित करना है कि हमारे सिस्टम में उपयोगकर्ता को यह निर्धारित करने का एक आसान और सुसंगत तरीका है।

मैं आपको एक टिप्पणी के साथ उत्तर देता हूं: MessageSender, MessageRecipient, TimeSent (एक संदेश के लिए)। आप कभी भी इस तरह से अस्पष्टता रख सकते हैं (उदाहरण के लिए, सिस्टम जनरेट किए गए संदेशों के साथ कुछ ऐसा होता है जो अक्सर होता है)। और आप यहाँ MessageSender और MessageRecipient को कैसे मान्य करने जा रहे हैं? मान लीजिए कि आपने FirstName, Lastname, DateOfBirth का उपयोग करके उन्हें मान्य किया है, तो आप अंततः एक ऐसी स्थिति में जा रहे हैं, जहाँ आपके पास एक ही दिन में 2 लोग एक ही नाम के साथ पैदा हुए हों। यह उल्लेख करने के लिए नहीं कि आप एक ऐसी स्थिति में भाग लेंगे, जहां आपके पास नाम का संदेश है tacostacostacos-America-1980-Doc Brown-France-1965-23/5/2014-11:43:54.003UTC+200। यह एक नाम का एक राक्षस है, और आपके पास अभी भी कोई गारंटी नहीं है कि आपके पास केवल 1 ही होगा।

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

आपको अपना आईडी अपने उपयोगकर्ता को दिखाने की आवश्यकता नहीं है। आप इसे छिपा सकते हैं (यदि आवश्यक हो तो सादे दृष्टि में, URL के माध्यम से)।

एक और कारण है कि एक पीके इतना उपयोगी है कि आप ऊपर से कटौती कर सकते हैं: एक पीके ऐसा करता है ताकि आपको उपयोगकर्ता द्वारा उत्पन्न कोड की व्याख्या करने के लिए कंप्यूटर को मजबूर न करना पड़े। यदि एक चीनी उपयोगकर्ता आपके कोड का उपयोग करता है और चीनी वर्णों का एक समूह में प्रवेश करता है, तो आपके कोड को अचानक इन आंतरिक रूप से काम करने में सक्षम होने की आवश्यकता नहीं है, लेकिन यह केवल उस गाइड का उपयोग कर सकता है जो सिस्टम उत्पन्न करता है। यदि आपके पास एक अरबी उपयोगकर्ता है जो अरबी लेखन में प्रवेश करता है, तो आपके सिस्टम को आंतरिक रूप से सामना करने की आवश्यकता नहीं है, लेकिन मूल रूप से यह अनदेखी कर सकते हैं कि वे वहां हैं।

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

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

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


1

बाहरी सिस्टम के लिए एक पहचानकर्ता जारी करते समय, आपको केवल यूआरआई देना चाहिए, या वैकल्पिक रूप से एक कुंजी या कुंजी का एक सेट होना चाहिए, जिसमें यूआरआई के समान गुण हैं, डेटाबेस प्राथमिक कुंजी को सीधे उजागर करने के बजाय (यहां से आगे) मैं संदर्भित करूंगा। URI या एक कुंजी या कुंजियों का एक सेट जिसमें URI के समान गुण होते हैं, दूसरे शब्द में URI नीचे का मतलब RFC 3986 URI नहीं है)।

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

GUID का उपयोग करना कुछ मानदंडों को पूरा करता है, हालांकि GUID जैसे पहचानकर्ता को आपके सिस्टम में भी ऑब्जेक्ट को वापस करने में मुश्किल हो सकती है, इसलिए GUID की तरह आपके सिस्टम से अपारदर्शी होने वाली चाबियां केवल तभी होनी चाहिए जब क्लाइंट URI / पहचानकर्ता को पार्स कर रहा हो। एक सुरक्षा खतरा बन गया है।

अपने वीओआईपी उदाहरण पर वापस जाएँ, कहते हैं कि एक वीओआईपी प्रदाता विशिष्ट रूप से या तो (VoIPProviderID) या (नाम, URL) या (GUID) द्वारा निर्धारित किया जा सकता है। जब किसी बाहरी सिस्टम को वीओआईपी प्रदाता को अपडेट करने की आवश्यकता होती है, तो वह बस एक PUT / प्रदाता / बाय-आईडी / 1234 या PUT /provider/foo-voip/bar-domain.comया पारित कर सकता है PUT /3F2504E0-4F89-41D3-9A0C-0305E82C3301और आपका सिस्टम समझ जाएगा कि बाहरी सिस्टम VoIPProvider को अपडेट करना चाहता है। ये यूआरआई आपके सिस्टम द्वारा उत्पन्न होते हैं और केवल आपके सिस्टम को यह समझने की जरूरत है कि सभी का मतलब एक ही है। बाहरी प्रणाली को बस यूआरआई में जो भी मूल रूप से है, उसका इलाज करना चाहिए PUT <whatever>

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

जब आपका सिस्टम इस तरह से ऑब्जेक्ट्स को संदर्भित करने के लिए एक URI का उपयोग करता है, तो आप अपने सिस्टम को कैसे कार्यान्वित करते हैं, इसके बारे में कुछ भी लीक नहीं कर रहे हैं। आप URI को जनरेट करते हैं और क्लाइंट बस इसे आपके पास वापस भेज देता है।


0

मुझे इस बेतहाशा गलत और भोले-भाले बयान पर निशाना साधना होगा:

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

नाम कुंजी के रूप में भयानक हैं , क्योंकि वे अक्सर बदलते रहते हैं। एक कंपनी के जीवनकाल में कई नाम हो सकते हैं , कंपनी विलय कर सकती है, विभाजित हो सकती है, फिर से विलय कर सकती है, विशिष्ट कर उद्देश्यों के लिए एक अलग सहायक बना सकती है जिसमें 0 कर्मचारी हैं लेकिन सभी ग्राहक जो तब पूरी तरह से अलग सहायक से कर्मचारियों को काम पर रखते हैं।

फिर हम इस तथ्य से रूबरू होते हैं कि कंपनी के नाम भी दूरस्थ रूप से अद्वितीय नहीं हैं, जैसा कि लैंडमार्क ऐप्पल बनाम एप्पल द्वारा दिखाया गया है ।

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

संदर्भ के लिए, मैं पसंद करता हूं कि कैसे django इसे संभालता है:

class VoipProvider(models.Model):
    name=fields.TextField()
    address=fields.TextField()

class Customer(models.Model):
    name=fields.TextField()
    address=fields.TextField()
    voipProvider=fields.ForeignKeyField(VoipProvider)

इस तरह, ग्राहक के प्रदाता के विवरण का उपयोग करके कोड में उपयोग किया जा सकता है:

myCustomer.voipProvider.name #returns the name of the customers VOIP Provider.

हालांकि प्राथमिक / विदेशी कुंजी दिखाई नहीं देती हैं, वे वहां मौजूद हैं, और उनका उपयोग वस्तुओं तक पहुंचने के लिए किया जा सकता है, लेकिन वे दूर हैं।


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

0

मुझे लगता है कि हम अक्सर इस मुद्दे को डीबी के परिप्रेक्ष्य से गलत तरीके से देखते हैं: ओह, कोई प्राकृतिक कुंजी नहीं है, इसलिए हमें एक सरोगेट कुंजी बनाने की आवश्यकता है। अरे नहीं, हम सरोगेट कुंजी को डोमेन ऑब्जेक्ट्स में वापस नहीं ला सकते हैं, यह टपका हुआ है आदि।

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

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

इस दृष्टिकोण का यह भी अर्थ है कि यदि कोई डोमेन ऑब्जेक्ट दृढ़ता परत को हिट करता है, और उसके पास आईडी नहीं है, तो शायद यह किसी प्रकार का मूल्य ऑब्जेक्ट है, इसलिए आईडी की आवश्यकता नहीं है।

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