2012-06-13 15 views
9

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

मैं स्टैक ओवरफ्लो पर सिमिलियर प्रश्न पर my own answer से आ रहा हूं। मैं इस समस्या पर अपनी दृष्टि से पूरी तरह से संतुष्ट नहीं हूं इसलिए मैंने सोचा कि मुझे इस मामले पर विस्तार करने की जरूरत है।

उदाहरण के लिए, मुझे साधारण मॉडल बनाने की ज़रूरत है जो कार नामकरण का प्रतिनिधित्व करती है: कंपनी, मॉडल और संशोधन (उदाहरण के लिए, निसान टीना 2012 - वह "निसान" कंपनी, "टीना" मॉडल और "2012" संशोधन होगी)।

मॉडल मैं इस तरह दिखता है बनाना चाहते हैं स्केच:

CarsCompany 
{ 
    Name 
    (child entities) Models 
} 

CarsModel 
{ 
    (parent entity) Company 
    Name 
    (child entities) Modifications 
} 


CarsModification 
{ 
    (parent entity) Model 
    Name 
} 

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

पहला दृष्टिकोण।

मैं कारखाने के तरीकों के माध्यम से विशिष्ट वस्तु निर्माण के साथ सरल दृष्टिकोण से शुरू करूंगा।

using (var tx = session.BeginTransaction()) 
{ 
    var company = CarsCompany.Create ("Nissan"); 

    var model = CarsModel.Create (company, "Tiana"); 
    company.AddModel (model); 
    // (model.Company == company) is true 
    // but (company.Models.Contains (model)) is false 

    var modification = CarsModification.Create (model, "2012"); 
    model.AddModification (modification); 
    // (modification.Model == model) is true 
    // but (model.Modifications.Contains (modification)) is false 

    session.Persist (company); 
    tx.Commit(); 
} 

के बाद लेन-देन के लिए प्रतिबद्ध है और सत्र प्लावित है, ORM करेंगे:

public class CarsCompany 
{ 
    public virtual string Name { get; protected set; } 
    public virtual IEnumerable<CarsModel> Models { get { return new ImmutableSet<CarsModel> (this._models); } } 


    private readonly ISet<CarsModel> _models = new HashedSet<CarsModel>(); 


    protected CarsCompany() 
    { 
    } 


    public static CarsCompany Create (string name) 
    { 
     if (string.IsNullOrEmpty (name)) 
      throw new ArgumentException ("Invalid name specified."); 

     return new CarsCompany 
     { 
      Name = name 
     }; 
    } 


    public void AddModel (CarsModel model) 
    { 
     if (model == null) 
      throw new ArgumentException ("Model is not specified."); 

     this._models.Add (model); 
    } 
} 


public class CarsModel 
{ 
    public virtual CarsCompany Company { get; protected set; } 
    public virtual string Name { get; protected set; } 
    public virtual IEnumerable<CarsModification> Modifications { get { return new ImmutableSet<CarsModification> (this._modifications); } } 


    private readonly ISet<CarsModification> _modifications = new HashedSet<CarsModification>(); 


    protected CarsModel() 
    { 
    } 


    public static CarsModel Create (CarsCompany company, string name) 
    { 
     if (company == null) 
      throw new ArgumentException ("Company is not specified."); 

     if (string.IsNullOrEmpty (name)) 
      throw new ArgumentException ("Invalid name specified."); 

     return new CarsModel 
     { 
      Company = company, 
      Name = name 
     }; 
    } 


    public void AddModification (CarsModification modification) 
    { 
     if (modification == null) 
      throw new ArgumentException ("Modification is not specified."); 

     this._modifications.Add (modification); 
    } 
} 


public class CarsModification 
{ 
    public virtual CarsModel Model { get; protected set; } 
    public virtual string Name { get; protected set; } 


    protected CarsModification() 
    { 
    } 


    public static CarsModification Create (CarsModel model, string name) 
    { 
     if (model == null) 
      throw new ArgumentException ("Model is not specified."); 

     if (string.IsNullOrEmpty (name)) 
      throw new ArgumentException ("Invalid name specified."); 

     return new CarsModification 
     { 
      Model = model, 
      Name = name 
     }; 
    } 
} 

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

दूसरा दृष्टिकोण।

इस बार हम अन्य वर्गों के संरक्षित गुणों को स्थापित करने की समस्या को हल करने के लिए भाषा विशिष्ट विकल्प का उपयोग करेंगे - अर्थात हम दोनों सेटर्स और कन्स्ट्रक्टर पर "संरक्षित आंतरिक" संशोधक का उपयोग करेंगे।

