15

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

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

विकल्प 1: डीडीडी की मूलभूत बातें [मेरी समझ] के साथ चिपकने का प्रयास करें जहां इकाई से संबंधित व्यवहार सीधे इकाई के हिस्से के रूप में लागू किया जाता है (व्यक्ति लागू करता है AddEmail, ChangeEmail, आदि)। इसके साथ एकमात्र समस्या, जोड़ें * विधियों के अपवाद के साथ, यह है कि व्यक्ति को संदर्भ या इकाई ढांचे के टुकड़ों (जो किसी भी दृढ़ता अज्ञान को हटा देगा) के बारे में जानना होगा या चिह्नित करने के लिए "सेवा" या भंडार का उपयोग करने की आवश्यकता होगी संशोधित के रूप में ईमेल।

// Person Service 
public class PersonService { 
    // constructor injection to get unit of work and person repository... 
    // ...methods to add/update a person 
    public EmailAddress AddEmailAddress(int personId, EmailAddress email) 
    { 
     Person p = personRepository.Find(p => p.Id == personId).First(); 
     p.AddEmail(email); 
     uow.SaveChanges(); 
     return email; 
    } 

    public EmailAddress ChangeEmailAddress(EmailAddress email) 
    { 
     Person p = personRepository.Find(p => p.Id == personId).First(); 
     p.ChangeEmail(email); 
     // change state of email object here so it's updated in the next line??? 
     // if not here, wouldn't the Person entity have to know about the context 
     // or use a service? 
     uow.SaveChanges(); 
     return email;  
    } 
} 

// Person Repository 
public class PersonRepository 
{ 
    // generic repository implementation 
} 

// Person Entity 
public class Person 
{ 
    public string Name { get;set; } 
    public IEnumerable<EmailAddress> EmailAddresses { get;set; } 

    public void AddEmail(EmailAddress email) 
    { 
     this.EmailAddresses.Add(email); 
    } 

    public void ChangeEmail(EmailAddress email) 
    { 
     EmailAddress orig = this.EmailAddresses.First(e => e.Id == email.id); 

     // update properties on orig 

     // NOW WHAT? [this] knows nothing about the context in order to change state, 
     etc, or do anything to mark the email add updated 
    } 
} 

// Email 
public class EmailAddress 
{ 
    public string Email { get;set; } 
    public bool IsPrimary { get;set; } 
} 

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

// Person Service 
public class PersonService { 
    // constructor injection to get unit of work and person repository... 
    // ...methods to add/update a person 
    public EmailAddress AddEmailAddress(int personId, EmailAddress email) 
    { 
     Person p = personRepository.Find(p => p.Id == personId).First(); 
     personRepository.AddEmail(personId, email); 
     uow.SaveChanges(); 
     return email; 
    } 

    public EmailAddress ChangeEmailAddress(EmailAddress email) 
    { 
     personRepository.ChangeEmail(email); 
     uow.SaveChanges(); 
     return email;  
    } 
} 

// Person Repository 
public class PersonRepository 
{ 
    // generic repository implementation 
} 

// Person Entity 
public class Person 
{ 
    public string Name { get;set; } 
    public IEnumerable<EmailAddress> EmailAddresses { get;set; } 
} 

// Email 
public class EmailAddress 
{ 
    public string Email { get;set; } 
    public bool IsPrimary { get;set; } 
} 

वैसे भी, इस पर कोई विचार?

धन्यवाद, ब्रायन

+0

अच्छा, साफ और समझने में आसान प्रश्न।:) –

उत्तर

0

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

और मेरा मानना ​​है कि ईएफ 4 को संग्रह परिवर्तनों को ट्रैक करने के बारे में पता होना चाहिए। यदि नहीं, तो सबसे अच्छा तरीका है अपनी व्यक्तिगत इकाई में तर्क जोड़ने/हटाने और व्यक्ति सेवा में बने रहना।

बीटीडब्ल्यू, आपका ईमेल एड्रेस यहां एक इकाई नहीं है, कोई आईडी नहीं है (केवल एक टाइपो मुझे लगता है)। और आप अपने ईमेल एड्रेस को व्यक्ति से कैसे लिंक करते हैं?

+0

कोस्टासोइड - व्यक्ति का ईमेल एड्रेस का संग्रह है। ईमेल एड्रेस में एक आईडी है, यह एक टाइपो था। – user800131

2

विकल्प 1 जाने का तरीका है।

तर्क सरल है - ई-मेल पते बदलना डोमेन चिंता है। मैं शर्त लगाता हूं कि आपके डोमेन विशेषज्ञों ने कहा है कि उन्हें ईमेल बदलने की आवश्यकता होगी। यह स्वचालित रूप से डोमेन तर्क में रहने वाले व्यापार तर्क के रूप में तर्क के ईमेल बदलने वाले टुकड़े को चिह्नित करता है। ऑब्जेक्ट्स को मुख्य रूप से उनके व्यवहार द्वारा परिभाषित किया जाता है, न कि उनके पास डेटा।

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

मैं कुछ इस तरह होगा:

public class Person{ 
    public Email Email{get;private set;} 
    public void SpecifyEmail(Email email){ 
    //some validation, if necessary 
    EnsureEmailCanBeChanged(); 
    //applying state changes 
    Email=email; 
    //raising event, if necessary 
    Raise(new EmailChanged(this)); 
    } 
    public class EmailChanged:Event<Person>{ 
    public EmailChanged(Person p):base(p){} 
    } 
} 
public class Email{ 
    public Email(string email){ 
    //validations (e.g. email format) 
    Value=email; 
    } 
    //implicit to string, explicit from string conversions 
} 

public class PersonController{ 
    public ActionResult SpecifyEmail(int person, string email){ 
    _persons.Get(person).SpecifyEmail((Email)email); 
    return RedirectToAction("Person",new{person}); 
    } 
} 

मैं NHibernate का उपयोग कर रहा है - यह बहुत चालाक यह पता लगाने की के बाद से व्यक्ति पिछली बार कायम किया गया था क्या बदल गया है। यह कहना मुश्किल है कि वास्तव में इकाई ढांचा कैसे संभालता है।

+0

अर्निस - आपके परिदृश्य में, कौन सी इकाई/सेवा घटना की सदस्यता लेती है और क्या वह समय है जब परिवर्तन ईएफ या रिपोजिटरी का उपयोग करके जारी रहेगा? तो अपना उदाहरण और मेरा विलय कर रहा है, व्यक्ति सेवा व्यक्ति से ईमेलChanging घटना की सदस्यता लेगी और फिर तब होता है जब परिवर्तन होता है? – user800131

+0

@ user800131 कुछ भी जो वास्तव में रुचि रखते हैं कि ईमेल बदल गया है। घटनाओं का उपयोग यह पता लगाने के लिए किया जा सकता है कि परिवर्तन कब जारी रहें, लेकिन इससे आपको हर जगह घटनाओं का उपयोग करने के लिए मजबूर किया जाएगा। मैं व्यक्तिगत रूप से केवल NHibernate पर भरोसा करता हूं जो संस्थाओं की गंदगी को ट्रैक करता है। –

+0

यह 'उठाएं (नया ईमेल चेंज किया गया (यह)) दिलचस्प लगता है, उस पर कोई जानकारी? :) – Ian

संबंधित मुद्दे