2014-10-27 7 views
5

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

मैं एक डोमेन मॉडल नौकरी कहा जाता है जो इस तरह दिखता है,

public class Job 
{ 
    private DateTime _someOtherDate; 
    private DateTime _lastUpdated; 

    // this may be called from many different services 
    public void SetLastUpdated() 
    { 
    _lastUpdated = DateTime.UtcNow; 
    } 
} 

समय में कुछ बिंदु पर, प्रसंस्करण एक नौकरी मैं समय में है कि विशिष्ट बात करने के लिए काम के अंतिम अद्यतन तिथि निर्धारित करना चाहते हैं के दौरान की है। ऐसा करने के लिए मैंने इसके लिए एक सार्वजनिक सेटटर बनाया है जैसा कि आप ऊपर देख सकते हैं।

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

क्या कोई इस बात की सलाह दे सकता है कि नौकरी को पुनर्प्राप्त करते समय मैं इस संपत्ति को रिपोजिटरी कार्यान्वयन में कैसे सेट कर सकता हूं, लेकिन सेवा से नहीं, जहां यह SetLastUpdated() पर कॉल करने के लिए प्रतिबंधित है।

अपडेट 1) मैंने प्रश्न अपडेट किया है क्योंकि प्रारंभ तिथि का उपयोग करना एक बुरा उदाहरण था।

अपडेट 2) दिए गए उत्तर से, एक ही रास्ता मैं देख सकता हूँ यह किया जा रहा भंडार में AutoMapper का उपयोग नहीं है, जब नौकरी के निर्माण _lastUpdated की स्थापना, और इस का उपयोग कर के लिए नौकरी वर्ग पर एक निर्माता जोड़कर है भंडार की नौकरी पुनर्प्राप्ति विधि में वापस लौटने के लिए।

+0

आप अपने डोमेन मॉडल को हाइड्रेट करने के लिए किस प्रकार का पैटर्न उपयोग कर रहे हैं? क्या आप एक ओआरएम, या यादें का उपयोग कर रहे हैं? आपके निर्माता क्या दिखते हैं? – arootbeer

+0

मैं डोमेन मॉडल पर एंटीटी फ्रेमवर्क मॉडल को मैप करने के लिए ऑटोमैपर का उपयोग कर रहा हूं। यह वह जगह है जहां प्रारंभ तिथि निर्धारित की जाएगी। डोमेन मॉडल पर कोई रचनाकार नहीं हैं, वे डिज़ाइन द्वारा एनीमिक हैं। – Jonathan

+0

फोरम साइट्स के विपरीत, हम "धन्यवाद" या "किसी भी मदद की सराहना नहीं करते हैं", या हस्ताक्षर [so] का उपयोग नहीं करते हैं। देखें "[चाहिए 'हाय', 'धन्यवाद,' टैगलाइन, और नमस्कार पदों से हटा दिए जाएंगे?] (Http://meta.stackexchange.com/questions/2950/should-hi-thanks-taglines-and-salutations-be -प्रमुख-से-पोस्ट) –

उत्तर

1

एक आम दृष्टिकोण यह

public class Job 
{ 
    private DateTime _startDate; 

    public void Job() 
    { 
    _startDate = DateTime.UtcNow; 
    } 

    public void Job(DateTime dt) 
    { 
    // check DateTime kind, this could be source of a bug 
    if(dt.Kind != DateTimeKind.Utc) throw new ... 
    _startDate = dt; 
    } 
} 

आप इस विधि/संपत्ति एक तरह से या किसी अन्य को बेनकाब करने के लिए निर्माताओं के उपयोग करने के लिए है। यदि भंडार इसे सेट कर सकता है, तो आप इसे अन्य स्थानों से सेट कर सकते हैं। यदि आप इसके बारे में स्मार्ट होने का प्रयास करते हैं (उदाहरण के लिए, इंटरफेस का उपयोग करके आप कर सकते हैं), तो आपको अतिवृद्धि का खतरा मिल जाएगा।

+0

हाय oleksii, दिलचस्प जांच .किंड, इसके लिए धन्यवाद! मुझे लगता है कि प्रारंभ तिथि का उपयोग करना उदाहरण में एक बुरा विचार था। मेरा अपडेट देखें। – Jonathan

+0

@ जोनाथन सी # डेटटाइम एक बट में दर्द करने के लिए दर्द है। आप देखेंगे कि यह अपवाद बहुत फायरिंग होगा। हमारे पास इसके साथ कुछ कीड़े हैं। जब ओआरएम (Automapper) डिफ़ॉल्ट रूप से एक नया डेटटाइम बनाता है, अगर मुझे सही याद है, तो यह प्रकार निर्दिष्ट नहीं है। यह ऑब्जेक्ट यूटीसी तिथि को खुशी से स्वीकार करेगा, लेकिन यूटीसी प्रकार को सेट करने के लिए "भूल जाएगा"। – oleksii

1

डीडीडी कर रहे प्राथमिक कारणों में से एक प्रबंधित उत्परिवर्तन का लाभ उठाना है जिसे encapsulation द्वारा प्रदान किया जा सकता है। यह हमेशा कन्स्ट्रक्टर के साथ शुरू करने जा रहा है।

