2009-02-27 10 views
8

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

public decimal CaculateBatchTotal(VendorApplicationBatch batch) 
{ 
    IList<VendorApplication> applications = AppRepo.GetByBatchId(batch.Id); 

    if (applications == null || applications.Count == 0) 
      throw new ArgumentException("There were no applications for this batch, that shouldn't be possible"); 
    decimal total = 0m; 
    foreach (VendorApplication app in applications) 
      total += app.Amount; 
    return total; 
} 

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

मेरे सवालों का इस प्रकार हैं:

  1. कहाँ आप इस कोड डाल होगा?
  2. क्या आप इस फ़ंक्शन को तोड़ देंगे?
  3. सख्त डोमेन-संचालित डिज़ाइन का अनुसरण करने वाले किसी व्यक्ति को कहां रखा जाएगा?
  4. क्यों?

आपके समय के लिए धन्यवाद।

संपादित करें नोट: इस पर एक ओआरएम का उपयोग नहीं कर सकता, इसलिए मैं आलसी लोडिंग समाधान का उपयोग नहीं कर सकता।

नोट 2 संपादित करें: मैं पैरामीटर में लेने के लिए कन्स्ट्रक्टर को बदल नहीं सकता, क्योंकि डेटा परत प्रतिबिंब (मेरा विचार नहीं) का उपयोग कर डोमेन ऑब्जेक्ट को तत्काल कैसे करता है।

नोट 3 संपादित करें: मुझे विश्वास नहीं है कि बैच ऑब्जेक्ट केवल एप्लिकेशन की किसी भी सूची को कुल करने में सक्षम होना चाहिए, ऐसा लगता है कि यह केवल उस विशेष बैच में मौजूद कुल एप्लिकेशन को सक्षम करने में सक्षम होना चाहिए। अन्यथा, यह सेवा कक्षा में समारोह छोड़ने के लिए मुझे और अधिक समझ में आता है।

+0

पास्कल-आधारित स्थानीय चर। छी। – yfeldblum

+0

@ जस्टिस, मुझे तुम्हारा दर्द महसूस होता है – mbillard

उत्तर

5

आपको डोमेन ऑब्जेक्ट से रिपॉजिटरीज़ तक पहुंच भी नहीं लेनी चाहिए।

आप क्या कर सकते हैं या तो सेवा को डोमेन ऑब्जेक्ट को उपयुक्त जानकारी दें या डोमेन ऑब्जेक्ट में एक प्रतिनिधि है जो किसी सेवा या कन्स्ट्रक्टर द्वारा निर्धारित किया गया है।

public DomainObject(delegate getApplicationsByBatchID) 
{ 
    ... 
} 
+0

अच्छा विचार, मुझे यह पसंद है। –

+0

सहमत है, इसलिए इस उदाहरण के लिए मैं उस सेवा को करूँगा जिसके लिए सेवा वर्ग में रिपॉजिटरी कॉल की आवश्यकता होती है, फिर गणना की आवश्यकता होने पर एक संग्रह या एकल ऑब्जेक्ट को इकाई में पास करें –

+0

हां, डोमेन ऑब्जेक्ट इसके प्रतिनिधि का उपयोग किसी भी डेटा को प्राप्त करने के लिए करेगा इसकी जरूरत है, प्रतिनिधि जो भी डोमेन ऑब्जेक्ट बनाता है द्वारा सेट किया जाएगा। प्रतिनिधि सीधे एक सेवा विधि या एक भंडार विधि हो सकता है। – mbillard

2

क्यों एक विक्रेता <VendorApplication> में एक विक्रेता अनुप्रयोग बैच के बजाय पैरामीटर के रूप में पास नहीं है? संभवतः इसके लिए कॉलिंग कोड ऐसी सेवा से आएगा जो AppRepo तक पहुंच होगी। इस तरह आपकी रिपॉजिटरी एक्सेस ऊपर होगी जहां यह संबंधित है, जबकि आपका डोमेन फ़ंक्शन उस डेटा से कहां से आया है, इस पर ध्यान से अनजान रह सकता है।

+0

अगर मैं उस कोड को डालता हूं जो भंडार में बैच के बराबर है, लेकिन गेटबाइबैड नहीं है, तो कोई गारंटी नहीं होगी कि पास किए गए एप्लिकेशन उस बैच से होंगे। मुझे लगता है कि बैच केवल उन अनुप्रयोगों को पूरा करने में सक्षम होना चाहिए जिनमें यह शामिल है। –

+0

भंडार में बैच का योग करता है -> बैच डोमेन ऑब्जेक्ट –

+0