public class CarsCompany 
{ 
    public virtual string Name { get; protected set; } 
    public virtual IEnumerable<CarsModel> Models { get { return new ImmutableSet<CarsModel> (this._models); } } 


    private readonly ISet<CarsModel> _models = new HashedSet<CarsModel>(); 


    protected CarsCompany() 
    { 
    } 


    public static CarsCompany Create (string name) 
    { 
     if (string.IsNullOrEmpty (name)) 
      throw new ArgumentException ("Invalid name specified."); 

     return new CarsCompany 
     { 
      Name = name 
     }; 
    } 


    public CarsModel AddModel (string name) 
    { 
     if (string.IsNullOrEmpty (name)) 
      throw new ArgumentException ("Invalid name specified."); 

     var model = new CarsModel 
     { 
      Company = this, 
      Name = name 
     }; 

     this._models.Add (model); 

     return model; 
    } 
} 


public class CarsModel 
{ 
    public virtual CarsCompany Company { get; protected internal set; } 
    public virtual string Name { get; protected internal set; } 
    public virtual IEnumerable<CarsModification> Modifications { get { return new ImmutableSet<CarsModification> (this._modifications); } } 


    private readonly ISet<CarsModification> _modifications = new HashedSet<CarsModification>(); 


    protected internal CarsModel() 
    { 
    } 


    public CarsModification AddModification (string name) 
    { 
     if (string.IsNullOrEmpty (name)) 
      throw new ArgumentException ("Invalid name specified."); 

     var modification = new CarsModification 
     { 
      Model = this, 
      Name = name 
     }; 

     this._modifications.Add (modification); 

     return modification; 
    } 
} 


public class CarsModification 
{ 
    public virtual CarsModel Model { get; protected internal set; } 
    public virtual string Name { get; protected internal set; } 


    protected internal CarsModification() 
    { 
    } 
} 

... 

using (var tx = session.BeginTransaction()) 
{ 
    var company = CarsCompany.Create ("Nissan"); 
    var model = company.AddModel ("Tiana"); 
    var modification = model.AddModification ("2011"); 

    session.Persist (company); 
    tx.Commit(); 
} 

इस बार प्रत्येक इकाई निर्माण लगातार राज्य में माता-पिता और बाल इकाई दोनों को छोड़ देता है। लेकिन बाल इकाई राज्य की वैधता मूल इकाई (AddModel और AddModification विधियों में लीक हुई) में लीक हुई। चूंकि मैं डीडीडी में कहीं भी विशेषज्ञ नहीं हूं, मुझे यकीन नहीं है कि यह ठीक है या नहीं। यह भविष्य में और अधिक समस्याएं पैदा कर सकता है जब बच्चे संस्थाओं को गुणों के माध्यम से बस सेट नहीं किया जा सकता है और पास किए गए पैरामीटर के आधार पर कुछ राज्य स्थापित करने के लिए अधिक जटिल कार्य की आवश्यकता होती है जो संपत्ति को पैरामीटर मान निर्दिष्ट करती है। मैं इस धारणा के तहत था कि जहां भी संभव हो, उस इकाई के अंदर इकाई के बारे में तर्क को ध्यान में रखना चाहिए। मेरे लिए यह दृष्टिकोण मूल वस्तु को किसी प्रकार की इकाई & फैक्टरी हाइब्रिड में बदल देता है।

तीसरा दृष्टिकोण।

ठीक है, हम अभिभावक-बाल संबंध बनाए रखने की जिम्मेदारियों को उलटा कर देंगे।

public class CarsCompany 
{ 
    public virtual string Name { get; protected set; } 
    public virtual IEnumerable<CarsModel> Models { get { return new ImmutableSet<CarsModel> (this._models); } } 


    private readonly ISet<CarsModel> _models = new HashedSet<CarsModel>(); 


    protected CarsCompany() 
    { 
    } 


    public static CarsCompany Create (string name) 
    { 
     if (string.IsNullOrEmpty (name)) 
      throw new ArgumentException ("Invalid name specified."); 

     return new CarsCompany 
     { 
      Name = name 
     }; 
    } 


    protected internal void AddModel (CarsModel model) 
    { 
     this._models.Add (model); 
    } 
} 


public class CarsModel 
{ 
    public virtual CarsCompany Company { get; protected set; } 
    public virtual string Name { get; protected set; } 
    public virtual IEnumerable<CarsModification> Modifications { get { return new ImmutableSet<CarsModification> (this._modifications); } } 


    private readonly ISet<CarsModification> _modifications = new HashedSet<CarsModification>(); 


