2010-02-10 11 views
12

मैं निम्नलिखित डीबी मॉडल है:DDD: संस्थाओं की तरह Enum

**Person table** 
ID | Name | StateId 
------------------------------ 
1   Joe  1 
2   Peter  1 
3   John  2 

**State table** 
ID | Desc 
------------------------------ 
1   Working 
2   Vacation 

और डोमेन मॉडल हैं (सरलीकृत) किया:

public class Person 
{ 
    public int Id { get; } 
    public string Name { get; set; } 
    public State State { get; set; } 
} 

public class State 
{ 
    private int id; 
    public string Name { get; set; } 
} 

राज्य डोमेन तर्क जैसे में इस्तेमाल किया जा सकता है:

if(person.State == State.Working) 
    // some logic 

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

तो राज्य के लिए बढ़ाया जा सकता है:

public class State 
{ 
    private int id; 
    public string Name { get; set; } 

    public static State New {get {return new State([hardCodedIdHere?], [hardCodeNameHere?]);}} 
} 

लेकिन इस दृष्टिकोण राज्य के नाम डोमेन में hardcoded किया जाएगा इस्तेमाल करते हैं।

क्या आप जानते हैं मेरा क्या मतलब है? क्या ऐसी चीज के लिए एक मानक दृष्टिकोण है? मेरे दृष्टिकोण से मैं जो करने की कोशिश कर रहा हूं वह एक ऑब्जेक्ट का उपयोग कर रहा है (जो ईआरएम डिज़ाइन परिप्रेक्ष्य से जारी है) मेरे डोमेन के भीतर एक मूल्य वस्तु के रूप में। तुम क्या सोचते हो?

प्रश्न अद्यतन: शायद मेरा प्रश्न पर्याप्त स्पष्ट नहीं था।

मुझे क्या जानने की ज़रूरत है, मैं एक इकाई (जैसे राज्य उदाहरण) का उपयोग कैसे करूं जो मेरे डोमेन तर्क के भीतर डेटाबेस में संग्रहीत है। जैसी चीजों से बचने के लिए:

if(person.State.Id == State.Working.Id) 
     // some logic 

या

if(person.State.Id == WORKING_ID) 
// some logic 
+0

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

उत्तर

7

previous question of mine कुछ उपयोगी लिंक पता चला है जो मुझे संदेह है कि आपके प्रश्न के अनुरूप हैं, विशेष रूप से जिमी बोगर्ड की Enumeration Classes पर चर्चा।

+0

थोड़ी देर के लिए अपनी गणना कक्षा का उपयोग कर रहे थे ... एक अपग्रेड किए गए संस्करण पर ठोकर खाई। https://github.com/HeadspringLabs/Enumeration – CSharper

+0

और एक NuGet पैकेज के रूप में भी उपलब्ध है! - अच्छा ... http://www.nuget.org/packages/Enumeration – rohancragg

3

यह एक आम बात है एक 'अज्ञात' तत्व एक enum में 0 मान शामिल करने के लिए है। यदि आप वास्तव में चाहते हैं तो आप इसे कर सकते हैं और इसे नए राज्य के लिए उपयोग कर सकते हैं।

लेकिन जो आप वर्णन कर रहे हैं वह व्यवसाय तर्क है ... एक नई वस्तु बनाने के बाद एक राज्य स्थापित करना व्यापार तर्क परत में होना चाहिए, कक्षा के अंदर नहीं।

0

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

मैं एक सरल डिजाइन के लिए जाना होगा। राज्य व्यक्ति वर्ग से संबंधित है। मैं इसे कक्षा में शामिल करूंगा।

public class Person 
{ 
    public int Id { get; } 
    public string Name { get; set; } 
    public PersonState State { get; set; } 
} 

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

enum Days {Working, Vacation}; 

यह मेरी राय में डिजाइन को समझना एक आसान है। ईआरएम डिजाइन में मैपिंग दृढ़ता परत में IMHO से संबंधित है। वहां एनम को राज्य तालिका की कुंजी पर मैप किया जाना है। यह मूल डोमेन मॉडल को साफ रखने के लिए एक पहलू का उपयोग करके किया जा सकता है।

7