में बैच का योग करता है मुझे यकीन नहीं है कि मैं समझता हूं। मैं जो सुझाव दे रहा हूं वह है कि आप अपने कोड को जिस तरह से रखते हैं, उसे छोड़कर, एक विक्रेता में गुजरने के बजाय एप्लिकेशन की सूची में आप पास करते हैं। GetByBatchID अभी भी भंडार में है, कोड जो अभी भी डोमेन में है। –

5

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

संपादित करें: उदाहरण

मैं सरल सत्यापन के लिए उद्यम लाइब्रेरी का उपयोग, इसलिए इकाई कक्षा में मैं बहुत की तरह एक विशेषता सेट हो जाएगा:

[StringLengthValidator(1, 100)] 
public string Username { 
    get { return mUsername; } 
    set { mUsername = value; } 
} 

इकाई एक आधार वर्ग है जो निम्न "अगर है" विधि यह सुनिश्चित करेंगे कि प्रत्येक वस्तु को पूरा करती है से विरासत सत्यापन मानदंड

 public bool IsValid() 
    { 
     mResults = new ValidationResults(); 
     Validate(mResults); 

     return mResults.IsValid(); 
    } 

    [SelfValidation()] 
    public virtual void Validate(ValidationResults results) 
    { 
     if (!object.ReferenceEquals(this.GetType(), typeof(BusinessBase<T>))) { 
      Validator validator = ValidationFactory.CreateValidator(this.GetType()); 
      results.AddAllResults(validator.Validate(this)); 
     } 
     //before we return the bool value, if we have any validation results map them into the 
     //broken rules property so the parent class can display them to the end user 
     if (!results.IsValid()) { 
      mBrokenRules = new List<BrokenRule>(); 
      foreach (Microsoft.Practices.EnterpriseLibrary.Validation.ValidationResult result in results) { 
       mRule = new BrokenRule(); 
       mRule.Message = result.Message; 
       mRule.PropertyName = result.Key.ToString(); 
       mBrokenRules.Add(mRule); 
      } 
     } 
    } 

अगला हम विधि बचाने सेवा कक्षा में इस "अगर है" विधि निष्पादित करने के लिए, तो तरह की जरूरत है:

public void SaveUser(User UserObject) 
{ 
    if (UserObject.IsValid()) { 
     mRepository.SaveUser(UserObject); 
    } 
} 

एक अधिक जटिल उदाहरण एक बैंक खाता हो सकता है। जमा तर्क खाता ऑब्जेक्ट के अंदर लाइव होगा, लेकिन सेवा कक्षा इस विधि को कॉल करेगी।

1

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

उदाहरण (हवा कोड) के लिए:

public class VendorApplicationBatch { 

    private IList<VendorApplication> Applications {get; set;}; 

    public decimal CaculateBatchTotal() 
    { 
     if (Applications == null || Applications.Count == 0) 
      throw new ArgumentException("There were no applications for this batch, that shouldn't be possible"); 

     decimal Total = 0m; 
     foreach (VendorApplication App in Applications) 
      Total += App.Amount; 
     return Total; 
    } 
} 

यह आसानी से NHibernate की तरह एक ORM साथ किया जाता है और मुझे लगता है कि यह सबसे अच्छा समाधान होगा।

+0

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

+0

फिर जवाब है कि सेवा विक्रेता विक्रेता सूची प्राप्त करे और बैच ऑब्जेक्ट को तर्क करना चाहिए। पूर्व: विक्रेता आवेदन बैच। कैक्यूलेटबैचटॉटल (IList <विक्रेता आवेदन> अनुप्रयोग) – gcores

+0

मुझे नहीं लगता कि बैच को उन सभी अनुप्रयोगों के लिए अनुमति देना सही है जो किसी अन्य बैच से संबंधित हो सकते हैं, गारेनटे के लिए कुछ तरीका होना चाहिए कि बैच केवल अपने विक्रेता को ही पूरा कर सकता है अनुप्रयोगों। इस प्रकार मैं अच्छी भरोसा नहीं कर सकता, इस समारोह को बैच में डाल दें। –

0

मुझे ऐसा लगता है कि आपके CalculateTotal VendorApplication के के संग्रह के लिए एक सेवा है, और VendorApplication के संग्रह लौटने एक बैच के लिए बैच वर्ग के एक संपत्ति के रूप में स्वाभाविक रूप से फिट बैठता है कि। तो कुछ अन्य सेवा/नियंत्रक/जो कुछ भी बैच से विक्रेता अनुप्रयोग के उचित संग्रह को पुनर्प्राप्त करेंगे और उन्हें विक्रेता अनुप्रयोग टोटलकलक्यूलेटर सेवा (या कुछ समान) में पास कर देगा। लेकिन इससे कुछ डीडीडी कुल रूट सेवा नियम या ऐसी कुछ चीज तोड़ सकती है जो मैं अज्ञात हूं (डीडीडी नौसिखिया)।

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

  • कोई संबंधित समस्या नहीं^_^