    protected CarsModel() 
    { 
    } 


    public static CarsModel Create (CarsCompany company, string name) 
    { 
     if (company == null) 
      throw new ArgumentException ("Company is not specified."); 

     if (string.IsNullOrEmpty (name)) 
      throw new ArgumentException ("Invalid name specified."); 

     var model = new CarsModel 
     { 
      Company = company, 
      Name = name 
     }; 

     model.Company.AddModel (model); 

     return model; 
    } 


    protected internal void AddModification (CarsModification modification) 
    { 
     this._modifications.Add (modification); 
    } 
} 


public class CarsModification 
{ 
    public virtual CarsModel Model { get; protected set; } 
    public virtual string Name { get; protected set; } 


    protected CarsModification() 
    { 
    } 


    public static CarsModification Create (CarsModel model, string name) 
    { 
     if (model == null) 
      throw new ArgumentException ("Model is not specified."); 

     if (string.IsNullOrEmpty (name)) 
      throw new ArgumentException ("Invalid name specified."); 

     var modification = new CarsModification 
     { 
      Model = model, 
      Name = name 
     }; 

     modification.Model.AddModification (modification); 

     return modification; 
    } 
} 

... 

using (var tx = session.BeginTransaction()) 
{ 
    var company = CarsCompany.Create ("Nissan"); 
    var model = CarsModel.Create (company, "Tiana"); 
    var modification = CarsModification.Create (model, "2011"); 

    session.Persist (company); 
    tx.Commit(); 
} 

यह दृष्टिकोण इसी संस्थाओं के अंदर सभी मान्यता/निर्माण तर्क हो गया और अगर यह अच्छा है या बुरा है मैं नहीं जानता, लेकिन कारखाना विधि हम परोक्ष पैरेंट ऑब्जेक्ट बच्चों संग्रह में जोड़ने के साथ वस्तु की सरल निर्माण से । लेनदेन प्रतिबद्धता और सत्र फ्लश के बाद डेटाबेस में 3 प्रविष्टियां होंगी, भले ही मैंने कभी भी अपने कोड में कुछ "एड" कमांड नहीं लिखा था। मुझे नहीं पता शायद यह सिर्फ मुझे और डीडीडी दुनिया के बाहर मेरा विशाल अनुभव है, लेकिन अब यह थोड़ा अप्राकृतिक लगता है।

तो, डीडीडी के साथ बाल संस्थाओं को जोड़ने का सबसे सही तरीका क्या है?

+0

मैं सभी कोड उदाहरणों को हटा सकता हूं और इस पूरे प्रश्न को समझने में बहुत कठिन बना सकता हूं - लेकिन मुझे नहीं लगता कि यह समुदाय की मदद करेगा। मुझे पता नहीं था कि एसओ जटिल प्रश्नों के लिए नहीं है। –

+0