आपकी प्रस्तावित संरचना ठीक लगती है।(शब्दावली विषयांतर: के बाद से State एक आईडी है, यह नहीं एक मूल्य वस्तु, बल्कि एक इकाई है।)

Enums एक कोड गंध कर रहे हैं, ताकि मार्ग जाने के लिए प्रयास नहीं करते। State पैटर्न का उपयोग करके व्यवहार को राज्य वस्तु में स्थानांतरित करने के लिए यह अधिक ऑब्जेक्ट उन्मुख है।

इसके बजाय सभी अपने कोड पर

if (person.State == State.Working) 
    // do something... 

लिखने के लिए होने के

, यह आप

person.State.DoSomething(); 

लिखने के लिए यही कारण है कि अधिक स्वच्छ है, और आप अगर हो जरूरत नई स्टेट्स जोड़ने की अनुमति देगा की अनुमति होगी।

+0

अज्ञात डाउनवोट क्यों? –

+0

प्रश्न को राज्य पैटर्न को लागू करने के तरीके के साथ क्या करना है, यह एक प्रश्नकर्ता राज्य पैटर्न का उपयोग कर रहा है। –

+2

@ ब्रायन लेहै: मुझे राज्य में * पैटर्न * पैटर्न को कहीं भी नहीं देखा गया है ... –

2

आप एक कारखाना विधि बनाना चाहते हैं जो संग्रहीत मूल्य के आधार पर उचित राज्य वर्ग को तत्काल स्थापित करेगी।

तरह

public static State GetStateByID(StateEnum value) 
{ 
    if(value.Invalid) 
     throw new Exception(); 

switch(value) 
    case State.Working 
     return new WorkingState(); 
    case State.somethingelse 
     return new somethingelseState(); 
    case State.something 
     return new somethingState(); 
    case State.whatever 
     return new whateverState(); 

} 

enums का उपयोग करते समय हमेशा की तरह अमान्य 0 इस्तेमाल करने की कोशिश कुछ। हुड के तहत एक enum एक मान प्रकार है, और एक असाइन किए गए int हमेशा 0.

राज्य पैटर्न के संयोजन के साथ इस तरह के कारखाने का उपयोग करना आम बात है।

तो जब आप डेटाबेस से अपने संग्रहीत पूर्णांक मान को पढ़ते हैं तो आप enum को int डाल सकते हैं और उपयुक्त राज्य वस्तु प्राप्त करने के लिए कारखाने को इसके साथ कॉल कर सकते हैं।

1

मुझे व्यक्तिगत रूप से लगता है कि यह आईडी के खिलाफ कार्यक्रम की गलती है। इसके बजाय, मैं निम्नलिखित करने के लिए अपनी मेज में संशोधन होगा:

**State table** 
ID | Desc    | IsWorking | IsVacation 
----------------------------------------------------------- 
1   Working    True   False 
2   Vacation    False  True 

मैं तो जैसे पर व्यावसायिक निर्णय लेने के इन विशेषताओं का प्रयोग करेंगे:

public void MakeDecisionOnState(State state) 
    { 
     if (state.IsVacation) 
      DoSomething(); 
     if (state.IsWorking) 
      DoSomethingElse(); 
    } 

या और भी अधिक चतुर होने से, कारखाने पैटर्न का उपयोग इन विशेषताओं के आधार पर सही उदाहरण बनाने के लिए:

public abstract class State 
    { 
     public Guid Id { get; set; } 

     public string Description { get; set; } 

     public abstract void DoSomething(); 

    } 

    public class WorkingState : State 
    { 
     public override void DoSomething() 
     { 
      //Do something specific for the working state 
     } 
    } 

    public class VacationState : State 
    { 
     public override void DoSomething() 
     { 
      //Do something specific for the vacation state 
     } 
    } 

    public class StateFactory 
    { 
     public static State CreateState(IDataRecord record) 
     { 
      if (record.GetBoolean(2)) 
       return new WorkingState { Id = record.GetGuid(0), Description = record.GetString(1) }; 
      if (record.GetBoolean(3)) 
       return new VacationState { Id = record.GetGuid(0), Description = record.GetString(1) }; 

      throw new Exception("Data is screwed"); 
     } 
    } 

अब आप अगर/स्विच बयान का सफाया कर दिया गया है, और अपने कोड बस हो सकता है:

state.DoSomething(); 

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

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