2010-02-10 3 views
8

निम्नलिखित सरल उदाहरण पर विचार करें। बाद में टिकट के जीवन चक्र में अन्य राज्यों को स्थापित किया जा सकता है।DDD इकाई राज्य संक्रमण

टिकट टिकट तालिका के साथ-साथ टिकटस्टेट में भी जारी है। तो डीबी के भीतर टिकट टिकट राज्य तालिका के लिए एक विदेशी कुंजी होगी।

जब मेरी यूनिट के भीतर उपयुक्त राज्य की स्थापना, मैं कैसे डीबी से राज्य उदाहरण लोड करूं? क्या मुझे इकाई में एक भंडार इंजेक्ट करना है? क्या मुझे ऐसे मामले के लिए महल जैसे ढांचे का उपयोग करने की ज़रूरत है? या क्या बेहतर समाधान हैं, शायद बाहर से राज्य को पारित कर रहे हैं?

public class Ticket 
{ 
    //... 
    public ITicketStateRepository stateRep; //<-- inject 

    public Ticket() 
    { 
     State = stateRep.GetById(NEW_STATE_ID); 
    } 
    //... 
} 

क्या कोई सर्वोत्तम अभ्यास है? अब तक मैं किसी भी निर्भरता इंजेक्शन ढांचे या कुछ भी उपयोग नहीं किया है और मैं डोमेन से बाहर एक और approch किसी भी हठ बातें रखा ..

:

public class Ticket 
{ 
    //... 

    public Ticket(NewTicketState newTicketState) 
    { 
     State = newTicketState; 
    } 
    public void Finished(FinishedTicketState finishedTicketState) 
    { 
     State = finishedTicketState; 
    } 
    //... 
} 

उत्तर

4

टिकट भंडार के लिए एक संदर्भ नहीं होगा। यह टिकटस्टेट के साथ एक-से-एक संबंध होगा, और टिकट रिपोजिटरी बस जॉइन करेगी और टिकटों को टिकट में मैप करेगी।

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

कुछ लोग इस पर आपत्ति करते हुए कहा कि यह एक anemic domain model की ओर जाता है; शायद आप उनमें से एक हैं। यदि ऐसा है, तो अपने टिकट ऑब्जेक्ट में रिपोजिटरी इंजेक्ट करें, लेकिन सरल इसे जॉइन करने के लिए कहें और अपने राज्य के साथ एक टिकट वापस कर दें। जब आप सम्मिलित करते हैं या अपडेट करते हैं तो आपको दो टेबल को काम की एक इकाई के रूप में संशोधित करना होता है, इसलिए सुनिश्चित करें कि लेनदेन चालू हो।

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

अद्यतन:

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

मॉडल में दृढ़ता सम्मिलित करें और वे cyclicly एक दूसरे पर निर्भर कर रहे हैं। आप बिना किसी के किसी एक का उपयोग या परीक्षण कर सकते हैं। कोई लेयरिंग नहीं, चिंताओं का कोई अलगाव नहीं।

+0

+1 निरंतर वस्तुओं के लिए +1। सिर्फ इसलिए कि डोमेन मॉडल को रिपोजिटरी ऑब्जेक्ट्स के साथ प्रदूषित किया गया है, इसका मतलब यह नहीं है कि यह एनीमिक नहीं है - असल में, यह उन स्थानों को छुपा सकता है जहां डोमेन ऑब्जेक्ट्स अपना वजन नहीं ले रहे हैं। –

+0

धन्यवाद लेकिन शायद मेरा प्रश्न पर्याप्त स्पष्ट नहीं था। मैं पूछ रहा था कि एप्राइपिएट स्टेट इकाई को कैसे सेट करें जब उदा। टिकट instanstiated है या इसकी स्थिति बदल गई है। क्या आप उपरोक्त समस्या को हल करने के तरीके पर एक उदाहरण पोस्ट कर सकते हैं? – Chris

+0

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

1

यह उत्तर उम्मीद है कि डफिमो से है।

दुनिया के एक DDD ध्यान में रखते हुए अपने TicketState एक इकाई है कि टिकट कुल (जहां एक टिकट कुल जड़ है) का हिस्सा है।

इसके बाद, आपकी टिकट रिपोजिटरी टिकट, और टिकटस्टेट दोनों के साथ सौदा करती है।

