क्या डेटा ट्रांसफर ऑब्जेक्ट के रूप में एंटिटी ऑब्जेक्ट्स का उपयोग करना अच्छा है?


29

मैं सोच रहा हूं क्योंकि अगर यह है, तो एंटिटी फ्रेमवर्क परतों के बीच डेटा स्थानांतरित करने के लिए समान गुणों के साथ एक नई वस्तु बनाने के लिए तर्क क्यों नहीं देता है?

मैं इकाई वस्तुओं का उपयोग करता हूं जो मैं इकाई ढांचे के साथ उत्पन्न करता हूं।


3
मुझे लगता है कि यह एक अच्छा सवाल है, लेकिन मैं वास्तव में नहीं बता सकता क्योंकि यह पढ़ना बहुत मुश्किल है मुझे यकीन नहीं है कि इसे कैसे ठीक किया जाए। कृपया अपना प्रश्न संपादित करें।
कैंडिड_ऑरेंज

1
@CandiedOrange +1, और यह इसे और अधिक डरावना बनाता है कि इसने बहुत सारे अपवोट प्राप्त किए।
गुरिल्ला ०३

जवाबों:


23

यह आप पर निर्भर है।

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

EF ने कई कारणों से DDD के साथ अच्छी तरह से कभी नहीं खेला, लेकिन दो बाहर खड़े हैं: आप अपनी संस्थाओं पर पैरामीटर का निर्माण नहीं कर सकते हैं और आप संग्रह को एन्क्रिप्ट नहीं कर सकते हैं। DDD उस पर निर्भर करता है, क्योंकि डोमेन मॉडल में डेटा और व्यवहार दोनों शामिल होने चाहिए।

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

उदाहरण के लिए: मान लीजिए कि आपके पास Personनिम्नलिखित परिभाषा के साथ एक वर्ग है :

public class Person
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime DateOfBirth { get; get; }

    // plus a bunch of other properties relevant about a person
}

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

आपके अद्यतन प्रश्न का उत्तर देने के लिए, EF एक ORM है। इसका काम डेटाबेस रिकॉर्ड को ऑब्जेक्ट में मैप करना और इसके विपरीत है। ईएफ से गुजरने से पहले और बाद में आप उन वस्तुओं के साथ क्या करते हैं, यह इसकी चिंताओं का हिस्सा नहीं है। और न ही होना चाहिए।


1
संक्षेप में संक्षेप। डीटीओ और पीओसीओ के बीच अंतर क्या हैं? क्या वे केवल डेटा नहीं रखते हैं?
लैव

1
@ guillaume31 आपके पास एक वास्तविक डोमेन मॉडल नहीं हो सकता है, जिसमें दृढ़ता पर विचार किए बिना। अगर मैं प्रतिबिंब का उपयोग करने के लिए मजबूर हूं (सार्वजनिक रूप से हैक के अन्य प्रकारों का उल्लेख नहीं करने के लिए), तो यह अच्छा है कि बशर्ते कि मेरी सार्वजनिक संपत्ति को अलग-अलग नाम से निजी क्षेत्र द्वारा समर्थित किया गया हो? यदि EF मुझे अपने सार्वजनिक इंटरफ़ेस का उपयोग करके अपने समुच्चय को छिपाने के लिए बुनियादी ढाँचा प्रदान नहीं कर रहा है, तो मैं अपने व्यवसाय के तर्क को कहीं और रखना बेहतर हूं और डेटाबेस से लोड करने के लिए अतिरिक्त बॉयलर प्लेट लिखने के बजाय मेरा डोमेन एनीमिक है।
devnull

1
इसलिए आप अपने पूरे डोमेन मॉडल को अपने पब्लिक कलेक्शन के नाम से एनेमिक बना देंगे, उसी तरह जैसे प्राइवेट फील्ड में होता है? (चलो कंस्ट्रक्टर समस्या को एक तरफ सेट करें, क्योंकि यह सबसे पहले डोमेन के खिलाफ पहली बार ऑब्जेक्ट के सभी क्षेत्रों को लेने वाले एक कंस्ट्रक्टर को उजागर करने के लिए है ...)
guillaume31

