2012-02-27 9 views
9

मैं एसओए के लिए नौसिखिया हूं हालांकि मुझे ओओएडी में कुछ अनुभव है।"डिज़ाइन में सार बेस क्लास का उपयोग न करें; लेकिन मॉडलिंग/विश्लेषण में "

एसओए डिज़ाइन के लिए दिशानिर्देशों में से एक है "केवल मॉडलिंग के लिए सार कक्षाओं का उपयोग करें। उन्हें डिजाइन से छोड़ दें "। मॉडलिंग (विश्लेषण चरण) में अमूर्तता का उपयोग सहायक हो सकता है।

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

नोट: यदि आप डब्ल्यूसीएफ का उपयोग कर कोड प्रदर्शन प्रदान कर सकते हैं तो यह बहुत अच्छा होगा।

+0

यदि यह होमवर्क है, तो कृपया इसे इस तरह टैग करें। –

+0

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

उत्तर

8

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

इस स्थिति में आपको उपयोगकर्ता की एक सूची की जरूरत है

तो खातों अपने इंटरफेस की तरह

[ServiceContract] 
interface ISomeService 
{ 
    [OperationContract] 
    Collection<AccountSummary> ListAccountsForUser(
     User user /*This information could be out of band in a claim*/); 
} 

[DataContract] 
class AccountSummary 
{ 
    [DataMember] 
    public string AccountNumber {get;set;} 
    [DataMember] 
    public string AccountType {get;set;} 
    //Other account summary information 
} 

कुछ देखने अगर आप विरासत मार्ग नीचे जाना का फैसला करते हैं, तो आप KnownType attribute उपयोग कर सकते हैं, लेकिन उस बारे में पता होना इससे तार में भेजे जा रहे संदेश में कुछ प्रकार की जानकारी शामिल होगी जो कुछ मामलों में आपकी इंटरऑपरेबिलिटी को सीमित कर सकती है।

अद्यतन:

मैं थोड़ा पहले जब मैंने जवाब समय के लिए सीमित था, इसलिए मैं कोशिश करते हैं और यही कारण है कि मैं इस शैली पसंद करते हैं पर विस्तृत होगा।

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

खुला संचालन के आधार पर डीटीओ का उपयोग करना और डोमेन मॉडल पर नहीं, सेवा encapsulation रखने में मदद करता है और डोमेन मॉडल में युग्मन को कम करता है। मेरे डोमेन मॉडल को उजागर न करके, मुझे क्रमिकरण के लिए क्षेत्र दृश्यता या विरासत पर कोई समझौता करने की आवश्यकता नहीं है।

उदाहरण के लिए

अगर मैं एक से दूसरे खाते से एक स्थानांतरण विधि को उजागर किया गया था सेवा इंटरफ़ेस कुछ इस तरह दिखेगा: यह conusmer को बहुत स्पष्ट करने के लिए क्या आवश्यक डेटा अब

[ServiceContract] 
interface ISomeService 
{ 
    [OperationContract] 
    TransferResult Transfer(TransferRequest request); 
} 

[DataContract] 
class TransferRequest 
{ 
    [DataMember] 
    public string FromAccountNumber {get;set;} 
    [DataMember] 
    public string ToAccountNumber {get;set;} 
    [DataMember] 
    public Money Amount {get;set;} 
} 

class SomeService : ISomeService 
{ 
    TransferResult Transfer(TransferRequest request) 
    { 
     //Check parameters...omitted for clarity 
     var from = repository.Load<Account>(request.FromAccountNumber); 
     //Assert that the caller is authorised to request transfer on this account 
     var to = repository.Load<Account>(request.ToAccountNumber); 
     from.Transfer(to, request.Amount); 
     //Build an appropriate response (or fault) 
    } 
} 

इस इंटरफ़ेस से इस ऑपरेशन को कॉल करें। अगर मैं

[ServiceContract] 
interface ISomeService 
{ 
    [OperationContract] 
    TransferResult Transfer(AccountDto from, AccountDto to, MoneyDto dto); 
} 

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

इससे भी बदतर, सेवा कार्यान्वयनकर्ता के रूप में, क्या होता है यदि उन्होंने मुझे वर्तमान शेष राशि प्रदान की हो? क्या मुझे विश्वास करना चाहिए?

सामान्य नियम यहां पूछना है कि डेटा, ग्राहक या सेवा का मालिक कौन है? यदि ग्राहक इसका मालिक है, तो यह इसे सेवा में पास कर सकता है और कुछ बुनियादी जांच करने के बाद, सेवा इसका उपयोग कर सकती है। अगर सेवा का मालिक है, तो ग्राहक को केवल उस चीज़ को पुनः प्राप्त करने के लिए पर्याप्त जानकारी पास करनी चाहिए जो उसे चाहिए। यह सेवा को उस डेटा की स्थिरता बनाए रखने की अनुमति देता है जो उसके पास है।

इस उदाहरण में, सेवा खाते की जानकारी का मालिक है और इसका पता लगाने की कुंजी एक खाता संख्या है। हालांकि सेवा राशि (सकारात्मक, समर्थित मुद्रा इत्यादि) को मान्य कर सकती है, यह ग्राहक के स्वामित्व में है और इसलिए हम उम्मीद करते हैं कि डीटीओ के सभी क्षेत्रों को जनसंख्या में रखा जाए।

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

