डोमेन ऑब्जेक्ट के लिए डीटीओ को मैप करने के लिए सर्वोत्तम अभ्यास?


83

मैंने DTO को डोमेन ऑब्जेक्ट्स से मैप करने से संबंधित बहुत सारे प्रश्न देखे हैं , लेकिन मुझे नहीं लगा कि उन्होंने मेरे प्रश्न का उत्तर दिया है। मैंने पहले कई तरीकों का इस्तेमाल किया है और मेरी अपनी राय है लेकिन मैं कुछ और ठोस देख रहा हूं।

स्थिति:

हमारे पास कई डोमेन ऑब्जेक्ट हैं। हम एक CSLA मॉडल का उपयोग कर रहे हैं ताकि हमारे डोमेन ऑब्जेक्ट बहुत जटिल हो सकें और उनमें अपना डेटा एक्सेस हो। आप तार पर इन चारों को पारित नहीं करना चाहते हैं। हम कुछ नई सेवाओं को लिखने जा रहे हैं जो कई प्रारूपों (.Net, JSON, आदि) में डेटा लौटाएंगे। इसके लिए (और अन्य कारणों से) हम तार पर घूमने के लिए एक दुबला, डेटा ट्रांसफर ऑब्जेक्ट भी बना रहे हैं।

मेरा सवाल है: डीटीओ और डोमेन ऑब्जेक्ट को कैसे जोड़ा जाना चाहिए?

मेरी पहली प्रतिक्रिया एक फाउलर, डीटीओ पैटर्न-प्रकार के समाधान का उपयोग करना है । मैंने कई बार ऐसा किया है और यह मुझे सही लगता है। डोमेन ऑब्जेक्ट में DTO का कोई संदर्भ नहीं है। एक बाहरी ऑब्जेक्ट (एक "मैपर" या "असेंबलर") को डोमेन ऑब्जेक्ट से डीटीओ बनाने के लिए कहा जाता है। आम तौर पर डोमेन ऑब्जेक्ट पक्ष पर एक ORM होता है। इसका नकारात्मक पक्ष यह है कि "मैपर" किसी भी वास्तविक स्थिति के लिए अत्यंत जटिल हो जाता है और बहुत नाजुक हो सकता है।

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

क्या अन्य तरीके हैं? क्या उपयोग करने के लायक ऊपर का एक तरीका है? यदि ऐसा है या नहीं तो क्यों?


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

2
जब हम DTO से डोमेन ऑब्जेक्ट पर जाते हैं, तो वह मैपिंग 100% मैनुअल होती है। यह हल करने के लिए एक बहुत कठिन समस्या है, क्योंकि हम केवल डेटा कंटेनरों के बजाय हमारे डोमेन ऑब्जेक्ट्स को ऑपरेशन-आधारित रखने का प्रयास करते हैं। जा रहे हैं करने के लिए एक डीटीओ, कि हल करने के लिए एक आसान समस्या है।
जिमी बोगार्ड

एक अन्य विकल्प ServiceToolkit.NET का बीटा संस्करण है, जिसे हमने अपने पिछले प्रोजेक्ट के दौरान शुरू किया था। शायद यह आपकी मदद कर सकता है: http://servicetoolkit.codeplex.com/

मैं सहमत हूँ कि यह गलत है कि डोमेन ऑब्जेक्ट को dto ऑब्जेक्ट का कोई ज्ञान नहीं होना चाहिए। हालांकि वे इस मामले में संबंधित हो सकते हैं, उनका उद्देश्य पूरी तरह से अलग है (dtos आमतौर पर उद्देश्य के लिए बनाए जाते हैं) और आप एक अनावश्यक निर्भरता पैदा कर रहे होंगे।
सिनास्टेटिक

जवाबों:


40

आपके डोमेन और आपके DTO के बीच बैठने वाले मैपर होने का एक फायदा यह नहीं है कि जब आप केवल एक मैपिंग का समर्थन कर रहे हैं, लेकिन जैसे-जैसे मैपिंग की संख्या बढ़ रही है, उस कोड को डोमेन से अलग करने से डोमेन को सरल और लीनियर रखने में मदद मिलती है। आप बहुत अधिक वजन के साथ अपने डोमेन को अव्यवस्थित नहीं करेंगे।

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

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


