2012-06-27 19 views
17

NDC12 प्रस्तुति देख जिमी Bogard (http://ndcoslo.oktaset.com/Agenda) से "दुष्ट डोमेन मॉडल क्राफ्टिंग" के बाद के साथ रिच डोमेन मॉडल, मैं भटक रहा था कैसे डोमेन मॉडल उस तरह लागू करने के लिए।व्यवहार और ORM

public class Member 
{ 
    List<Offer> _offers; 

    public Member(string firstName, string lastName) 
    { 
     FirstName = firstName; 
     LastName = lastName; 
     _offers = new List<Offer>(); 
    } 

    public string FirstName { get; set; } 

    public string LastName { get; set; } 

    public IEnumerable<Offer> AssignedOffers { 
     get { return _offers; } 
    } 

    public int NumberOfOffers { get; private set; } 

    public Offer AssignOffer(OfferType offerType, IOfferValueCalc valueCalc) 
    { 
     var value = valueCalc.CalculateValue(this, offerType); 
     var expiration = offerType.CalculateExpiration(); 
     var offer = new Offer(this, offerType, expiration, value); 
     _offers.Add(offer); 
     NumberOfOffers++; 
     return offer; 
    } 
} 

तो वहाँ कुछ इस डोमेन मॉडल में शामिल नियम हैं::
इस प्रस्तुति से नमूना वर्ग है
- सदस्य होना आवश्यक है प्रथम और अंतिम नाम
- प्रदान करता है की संख्या के बाहर नहीं बदला जा सकता
- सदस्य नए मूल्य बनाने के लिए ज़िम्मेदार है, इसकी कीमत और असाइनमेंट की गणना

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

केवल बात मेरे लिए कोई मतलब नहीं है कि उपयोग कर रहा है आदेश/क्वेरी वास्तुकला: प्रश्नों हमेशा डीटीओ के साथ किया जाता है परिणाम के रूप में, न कि डोमेन संस्थाओं, और आदेशों डोमेन मॉडल पर किया जाता है। साथ ही, ईवेंट सोर्सिंग डोमेन मॉडल पर व्यवहार के लिए बिल्कुल सही है। लेकिन इस तरह का सीक्यूएस आर्किटेक्चर शायद हर परियोजना, विशेष रूप से ब्राउनफील्ड के लिए उपयुक्त नहीं है। या नहीं?

मैं इसी तरह के सवाल यहाँ के बारे में पता है, लेकिन ठोस उदाहरण और समाधान नहीं मिल सका।

+0

मैंने अभी वही वीडियो देखा, और मैं वही चीज़ सोच रहा था। कन्स्ट्रक्टर में पोको पास करने के बारे में आप क्या सोचते हैं, और उस वर्ग के क्लोन को वापस करने के लिए सदस्य वर्ग पर एक पठनीय संपत्ति भी रखते हैं? इस तरह आप इसे जारी रखने या इसे पारित करने के लिए डोमेन ऑब्जेक्ट में डेटा को बाहर और बाहर प्राप्त कर सकते हैं। – stralsi

+0

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

+0

जाने का एकमात्र तरीका है, मैंने वास्तव में इस वीडियो को देखा और वही बात सोच रहा था; क्या इसका मतलब है कि आपको डेटा/दृढ़ता परत के लिए डीटीओ/पीओसीओ ऑब्जेक्ट्स का एक सेट चाहिए जो आपके ओआरएम हाइड्रेट्स और उसके बाद किसी डोमेन ऑब्जेक्ट पर मैप करने के लिए ऑटोमैपर जैसे मैपर का उपयोग करें? क्या ऐसा कुछ भंडार में होता है? ऐसा लगता है कि ईएफ कोड की तरह ओआरएम की तरह पहले गेटर्स और सेटर्स के साथ एक पीओसीओ की उम्मीद है। – Abe

उत्तर

1

AssignedOffers लिए: यदि आप कोड को देखो आपको लगता है कि AssignedOffers एक क्षेत्र से मान देता है देखेंगे। NHibernate इस तरह के क्षेत्र को इस तरह से पॉप्युलेट कर सकता है: मानचित्र (x => x.AssignedOffers) .ccess.Field()।

सीक्यूएस का उपयोग करने के साथ सहमत हैं।

+0

एनएच जानकारी के लिए कूल, थेंक्स! –

+0

लेकिन निर्माता के बारे में क्या? –

+0

मुझे आपके नमूने में एक निजी/संरक्षित या आंतरिक कन्स्ट्रक्टर नहीं दिख रहा है। तो NHibernate डिफ़ॉल्ट का उपयोग करेगा जो पैरामीटर-कम है। मैं इस प्रकार के कन्स्ट्रक्टर का उपयोग करता हूं जो आपने केवल यह सुनिश्चित करने के लिए किया था कि ऑब्जेक्ट कोड में पॉप्युलेट हो जाता है, न कि ओआरएम द्वारा। – Luka

0

जब DDD पहली बात कर रही है, आप दृढ़ता चिंताओं की अनदेखी। यह ओआरएम एक आरडीबीएमएस के साथ जुड़ा हुआ है, इसलिए यह एक दृढ़ता चिंता है।

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

मान लीजिए कि आप एक नया सौंपा प्रस्ताव के संदर्भ में सदस्य को बचाने के लिए चाहते हैं। तो फिर तुम कुछ इस तरह होगा (निश्चित रूप से यह केवल एक संभव परिदृश्य है)

public interface IAssignOffer 
{ 
    int OwnerId {get;} 
    Offer AssignOffer(OfferType offerType, IOfferValueCalc valueCalc); 
    IEnumerable<Offer> NewOffers {get; } 
} 

public class Member:IAssignOffer 
{ 
    /* implementation */ 
} 

public interface IDomainRepository 
{ 
    void Save(IAssignOffer member);  
} 

अगला रेपो केवल राष्ट्रीय राजमार्ग इकाइयां बदल के लिए यह आवश्यक डेटा मिलेगा और इतना ही है।

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

+0

thanx, लेकिन रिपोजिटरी लोड सदस्यों को कैसे प्रदान करना चाहिए? –

+0

उन्हें किस उद्देश्य के लिए लोड करें? :) – MikeSW