1
@ कोनराड यहां से : As of EF Core 2.1, only services known by EF Core can be injected. Support for injecting application services is being considered for a future release.मुझे अपनी संस्थाओं में इंजेक्ट किए गए एप्लिकेशन सेवाओं को बहुत पसंद है।
devnull

1
@ कोनराड मैं अपने डोमेन एंटिटीज को डीटीओ के रूप में इस्तेमाल करना बंद कर दूंगा (अगर मैं उन्हें इस तरह इस्तेमाल करना था)। सेवा इंजेक्शन के लिए ईएफ के समर्थन की परवाह किए बिना डीटीओ उपयोगी हैं।
देवनुल

8

नहीं ऐसा नहीं है।

आदर्श रूप से, डीटीओ आपकी दृढ़ता रिपॉजिटरी (उर्फ, आपके डेटाबेस टेबल) से मेल खाएगा।

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

एक और बात यह है कि डीटीओ उस क्षेत्र के हिस्से हैं जो कुछ भी यह है कि दृढ़ता के साथ काम करता है, जबकि आपके बिजनेस लेयर को उनके बारे में कुछ भी नहीं पता होना चाहिए।


एक कमांड ऑब्जेक्ट एक डीटीओ है जिसके बारे में बिजनेस लेयर को कुछ पता होना चाहिए।
devnull

मुझे लगता है कि व्यापार परत शायद एक इंटरफ़ेस के माध्यम से अप्रत्यक्ष रूप से कमांड ऑब्जेक्ट को बुलाएगा। और मेरा मतलब है कि साधारण वस्तुओं के रूप में डीटीओ, जो डेटा ले जाते हैं, जिसमें कोई कार्यक्षमता नहीं है। मुझे यकीन नहीं है कि एक कमांड ऑब्जेक्ट एक DTO ( martinfowler.com/eaaCatalog/dataTransferObject.html ) है।
जुआन कार्लोस एडुआर्डो रोमाना एक

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

डीटीओ दृढ़ता से डोमेन तक नहीं जाते हैं, वे बाहर से भी आ सकते हैं जैसा कि डेटा शुरू करने में लगता है (REST APIs में सोचें)। जैसा कि देवनुल द्वारा बताया गया है, कमांड और ईवेंट कुछ हद तक डीटीओ हैं और उन्हें व्यावसायिक स्तर पर स्थानांतरित किया जाता है। यदि हैंडलर व्यवसायिक परत है या नहीं, यह डिजाइन पर निर्भर करता है।
लैव

4

यह वास्तव में एक बहुत बुरा विचार है। मार्टिन फाउलर का स्थानीय डीटीओ के बारे में एक लेख है

लंबी कहानी छोटी, DTOपैटर्न का उपयोग प्रक्रिया के बाहर डेटा स्थानांतरित करने के लिए किया गया था, उदाहरण के लिए तार पर और एक ही प्रक्रिया के अंदर परतों के बीच नहीं।


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

4

नहीं, यह एक बुरा अभ्यास है।

