2017-12-16 120 views
5

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

समाधान 1:

पहले संभव समाधान परिवर्तित करने के लिए सेवा परत में निजी विधि सेवा परत कोड में एक छोटी सी "सहायक" विधि है जो मेरी डीटीओ वस्तु को पुनः प्राप्त डेटाबेस वस्तु convertig है बनाने के लिए है ।

@Service 
public MyEntityService { 

    public SomeDto getEntityById(Long id){ 
    SomeEntity dbResult = someDao.findById(id); 
    SomeDto dtoResult = convert(dbResult); 
    // ... more logic happens 
    return dtoResult; 
    } 

    public SomeDto convert(SomeEntity entity){ 
    //... Object creation and using getter/setter for converting 
    } 
} 

पेशेवरों: -:

    • आसान लागू करने के लिए रूपांतरण की जरूरत के लिए कोई अतिरिक्त वर्ग> परियोजना संस्थाओं

    विपक्ष के साथ उड़ा नहीं है

  • परीक्षण करते समय समस्याएं,के रूप मेंमेरी when(someDao.findById(id)).thenReturn(alsoDeeplyNestedObject) की एक पर्याप्त परिणाम प्रदान करने के लिए privated विधि में प्रयोग किया जाता है और अगर वस्तु गहरा नीडिंत है मेरे पास है NullPointers से बचने के लिए यदि रूपांतरण भी आंतरिक संरचना

समाधान 2 भंग किया जाता है: डीटीओ में अतिरिक्त निर्माता डोमेन इकाई को डीटीओ

मेरा दूसरा समाधान कन्स्ट्रक्टर में ऑब्जेक्ट को कन्वर्ट करने के लिए मेरे डीटीओ इकाई में एक अतिरिक्त कन्स्ट्रक्टर जोड़ना होगा।

public class SomeDto { 

// ... some attributes 

public SomeDto(SomeEntity entity) { 
    this.attribute = entity.getAttribute(); 
    // ... nesting convertion & convertion of lists and arrays 
} 

} 

पेशेवरों: -:

    • जरूरत परिवर्तित
    • रूपांतरण डीटीओ इकाई में hided के लिए कोई अतिरिक्त वर्ग> सेवा कोड छोटे

    विपक्ष हैका उपयोग 10 सेवा कोड में और इसके लिए मुझे अपने someDao मॉकिंग के परिणामस्वरूप सही नेस्टेड ऑब्जेक्ट स्ट्रक्चर प्रदान करना होगा।

समाधान 3: Converter<S, T> लेकिन इस समाधान हर externalized वर्ग है जो के लिए खड़ा है: स्प्रिंग के कनवर्टर या किसी अन्य इस परिवर्तित

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

सकारात्मक:

  • के रूप में मैं अपने परीक्षण मामले के दौरान परिणाम नकली कर सकते हैं कार्यों की
  • जुदाई का परीक्षण करने के लिए आसान -> एक समर्पित वर्ग काम

विपक्ष कर रहा है:

  • मेरा डोमेन मॉडल बढ़ने के जितना "स्केल" नहीं करता है। (-> डीटीओ को डीटीओ entitiy और entitiy परिवर्तित)

आप मेरी समस्या के लिए और अधिक समाधान है और आप इसे कैसे संभाल करते हो संस्थाओं मैं हर नई इकाई के लिए दो कन्वर्टर्स बनाने के लिए की एक बहुत कुछ के साथ? क्या आप हर नए डोमेन ऑब्जेक्ट के लिए एक नया कनवर्टर बनाते हैं और परियोजना में कक्षाओं की मात्रा के साथ "लाइव" कर सकते हैं?

अग्रिम धन्यवाद!

+0