+1

मैं आपके आंतरिक डोमेन मॉडल की बजाय डीटीओ (डेटा ट्रांसफर ऑब्जेक्ट्स) को उजागर करने की अवधारणा से सहमत हूं। इसका मतलब है कि डीटीओ उस सेवा से संबंधित प्रतिक्रिया से संबंधित हो सकता है जिसे आप सेवा के माध्यम से भेज रहे हैं और डोमेन ऑब्जेक्ट व्यवसाय इकाई का प्रतिनिधित्व करने से संबंधित है। – Fenton

+0

@ सोहेनी धन्यवाद। मान लीजिए कि मेरे पास ओओएडी आधारित डिज़ाइन है, क्या हमें सेवा में उपभोग करने से पहले एक अलग परत का उपयोग करके इसे डीटीओ (जैसा ऊपर बताया गया है) में परिवर्तित करने की आवश्यकता है? क्या यह एक अच्छा अभ्यास है? क्या हमारे पास इस दृष्टिकोण के प्रोस और कंस समझाते हुए कोई अच्छा लेख है? – Lijo

+0

@jageall। स्पष्ट स्पष्टीकरण के लिए धन्यवाद। तीन प्रश्न - 1) क्या ऑटोमैपर "ऑपरेशन विशिष्ट डीटीओ" या "डोमेन से व्यवहार के डीटीओ" का उत्पादन करता है? 2) "ऑपरेशन विशिष्ट डीटीओ" दृष्टिकोण के लिए आप कौन से टूल्स का उपयोग करते हैं? 3) क्या हमारे पास कोई आलेख/ट्यूटोरियल है जो जेनेरिक रिपोजिटरी के उपयोग को बताता है। लोड ? – Lijo

1

मुझे लगता है कि यहाँ सबसे अच्छा अभ्यास अपने डेटा-ठेके में भाग का उपयोग नहीं करने के लिए है:

[DataContract] 
class SavingsAccount 
{ 
    public string AccountNr { ... } 
    .... 
} 

[DataContract] 
class FixedAccount 
{ 
    public string AccountNr { ... } 
    .... 
} 

कौन-सी सबसे परिदृश्यों के लिए wel काम करता है लेकिन मिश्रित खातों की सूची प्राप्त करने के लिए नहीं।
अगर वह वास्तव में आवश्यक है, पर विचार करें:

[DataContract] 
class AccountDTO 
{ 
    public string AccountType { ... } 
    public string AccountNr { ... } 
    .... 
} 

जो अनिवार्य रूप से @ jageall का जवाब है।

+0

धन्यवाद। क्या आपको लगता है कि एक सेवा जो एक मिश्रित परिणाम देता है, इतना अच्छा विचार नहीं है? यहां सामान्य मानक अभ्यास क्या है? – Lijo

1

मैं क्या दूसरों को यहाँ कहा है के साथ काफी जाना होगा, लेकिन शायद इन जोड़ने की जरूरत है:

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

इस परिदृश्य की कल्पना को पार (मामला है मूर्खतापूर्ण लेकिन निदर्शी):

public abstract class BankAccount 
{ 
    private DateTime _creationDate = DateTime.Now; 

    public DateTime CreationDate 
    { 
     get { return _creationDate; } 
     set { _creationDate = value; } 
    } 

    public virtual string CreationDateUniversal 
    { 
     get { return _creationDate.ToUniversalTime().ToString(); } 
    } 
} 

public class SavingAccount : BankAccount 
{ 
    public override string CreationDateUniversal 
    { 
     get 
     { 
      return base.CreationDateUniversal + " UTC"; 
     } 
    } 
} 

और अब आप यू है sed "सेवा संदर्भ जोड़ें" या बचत क्लाइंट तक पहुंचने के लिए अपने ग्राहक ( असेंबली का पुन: उपयोग नहीं) पर "वेब संदर्भ जोड़ें"

SavingAccount account = serviceProxy.GetSavingAccountById(id); 
account.CreationDate = DateTime.Now; 
var creationDateUniversal = account.CreationDateUniversal; // out of sync!! 

क्या होने जा रहा है CreationDate में परिवर्तन CreationDateUniversal को प्रतिदान नहीं किया जाएगा के बाद से कोई कार्यान्वयन सर्वर पर तार, केवल CreationDateUniversalका मूल्य को पार कर क्रमबद्धता के समय में है।

+0

धन्यवाद। क्या आप उदाहरण को और अधिक विस्तारित कर सकते हैं? "CreationDate में परिवर्तनों का सहारा नहीं लिया जाएगा" का क्या मतलब है। क्या इसका मतलब है कि मैंने बेस क्लास में तर्क बदल दिया है? – Lijo

+1

@ लिजो का अर्थ है कि जब ** सर्वर ** पर मैं 'क्रिएशनडेट' बदलता हूं, तो 'CreationDateUniversal' का मान भी बदलता है, क्योंकि यह मान की गणना करने के लिए संरक्षित फ़ील्ड का उपयोग करता है। लेकिन ** क्लाइंट ** पर, ये मान सरल ऑटो प्रॉपर्टी के रूप में आ गए हैं, इसलिए यदि आप 'क्रिएशनडेट' बदलते हैं तो 'क्रिएशनडेट यूनिवर्सल' को बदला नहीं जाएगा। – Aliostad