सामान्य तौर पर, इस काम के प्रकार एक ORM विशेष रूप से प्रदर्शन करने के लिए डिज़ाइन किया गया है, लेकिन यह भी किसी भी मौजूदा DTOs कि होगा memento pattern का उपयोग करके डोमेन ऑब्जेक्ट पर मैप किया गया है का लाभ ले सकते:

public Job() { 
    _lastUpdated = DateTime.UtcNow; 
    // ... 
} 

public Job(JobData data) { 
    _lastUpdated = data.LastUpdated; 
    //... 
} 

पुन: AutoMapper - यह थोड़ी देर के बाद से मैंने इसका इस्तेमाल किया, लेकिन यह possible for you to instruct it to access fields using reflection in the configuration होना चाहिए।

+0

जबकि आपके पास अच्छे अंक हैं, तो मैं नहीं कुछ चीजों को समझें। सबसे पहले, ओपी के कोड में डेट समय के लिए गेटर या सेटर नहीं है खेत। "इसे अब यूटीसी पर सेट करने" के लिए केवल एक ही विधि है। तो बाहरी कोड इसे देख या सेट नहीं कर सकता है। इस प्रकार "वर्तमान कोड वास्तव में भविष्य में किसी भी बिंदु पर _startDate को बदलने से रोकता नहीं है" गलत लगता है। दूसरा, स्मृति राज्य पिछले राज्यों के लिए किसी ऑब्जेक्ट की स्थिति को पुनर्स्थापित करने के लिए अच्छा है। मैं नहीं देख सकता कि यह इस संदर्भ में कैसे प्रासंगिक है। – oleksii

+0

@oleksii मैं जिस विधि हस्ताक्षर का जिक्र कर रहा था वह 'सार्वजनिक शून्य सेटस्टार्टडेट() 'था, जिसे ओपी ने सार्वजनिक सार्वजनिक सेट Setastastdated()' में संपादित किया है, जिसके लिए मेरा कथन बहुत कम लागू है। मैं उस भाग को संपादित कर दूंगा। 'मेमेंटो' पैटर्न किसी ऑब्जेक्ट की स्थिति को अपने पिछले राज्यों में बहाल करने के लिए अच्छा है - यदि आप ऑब्जेक्ट की पिछली स्थिति * नहीं करते हैं तो डेटाबेस में डेटा को आप क्या मानते हैं? – arootbeer

+0

इसे पिछले राज्य माना जा सकता है, अगर सभी नौकरियां वास्तव में एक ही वस्तु थीं - केवल उसी वस्तु के विभिन्न राज्यों को रिकॉर्ड कर रही थीं। लेकिन एक मेज आमतौर पर कई नौकरियों को स्टोर करती है, जो संभवतः एक ही नौकरी नहीं होती हैं।Memento एक ही ऑब्जेक्ट के उत्परिवर्तन स्टोर करता है, लेकिन इस तरह से विभिन्न वस्तुओं के संग्रह को संग्रहीत करने के लिए इसे शायद ही लागू किया जा सकता है। सही बात? – oleksii

2

जैसा कि मैंने इसे देखा, आपके पास कई विकल्प हैं।

विकल्प 1

यह मानते हुए कि अपने भंडार दो विधियों है:

public IEnumerable<Job> ReadAll() { ... } 
public int CreateJob(Job job) { ... } 

आप Job वर्ग दो कंस्ट्रक्टर्स, एक है कि एक DateTime और एक कि नहीं लेता दे सकते हैं।

public class Job 
{ 
    public Job(DateTime startDate) 
    { 
     this.StartDate = startDate; 
    } 

    public Job() : this(DateTime.UtcNow) 
    { 

    } 

    public DateTime StartDate { get; private set; } 
} 

यह "गलत" निर्माता को कॉल करने से सेवा नहीं रोकता है, लेकिन कम से कम यह फोन करने वाले को startDate बिना यह बुला का विकल्प संचार करता है। दो अलग-अलग वर्गों के साथ Job

विकल्प 2

कार्य करें।

आपका भंडार इस बजाय दिखाई देगा:

public IEnumerable<Job> ReadAll() { ... } 
public int CreateJob(NewJob newJob) { ... } 

और NewJob वर्ग दिखाई दे सकता है जैसे:

public class NewJob 
{ 
    public NewJob() 
    { 
     this.StartDate = DateTime.UtcNow; 
    } 

    public DateTime StartDate { get; private set; } 
} 

इस आशय बेहतर संचार करता है, क्योंकि भंडार के Create विधि केवल NewJob का एक उदाहरण स्वीकार करता है इसलिए मॉडल के उपयोगकर्ता को Job के बजाय NewJob बनाने के लिए मजबूर किया जाएगा।

विकल्प 3

repostory के Create विधि में StartDate पर ध्यान न दें और हमेशा विधि के भीतर DateTime.UtcNow पर सेट करें। या यहां तक ​​कि Insert डेटाबेस को ट्रिगर करने के लिए भी सेट करें, जो इसे सेट करता है।

+0

धन्यवाद। मुझे लगता है कि उदाहरण में प्रारंभ तिथि का उपयोग करना एक बुरा विचार था। मेरा अपडेट जांचें। – Jonathan

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