विकल्प 4 [MapStruct] (http://mapstruct.org) जैसे कुछ का उपयोग कर विकल्प 4। –

उत्तर

4

समाधान 1: सेवा परत में निजी विधि

परिवर्तित करने के लिए मैं समाधान लगता है 1, अच्छी तरह से काम नहीं नहीं करेगा क्योंकि आपका DTOs डोमेन उन्मुख और नहीं उन्मुख सेवा कर रहे हैं। इस प्रकार यह संभावना है कि वे विभिन्न सेवाओं में उपयोग किया जाता है। तो एक मैपिंग विधि एक servce से संबंधित नहीं है और इसलिए एक सेवा में लागू नहीं किया जाना चाहिए। आप दूसरी सेवा में मैपिंग विधि का फिर से उपयोग कैसे करेंगे?

1. यदि आप समर्पित सेवा डीटीओ प्रति सेवा विधि का उपयोग करते हैं तो समाधान अच्छी तरह से काम करेगा। लेकिन अंत में इसके बारे में अधिक। डीटीओ

के लिए डोमेन इकाई परिवर्तित सामान्य एक अच्छा विकल्प में, क्योंकि आप संस्था के लिए एक एडाप्टर के रूप में डीटीओ देख सकते हैं के लिए अतिरिक्त निर्माता डीटीओ में:

समाधान 2। दूसरे शब्दों में: डीटीओ एक इकाई का एक और प्रतिनिधित्व है। इस तरह के डिज़ाइन अक्सर स्रोत ऑब्जेक्ट को लपेटते हैं और उन तरीकों को प्रदान करते हैं जो आपको लिपटे ऑब्जेक्ट पर एक और दृश्य देते हैं।

लेकिन एक डीटीओ डेटा स्थानांतरण ऑब्जेक्ट है ताकि इसे जल्दी या बाद में क्रमबद्ध किया जा सके और नेटवर्क पर भेज दिया जा सके, उदा। spring's remoting capabilities का उपयोग कर। इस मामले में जो क्लाइंट इस डीटीओ को प्राप्त करता है उसे अव्यवस्थित करना चाहिए और इस प्रकार इसे कक्षा के वर्ग में इकाई वर्गों की आवश्यकता होती है, भले ही यह केवल डीटीओ के इंटरफेस का उपयोग करे।

समाधान 3: वसंत के कनवर्टर या इस के लिए किसी भी अन्य externalized बीन परिवर्तित

समाधान 3 का उपयोग समाधान है कि मैं भी पसंद करेंगे है। लेकिन मैं Mapper<S,T> इंटरफ़ेस बनाउंगा जो स्रोत से लक्ष्य और इसके विपरीत मैपिंग के लिए ज़िम्मेदार है। जैसे

public interface Mapper<S,T> { 
    public T map(S source); 
    public S map(T target); 
} 

कार्यान्वयन modelmapper जैसे मैपिंग फ्रेमवर्क का उपयोग करके कार्यान्वित किया जा सकता है।


आप यह भी कहा कि प्रत्येक इकाई

के लिए एक कनवर्टर नहीं "पैमाने" इतना मेरे डोमेन मॉडल का विस्तार होता है करता है। क्योंकि

- (डीटीओ को डीटीओ entitiy और entitiy परिवर्तित>) मैं doupt आप केवल 2 कनवर्टर या एक डीटीओ के लिए एक नक्शाकार बनाने होंगे संस्थाओं का एक बहुत के साथ मैं हर नई इकाई के लिए दो कन्वर्टर्स बनाने के लिए आपका डीटीओ डोमेन उन्मुख है।

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

यह उत्तर लंबे समय तक होगा यदि मैं समर्पित या साझा डीटीओ के पेशेवरों और विपक्ष से शुरू करता हूं, इसलिए मैं केवल आपको अपने ब्लॉग pros and cons of service layer designs पढ़ने के लिए कह सकता हूं।

+0

आपके विस्तृत उत्तर के लिए धन्यवाद। – rieckpil

4

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

2

मुझे स्वीकृत उत्तर से तीसरा समाधान पसंद है।

समाधान 3:

BaseEntity वर्ग मार्कर:

public abstract class BaseEntity implements Serializable { 
} 

वसंत के कनवर्टर या किसी अन्य इस परिवर्तित

और मैं इस तरह से DtoConverter बनाने के लिए बीन externalized का उपयोग करना कक्षा के लिए सारणी:

public class AbstractDto { 
} 

GenericConverter इंटरफ़ेस:

public interface GenericConverter<D extends AbstractDto, E extends BaseEntity> { 

    E createFrom(D dto); 

    D createFrom(E entity); 

    E updateEntity(E entity, D dto); 

    default List<D> createFromEntities(final Collection<E> entities) { 
     return entities.stream() 
       .map(this::createFrom) 
       .collect(Collectors.toList()); 
    } 

    default List<E> createFromDtos(final Collection<D> dtos) { 
     return dtos.stream() 
       .map(this::createFrom) 
       .collect(Collectors.toList()); 
    } 

} 

CommentConverter इंटरफ़ेस:

public interface CommentConverter extends GenericConverter<CommentDto, CommentEntity> { 
} 

CommentConveter वर्ग कार्यान्वयन:

मैपिंग कोड उत्पन्न करने के लिए
संबंधित मुद्दे