"(यदि आप A को संशोधित करते हैं, तो आपको B को भी संशोधित करना पड़ सकता है इसलिए A सेवा B के साथ काम करेगा)" - क्या यह व्यावसायिक तर्क के अंतर्गत नहीं आता है? मुझे लगता है कि इस हिस्से को सेवा के बजाय नियंत्रक पर जाना चाहिए?
अयप्पा

24

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


9
Automapper गलती से उजागर गुण -> सुरक्षा छेद को जन्म दे सकता है। यह स्पष्ट रूप से कहना बेहतर होगा कि डीटीओ के रूप में क्या उजागर किया जाना चाहिए।
deamon को

4
@deamon: वैध चिंता, लेकिन इतना बग (और मानव सुरक्षा के कारण संभावित सुरक्षा छेद) है कि सभी gooey मानचित्रण कोड लेखन बनाया जा सकता है। मैं स्वचालित सड़क पर जाऊंगा और 5% का उपयोग कर इसे कस्टम मैपिंग फीचर में बनाऊंगा।
मेरिट

@ डायमॉन - क्या आप सिर्फ उन संपत्तियों के लिए सशर्त मानचित्रण नहीं कर सकते हैं जिन्हें आप उजागर नहीं करना चाहिए? सोच रहा था कि AutoMapper उस परिदृश्य को संभालता है?
रिचर्ड बी

यदि आप AutoMapper का उपयोग करते हैं, तो मुझे लगता है कि यह जाँचने के लिए कि आपके पास मैपिंग सही ढंग से की गई है, आपके पास सभी यूनिट टेस्ट हैं।
एल-फोर

8

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

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

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


7

मैपिंग क्लासेस बनाने के लिए हम T4 टेम्प्लेट का उपयोग करते हैं।

प्रो - मानव पठनीय कोड संकलन समय पर उपलब्ध है, एक रनटाइम मैपर की तुलना में तेजी से। कोड पर 100% नियंत्रण (एक तदर्थ आधार पर कार्यक्षमता बढ़ाने के लिए आंशिक तरीकों / टेम्पलेट पैटर्न का उपयोग कर सकता है)

कॉन के - कुछ गुणों को छोड़कर, डोमेन ऑब्जेक्ट्स के संग्रह आदि, टी 4 सिंटैक्स सीखना।


3

आप एक DTO वर्ग के अंदर एक कंस्ट्रक्टर को लागू करने के लिए कैसे देखते हैं जो एक पैरामीटर ऑब्जेक्ट के रूप में लेता है?

कहो ... कुछ इस तरह

class DTO {

     // attributes 

     public DTO (DomainObject domainObject) {
          this.prop = domainObject.getProp();
     }

     // methods
}

10
कृपया, ऐसा कभी न करें। आप नहीं चाहते कि आपकी DTO परत आपके डोमेन परत के बारे में जागरूक हो या निर्भर हो। मैपिंग का लाभ यह है कि मैपिंग को बदलकर निचली परतों को आसानी से स्विच किया जा सकता है, या निचली परत में संशोधनों को मैपिंग को बदलकर नियंत्रित किया जा सकता है। चलिए आज dtoA मैप्स को domainObjectA कहते हैं, लेकिन कल आवश्यकता यह है कि यह domainObjectB को मैप करता है। आपके मामले में आपको डीटीओ ऑब्जेक्ट को संशोधित करना होगा, जो कि एक बड़ी संख्या है। आपने मैपर के लाभों को खो दिया है।
फ्रेडरिक प्रेज

2
सबसे पहले, धन्यवाद! : डी। इसलिए @FrederikPrijck DTOऔर के बीच एक परत डालकर DomainObject, हम मूल रूप से डीटीओ की इस समस्या का प्रयास करते हैं, डोमेन ऑब्जेक्ट पर निर्भर करता है, इसलिए सभी "बिल्डिंग का काम" एक मध्यम परत (वर्ग) में किया जाता है mapper, जिसे दोनों डीटीओ पर निर्भर है और DomainObjects। तो यह सबसे अच्छा है, या आम तौर पर सलाह देते हैं, इस मामले के लिए दृष्टिकोण? मैं केवल यह सुनिश्चित करने के लिए कहता हूं कि बिंदु को समझा गया था।
विक्टर

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