पूरा प्रश्न (कोड के साथ या बिना) यहां अनुचित है। जैसा कि मैंने कहा, यह चर्चा के लिए पूछता है। मेरे द्वारा पोस्ट किए गए लिंक पढ़ें। मैं एक और प्रदान कर सकता हूं: [कोई चर्चा बोर्ड या मंच नहीं] (http://meta.stackexchange.com/a/128550/172661)। जैसा कि मैंने पहले कहा था, यह साइट ** स्पष्ट, संक्षिप्त प्रश्नों के लिए है जिसका उत्तर बिना किसी चर्चा के किया जा सकता है **। चूंकि आपका पूरा प्रश्न "सबसे सही तरीके" पर चर्चा करने और "विपक्षी [एसपी]" (जो यहां भी उचित नहीं है) पर चर्चा करने के बारे में है, यह यहां उचित नहीं है। –

+3

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

उत्तर

1

मैं स्वीकार्य जवाब यहाँ मिल गया है: https://groups.yahoo.com/neo/groups/domaindrivendesign/conversations/messages/23187

असल में, यह विधि 2 और 3 का एक संयोजन है - CarsCompany में AddModel विधि रख दिया और यह नाम पैरामीटर के साथ CarsModel की रक्षा की आंतरिक निर्माता जो मान्य है फोन कर CarsModel के निर्माता के अंदर।

+0

दिलचस्प है, लेकिन माता-पिता और बाल संग्रह में ऑब्जेक्ट्स कहां जोड़ते हैं? –

+0

अभिभावक में .ddChild विधि, जो संरक्षित आंतरिक कन्स्ट्रक्टर द्वारा बच्चे को बनाता है (बच्चे को अपने माता-पिता को अपने माता-पिता को सेट करने के लिए पैरामीटर के रूप में पास कर रहा है), इसे बाल संग्रह में जोड़ता है और इसे वापस करता है। –

+0

धन्यवाद, यह समझ में आता है। क्या आपने इस पैटर्न का उपयोग एंटिटी फ्रेमवर्क के साथ किया है? –

0

यहां एक बहुत ही ठोस और उदारतापूर्ण ईमानदार उत्तर है: आपके सभी दृष्टिकोण गलत हैं, क्योंकि आपने डीडीडी का 'पहला नियम' तोड़ दिया है, यानी, डीबी मौजूद नहीं है।

जो आप परिभाषित कर रहे हैं वह एक ORM (nhibernate) के लिए PERSISTENCE मॉडल है। डोमेन ऑब्जेक्ट्स को डिज़ाइन करने के लिए ऑर्डे में, सबसे पहले आपको उस मॉडल के लिए Bounded Context, मॉडल, एंटिटीज और वैल्यू ऑब्जेक्ट्स और Aggregate Root (जो बच्चों और बसिन नियमों के साथ आंतरिक रूप से सौदा करेगा) की पहचान करनी होगी।

निबर्ननेट या डीबी स्कीमा में कोई स्थान नहीं है, आपको केवल शुद्ध सी # कोड और डोमेन की स्पष्ट समझ की आवश्यकता है।

+4

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

+2

मुश्किल बात डोमेन को डिजाइन कर रही है। वास्तव में बीसी और एग्ग्रेगेट्स की स्थापना सबसे कठिन चीजें हैं। एक बार जब आप उन्हें जानते हैं (pseduo कोड में) यह सी # में लिखने के लिए औपचारिकता है। यह सिद्धांत नहीं है, डीडीडी का सबसे कठिन हिस्सा DOMAIN को समझ रहा है और इसका एक बहुत स्पष्ट भेद है। इसके अलावा कोई चांदी बुलेट या आवेदन करने के लिए जो भी पैटर्न नहीं है। डीडीडी अवधारणाओं और दिशानिर्देशों के बारे में है। आप निबर्ननेट में कुछ संबंधों को लागू करना चाहते हैं। वह डीडीडी नहीं है। – MikeSW

+1

आपको समस्या का सामना करने और समस्याओं को समझने के लिए आपको DOMAIN विशेषज्ञ की आवश्यकता है। न तो मैं या आसपास के अन्य लोग डोमेन विशेषज्ञ हैं। आपको समझने के लिए समस्या क्या है समझने के लिए विशेषज्ञ से बात करनी है। और ईमानदारी से बीसी को स्पष्ट रूप से जानने के बिना आप एक इकाई या कुल को डिजाइन या कार्यान्वित नहीं कर सकते हैं। – MikeSW

0

तो, डीडीडी के साथ बाल संस्थाओं को जोड़ने का सबसे सही तरीका क्या है?

तीसरा दृष्टिकोण Tight Coupling कहा जाता है। Company, Car और Modification एक दूसरे के बारे में लगभग सब कुछ पता है।

डीडीडी में दूसरा दृष्टिकोण व्यापक रूप से प्रस्तावित है। एक डोमेन ऑब्जेक्ट एक नेस्टेड डोमेन ऑब्जेक्ट बनाने और इसे अंदर पंजीकृत करने के लिए ज़िम्मेदार है।

पहला दृष्टिकोण क्लासिक ओओपी शैली है। ऑब्जेक्ट का निर्माण किसी ऑब्जेक्ट को कुछ संग्रह में जोड़ने से अलग किया जाता है। इस प्रकार कोड उपभोक्ता किसी भी व्युत्पन्न वर्ग (जैसे ट्रेलरकर) के किसी ऑब्जेक्ट के साथ एक ठोस वर्ग (उदा। कार) की ऑब्जेक्ट को प्रतिस्थापित कर सकता है।

// var model = CarsModel.Create (company, "Tiana"); 

var model = TrailerCarsModel.Create (
    company, "Tiana", SimpleTrailer.Create(company)); 

company.AddModel (model); 

दूसरे/तीसरे दृष्टिकोण में इस व्यापार तर्क परिवर्तन को अपनाने का प्रयास करें।

0

दिलचस्प। डीडीडी बनाम रिपोजिटरी/ओआरएम नेविगेशन गुण। मुझे लगता है कि उत्तर इस बात पर निर्भर करता है कि आप एक या दो से निपट रहे हैं या नहीं। क्या CarsModel कारों का हिस्सा हो सकता है कॉम्पैनी कुल, या शायद अपने स्वयं के कुल?

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

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

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