जब आप दृढ़ता परत से टिकट प्राप्त करते हैं तो आप अपने टिकट रिपोजिटरी को राज्य को डीबी से पुनर्प्राप्त करने और उसे सही ढंग से टिकट पर सेट करने की अनुमति देते हैं।

यदि आप टिकट खरीद रहे हैं तो (मुझे लगता है) आपको अभी तक डेटाबेस को स्पर्श करने की आवश्यकता नहीं है। जब टिकट अंततः जारी रहता है, तो आप टिकट की नई स्थिति लेने और इसे सही तरीके से जारी रखने के बजाय।

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

+0

लेकिन अगर मैं एक नया टिकट तुरंत चालू करता हूं, जो अभी तक जारी नहीं है और उपयोगकर्ता इंटरफ़ेस पर अपना राज्य नाम (डीबी में संग्रहीत) प्रदर्शित करना चाहता है तो क्या होगा? मुझे वह जानकारी कहां मिलती है? – Chris

+0

@ क्रिस - नीचे मेरी टिप्पणी देखें। – duffymo

0

मेरे लिए, डेटाबेस में राज्य का प्रतिनिधित्व करने वाली एक साधारण कुंजी-मूल्य जोड़ी (या जो भी दृढ़ता माध्यम) को डोमेन में इस तरह मॉडल करने की आवश्यकता नहीं है। डोमेन में, मैं टिकटस्टेट को एक enum बना दूंगा, और यह डेटाबेस स्कीमा की आवश्यकताओं को मैप करने के तरीके के बारे में जानने के लिए ITicketRepository की ज़िम्मेदारी बनाउंगा।

टिकट भंडार के भीतर, आप टिकटस्टेट पर कुंजी टिकट आईडी आईडी का कैश कर सकते हैं, जो डाटाबेस से एक स्थैतिक चर (केवल एक दृष्टिकोण) में आलसी भरा हुआ है। टिकट भंडार टिकट को मानचित्रित करेगा। उस कैश से आईडी को आवेषण/अपडेट के लिए आईडी मान करें।

namespace Domain { 
    public class Ticket { 
    public Ticket() { State = TicketStates.New; } 
    public void Finish() { State = TicketStates.Finished; } 
    public TicketStates State {get;set;} 
    } 

    public enum TicketState { New, Finished } 
} 

namespace Repositories { 
    public class SqlTicketRepository : ITicketRepository { 
    public void Save(Ticket ticket) { 
     using (var tx = new TransactionScope()) { // or whatever unit of work mechanism 
     int newStateId = TicketStateIds[ticket.State]; 
     // update Ticket table with newStateId 
     } 
    } 
    } 

    private Dictionary<TicketState, int> _ticketStateIds; 
    protected Dictionary<TicketState, int> TicketStateIds{ 
    get { 
     if (_ticketStateIds== null) 
     InitializeTicketStateIds(); 
     return _ticketStateIds; 
    } 
    } 

    private void InitializeTicketStateIds() { 
    // execute SQL to get all key-values pairs from TicketStateValues table 
    // use hard-coded mapping from strings to enum to populate _ticketStateIds; 
    } 
} 
+0

मॉडल के रूप में मैं इस बात से सहमत हूं - हालांकि, अगर राज्य संक्रमण को विकसित करने की आवश्यकता है तो यह व्यापार तर्क व्यक्त कर सकता है, फिर राज्य इकाई होने से बहुत अधिक अर्थ हो सकता है। –

+0

लेकिन अगर मैं एक नया टिकट तुरंत चालू करता हूं, जो अभी तक जारी नहीं है और उपयोगकर्ता इंटरफ़ेस पर अपना राज्य नाम (डीबी में संग्रहीत) प्रदर्शित करना चाहता है तो क्या होगा? मुझे वह जानकारी कहां मिलती है? – Chris

+0

इसे तुरंत चालू करने के बाद और यूआई को प्रदर्शित करने से पहले इसे आसान बनाएं। सहेजे जाने से पहले आप एक सतत वस्तु की स्थिति क्यों दिखाएंगे? जब तक यह पूरा नहीं हो जाता तब तक आप किसी भी ऑपरेशन के परिणाम को किसी भी ऑपरेशन का प्रदर्शन नहीं करते हैं, और यह तब तक पूरा नहीं होता जब तक कि यह जारी न हो जाए। – duffymo