कुछ कारणों से:

  1. नए निकाय क्षेत्र डिफ़ॉल्ट रूप से Dto में होंगे । इकाई का उपयोग करें का अर्थ है कि हर जानकारी डिफ़ॉल्ट रूप से उपभोग करने के लिए उपलब्ध होगी। यह आपको समझदार चेतावनी को उजागर करने के लिए ले जा सकता है या, कम से कम, आपके एपीआई अनुबंध को फुला देता है, बहुत सारे informations के साथ जो एपीआई का उपभोग करने के लिए उपयोग नहीं किया जाता है। बेशक, आप कुछ एनोटेशन (जैसे @JsonIgnoreजावा दुनिया से) का उपयोग करके फ़ील्ड्स को अनदेखा कर सकते हैं , लेकिन इससे अगली समस्या हो सकती है ...
  2. इकाई पर बहुत सारी टिप्पणियां / स्थितियाँ / नियंत्रण । आपको यह नियंत्रित करने की आवश्यकता है कि आप डटो पर क्या भेजना चाहते हैं, जब कुछ विशेषता नाम बदल जाता है (यह अनुबंध को तोड़ देगा), कुछ विशेषता जोड़ें जो इकाई से नहीं है, विशेषताओं का क्रम, आदि। जल्द ही आप अपना सरल देखेंगे बहुत सारे एनोटेशन, अतिरिक्त फ़ील्ड्स और हर बार इकाई के साथ यह समझना मुश्किल होगा कि क्या हो रहा है।
  3. कम लचीलापन । Dto के साथ आप अधिक वर्गों में जानकारी को तोड़ने के लिए स्वतंत्र हैं, विशेषता नामों को बदल सकते हैं, नई विशेषताएँ जोड़ सकते हैं, आदि। आप Dto के रूप में एक इकाई के साथ इतना आसान नहीं कर सकते।
  4. अनुकूलित नहीं है । आपकी इकाई हमेशा एक साधारण Dto से बड़ी होगी। इसलिए आपके पास हमेशा अधिक जानकारी होगी जिसे अनदेखा किया जा सकता है / क्रमबद्ध किया जाएगा और संभवत: अधिक अनावश्यक जानकारी प्रसारित की जाएगी।
  5. आलस्य की समस्या । कुछ चौखटे (जैसे हाइबरनेट) की इकाई का उपयोग करते हुए, यदि आप कुछ जानकारी को पुनः प्राप्त करने का प्रयास करते हैं जो पहले डेटाबेस लेनदेन के अंदर आलसी लोड नहीं किया गया था, तो ओआरएम प्रॉक्सी लेनदेन से जुड़ी नहीं होगी और आपको किसी प्रकार का "आलसी अपवाद" प्राप्त होगा। बस getइकाई की एक विधि को कॉल करने के लिए।

तो, इस काम में मदद करने के लिए कुछ प्रकार के मैपर टूल का उपयोग करना आसान और सुरक्षित है, इकाई फ़ील्ड को Dto पर मैप करना।


1

@Dherik ने जो कहा, उसे पूरा करने के लिए डेटा ट्रांसफर ऑब्जेक्ट के रूप में एंटिटी ऑब्जेक्ट्स का उपयोग करने की मुख्य समस्याएं हैं:

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

  2. ग्राहक और सर्वर के बीच आपके द्वारा साझा किए गए डेटा का आकार: कभी-कभी आप अनुरोध की प्रतिक्रिया के आकार को कम करने के लिए ग्राहक को किसी इकाई की सभी सामग्री नहीं भेजना चाहते हैं। डीटीओ को इकाई से अलग करना अधिक लचीला है, इसलिए उस डेटा को विशेषज्ञ करना जो आप कुछ उपयोग-मामलों में भेजना चाहते हैं।

  3. दृश्यता और रखरखाव: आपको अपनी इकाई के क्षेत्रों पर अपने jpa / hibernate एनोटेशन का प्रबंधन करना होगा और एक ही स्थान पर json में क्रमबद्ध करने के लिए jackson एनोटेशन को बनाए रखना होगा (भले ही आप उन्हें उनके द्वारा विरासत में दिए गए इंटरफ़ेस में डालकर इकाई कार्यान्वयन से अलग कर सकते हैं इकाई)। फिर, यदि आप एक नए क्षेत्र को जोड़ने में अपनी डीटीओ सामग्री को बदलते हैं, तो दूसरा व्यक्ति शायद सोच सकता है कि यह इकाई का एक क्षेत्र है, इसलिए आपके डेटाबेस में संबंधित तालिका का एक क्षेत्र (भले ही आप @Transientअपने सभी डीटीओ फ़ील्ड पर एनोटेशन का उपयोग कर सकते हैं) मामले के लिए ..!)।

मेरी राय में, जब आप इकाई को पढ़ते हैं तो यह शोर पैदा करता है, लेकिन मेरी राय निश्चित रूप से व्यक्तिपरक है।

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