+0

सदस्य IENumerable का खुलासा करता है, इसलिए सेवा वर्ग या उस तरह के कुछ उपयोग में उपयोग के लिए। –

11

यह वास्तव में एक बहुत अच्छा सवाल है और मैंने कुछ विचार किया है। उचित डोमेन ऑब्जेक्ट्स बनाना संभवतः संभावित रूप से कठिन है (यानी कोई प्रॉपर्टी सेटर्स नहीं) और डोमेन ऑब्जेक्ट्स को सीधे बनाने के लिए ओआरएम का उपयोग करना मुश्किल है।

मेरे अनुभव में इस मुद्दे के हल के लिए 3 तरीके हैं:

  • जैसा कि पहले ही लुका द्वारा उल्लेख, NHibernate निजी क्षेत्रों के बजाय संपत्ति setters के लिए मानचित्रण का समर्थन करता है।
  • यदि ईएफ (जो मुझे लगता है कि ऊपर का समर्थन नहीं करता है) का उपयोग कर आप अपने डोमेन ऑब्जेक्ट्स को राज्य को पुनर्स्थापित करने के लिए memento pattern का उपयोग कर सकते हैं। जैसे आप 'स्मृति' ऑब्जेक्ट्स को पॉप्युलेट करने के लिए इकाई ढांचे का उपयोग करते हैं, जो आपकी डोमेन संस्थाएं अपने निजी फ़ील्ड सेट करने के लिए स्वीकार करती हैं।
  • जैसा कि आपने बताया है, घटना सोर्सिंग के साथ सीक्यूआरएस का उपयोग करके इस समस्या को समाप्त कर देता है। पूरी तरह से encapsulated डोमेन ऑब्जेक्ट्स क्राफ्टिंग की यह मेरी पसंदीदा विधि है, जिसमें ईवेंट सोर्सिंग के सभी अतिरिक्त लाभ भी हैं।
2

पुराना धागा। लेकिन वॉन वर्नन द्वारा more recent post (देर से 2014) है जो एंटीटी फ्रेमवर्क के विशेष संदर्भ के साथ इस परिदृश्य को संबोधित करता है। यह देखते हुए कि मैं किसी भी तरह की जानकारी खोजने के लिए संघर्ष कर रहा हूं, शायद इसे यहां पोस्ट करने में भी मददगार हो सकता है।

मूल रूप से Product डोमेन (कुल) वस्तु के लिए पोस्ट अधिवक्ताओं क्या "डेटा बैग" चीजों की पक्ष से संबंधित है के लिए ProductState एफई POCO डेटा वस्तु रैप करने के लिए। निस्संदेह डोमेन ऑब्जेक्ट डोमेन-विशिष्ट विधियों/एक्सेसर्स के माध्यम से अपने सभी समृद्ध डोमेन व्यवहार को जोड़ देगा, लेकिन जब यह अपनी गुणों को प्राप्त/सेट करना होगा तो यह आंतरिक डेटा ऑब्जेक्ट का सहारा लेगा।

प्रतिलिपि बनाई जा रही टुकड़ा सीधे पद से:

public class Product 
{ 
    public Product(
    TenantId tenantId, 
    ProductId productId, 
    ProductOwnerId productOwnerId, 
    string name, 
    string description) 
    { 
    State = new ProductState(); 
    State.ProductKey = tenantId.Id + ":" + productId.Id; 
    State.ProductOwnerId = productOwnerId; 
    State.Name = name; 
    State.Description = description; 
    State.BacklogItems = new List<ProductBacklogItem>(); 
    } 

    internal Product(ProductState state) 
    { 
    State = state; 
    } 

    //... 

    private readonly ProductState State; 
} 

public class ProductState 
{ 
    [Key] 
    public string ProductKey { get; set; } 

    public ProductOwnerId ProductOwnerId { get; set; } 

    public string Name { get; set; } 

    public string Description { get; set; } 

    public List<ProductBacklogItemState> BacklogItems { get; set; } 
    ... 
} 

भंडार अपने डीबी कायम संस्करण से दृष्टांत के लिए (लोड) एक इकाई उदाहरण क्रम में आंतरिक निर्माता का प्रयोग करेंगे।

एक बिट मैं अपने आप को जोड़ सकते हैं, यह है कि शायद Product डोमेन वस्तु सिर्फ एफई के माध्यम से दृढ़ता के प्रयोजन के लिए एक और एक्सेसर साथ गन्दा होना चाहिए: एक ही में new Product(productState) के रूप में था की अनुमति देता है से लोड किया जाना एक डोमेन इकाई डेटाबेस, विपरीत तरीके से कुछ के माध्यम से अनुमति दी जानी चाहिए:

public class Product 
{ 
    // ... 
    internal ProductState State 
    { 
    get 
    { 
     // return this.State as is, if you trust the caller (repository), 
     // or deep clone it and return it 
    } 
    } 
} 

// inside repository.Add(Product product): 

dbContext.Add(product.State); 
संबंधित मुद्दे