1
लेकिन यह जवाब वास्तव में टिप्पणियों और सुधारों के साथ "उपयोगी से अधिक" है, यह किसी भी पाठक को स्वीकार करता है और समस्या के बारे में सुझाव देता है .. यह वास्तव में सीखने में योगदान देता है, मैं नहीं देखता कि मैं डॉनवोट क्यों करता हूं .. यह मेरी मदद करता है .. लेकिन मैं उसके बारे में चर्चा शुरू नहीं करना चाहता। वैसे भी उत्तर के लिए धन्यवाद।
विक्टर

3
दरअसल, मुझे यह दृष्टिकोण पसंद है, वर्तमान में मैं निर्माता को डीटीओ को मैप करने के लिए निर्माता का उपयोग करता हूं, और मैप करने के लिए मैप करने के लिए मैपर क्लास का उपयोग करके एंटिटी का उपयोग करता हूं।
ड्रीम 83619

1

एक अन्य संभावित समाधान: http://glue.codeplex.com

विशेषताएं:

  • द्विदिश मानचित्रण
  • स्वचालित मानचित्रण
  • विभिन्न प्रकारों के बीच मानचित्रण
  • नेस्टेड मैपिंग और फ्लैटिंग
  • सूचियाँ और सारणियाँ
  • संबंधों का सत्यापन
  • मैपिंग का परीक्षण
  • गुण, फील्ड और तरीके


0

मैं एक उपकरण का सुझाव दे सकता हूं जिसे मैंने बनाया है और कोडप्लेक्स में होस्ट किया गया खुला स्रोत है: EntitiesToDTOs

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

आप कोड की तरह समाप्त करते हैं:

Foo entity = new Foo();
FooDTO dto = entity.ToDTO();
entity = dto.ToEntity();

List<Foo> entityList = new List<Foo>();
List<FooDTO> dtoList = entityList.ToDTOs();
entityList = dtoList.ToEntities();

यह वास्तुशिल्प रूप से गलत है क्योंकि आप डीटीओ और डोमेन संस्थाओं को एक-दूसरे से अवगत कराते हैं।
राफौए

5
@Raffaeu मुझे ऐसा नहीं लगता क्योंकि TODTO / ToDTOs / ToEntity / ToEntities विधियों को विस्तार विधियों के रूप में परिभाषित किया गया है जो असेंबलर्स का प्रतिनिधित्व करते हैं। एक इकाई को डीटीओ में परिवर्तित करने का तर्क और इसके विपरीत विस्तार विधियों (असेंबलर्स) में है, वास्तव में इकाई / डीटीओ में नहीं।
kzfabi 19

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

0

हम ऐसा क्यों नहीं कर सकते?

class UserDTO {
}

class AdminDTO {
}

class DomainObject {

 // attributes
 public DomainObject(DTO dto) {
      this.dto = dto;
 }     

 // methods
 public function isActive() {
      return (this.dto.getStatus() == 'ACTIVE')
 }

 public function isModeratorAdmin() {
      return (this.dto.getAdminRole() == 'moderator')
 }

}


userdto = new UserDTO();
userdto.setStatus('ACTIVE');

obj = new DomainObject(userdto)
if(obj.isActive()) {
   //print active
}

admindto = new AdminDTO();
admindto.setAdminRole('moderator');

obj = new DomainObject(admindto)
if(obj.isModeratorAdmin()) {
   //print some thing
}

@FrederikPrijck (या) कोई: कृपया सुझाव दें। उपरोक्त उदाहरण में DomainObject DTO पर निर्भर करता है। इस तरह से मैं dto <-> डोमेनोबिज मैपिंग करने के लिए कोड से बच सकता हूं।

या DomainObject क्लास DTO वर्ग का विस्तार कर सकता है?


0

एक अन्य विकल्प ModelProjector का उपयोग करना होगा । यह सभी संभावित परिदृश्यों का समर्थन करता है और न्यूनतम पदचिह्न के साथ उपयोग करना बहुत आसान है।


0

हम उसके लिए फैक्टरी, मेमेंटो और बिल्डर पैटर्न का उपयोग कर सकते हैं। फैक्ट्री डीटीओ से डोमेन मॉडल का उदाहरण कैसे बनाया जाए, इस पर विवरण छिपाएं। मेमेंटो DTO से / के लिए डोमेन मॉडल के क्रमांकन / डीरियलाइज़ेशन का ध्यान रखेगा और निजी सदस्यों तक भी पहुँच बना सकता है। बिल्डर डीटीओ से डोमेन को धाराप्रवाह इंटरफ़ेस के साथ मैप करने की अनुमति देगा।

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