2008-08-22 25 views
16

मैं वर्तमान में यूआई से एक एएसपी.Net ऐप लिख रहा हूं। मैं एक एमवीपी आर्किटेक्चर को कार्यान्वित कर रहा हूं क्योंकि मैं विनफॉर्म से बीमार हूं और कुछ ऐसी चीज चाहता था जिसमें चिंताओं का बेहतर अलगाव हो।एमवीपी का उपयोग कर उच्च परतों में सेवा परत संदेश/त्रुटियों को आप कैसे संचारित करते हैं?

तो एमवीपी के साथ, प्रेजेंटर दृश्य द्वारा उठाए गए कार्यक्रमों को संभालता है। यहाँ कुछ कोड मैं जगह में है कि उपयोगकर्ताओं का बनाया से निपटने के लिए है:

public class CreateMemberPresenter 
{ 
    private ICreateMemberView view; 
    private IMemberTasks tasks; 

    public CreateMemberPresenter(ICreateMemberView view) 
     : this(view, new StubMemberTasks()) 
    { 
    } 

    public CreateMemberPresenter(ICreateMemberView view, IMemberTasks tasks) 
    { 
     this.view = view; 
     this.tasks = tasks; 

     HookupEventHandlersTo(view); 
    } 

    private void HookupEventHandlersTo(ICreateMemberView view) 
    { 
     view.CreateMember += delegate { CreateMember(); }; 
    } 

    private void CreateMember() 
    { 
     if (!view.IsValid) 
      return; 

     try 
     { 
      int newUserId; 
      tasks.CreateMember(view.NewMember, out newUserId); 
      view.NewUserCode = newUserId; 
      view.Notify(new NotificationDTO() { Type = NotificationType.Success }); 
     } 
     catch(Exception e) 
     { 
      this.LogA().Message(string.Format("Error Creating User: {0}", e.Message)); 
      view.Notify(new NotificationDTO() { Type = NotificationType.Failure, Message = "There was an error creating a new member" }); 
     } 
    } 
} 

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

मान लीजिए कि निम्नलिखित सेवा लेयर संदेशों दिखा सकते हैं करते हैं:

  • ई-मेल खाता पहले से मौजूद (विफलता)
  • चर्चा करते हुए उपयोगकर्ता द्वारा दर्ज (विफलता) मौजूद नहीं है
  • पासवर्ड लंबाई डेटासंग्रह से अधिक की अनुमति दी लंबाई (विफलता)
  • सदस्य सफलतापूर्वक बनाया गया (सफलता)

के भी कहना है कि मीटर चलो अयस्क नियम सेवा परत में होंगे जो यूआई अनुमान नहीं लगा सकता है।

वर्तमान में यदि सेवा योजनाबद्ध नहीं है तो सेवा स्तर में अपवाद फेंक रहा है। क्या यह एक पर्याप्त रणनीति है? क्या यह कोड आपके लिए गंध करता है? अगर मैंने इस तरह की एक सेवा परत लिखी है तो क्या आप प्रेजेंटर्स लिखने से नाराज होंगे जो इस तरह से इसका इस्तेमाल करते हैं? रिटर्न कोड बहुत पुराने स्कूल लगते हैं और एक बूल पर्याप्त जानकारीपूर्ण नहीं है।


ओपी द्वारा संपादित नहीं: अनुवर्ती टिप्पणियों में विलय कि ओपी


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

tgmdbm, मुझे लैम्ब्डा अभिव्यक्ति का चालाक उपयोग पसंद है!


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

हालांकि, अगर मैं उसी संदेश में त्रुटि संदेश वापस करना चाहता हूं जहां उपयोगकर्ता ने डेटा को सबमिट करने वाले डेटा को सबमिट किया है, तो मुझे प्रस्तुतकर्ता में अपवाद को पकड़ना होगा?

यहाँ CreateUserView जब प्रस्तुतकर्ता ServiceLayerException संभाला है की तरह दिखता है:

Create a user

त्रुटि के इस प्रकार के लिए, यह एक ही दृश्य को उसकी रिपोर्ट करना अच्छा है।

वैसे भी, मुझे लगता है कि हम अब मेरे मूल प्रश्न के दायरे से आगे जा रहे हैं। मैं आपके द्वारा पोस्ट की गई चीज़ों के साथ खेलूँगा और यदि मुझे और जानकारी चाहिए तो मैं एक नया प्रश्न पोस्ट करूंगा।

उत्तर

15

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

अपवाद को पकड़ने मत

प्रस्तोता में

हालांकि, don't catch Exception, मैं अपनी आकर्षक पता है क्योंकि यह कोड कम रहता है, लेकिन आप सिस्टम स्तर अपवादों को पकड़ने से बचने के लिए विशिष्ट अपवाद को पकड़ने के लिए की जरूरत है।

योजना एक सरल अपवाद पदानुक्रम

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

आपका प्रस्तोता तो

try { 
    // call service etc. 
    // handle success to view 
} 
catch (AccountAlreadyExistsException) { 
    // set the message and some other unique data in the view 
} 
catch (ServiceLayerException) { 
    // set the message in the view 
} 
// system exceptions, and unrecoverable exceptions are allowed to bubble 
// up the call stack so a general error can be shown to the user, rather 
// than showing the form again. 

कर अपनी खुद की अपवाद कक्षाओं में भाग के उपयोग से आपका प्रस्तोता में multipile अपवाद को पकड़ने के लिए की आवश्यकता नहीं है इसका मतलब का विकल्प है - आप कर सकते हैं अगर वहाँ की जरूरत है - और आप आकस्मिक रूप से आकर्षक अपवादों को समाप्त नहीं करते हैं जिन्हें आप संभाल नहीं सकते हैं। यदि आपका प्रस्तुतकर्ता कॉल स्टैक के शीर्ष पर पहले से ही है, तो सिस्टम त्रुटियों को एक अलग दृश्य के साथ संभालने के लिए एक कैच (अपवाद) ब्लॉक जोड़ें।

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

+1

क्या अच्छा जवाब है :) – Mik378

3

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

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

public static class Try { 
    public static List<string> This(Action action) { 
     var errors = new List<string>(); 
     try { 
     action(); 
     } 
     catch (SpecificException e) { 
     errors.Add("Something went 'orribly wrong"); 
     } 
     catch (...) 
     // ... 
    return errors; 
    } 
} 

की तरह एक सहायक लेना पसंद सिर्फ निम्नलिखित

var errors = Try.This(() => { 
    // call your service here 
    tasks.CreateMember(...); 
}); 
त्रुटियों में

तब रिक्त है, तो आप बिल्कुल तैयार हैं।

आप इसे आगे ले जा सकते हैं और इसे custome अपवाद हैंडलर के साथ बढ़ा सकते हैं जो असामान्य अपवादों को संभालते हैं।

1

अनुवर्ती प्रश्न के जवाब में:

कठिन होता जा रहा है अपवाद बनाने के लिए, आप थोड़े इसकी आदत हो। एक अच्छा कोड जनरेटर या टेम्पलेट का उपयोग लगभग 5 या 10 सेकंड के भीतर न्यूनतम हाथ संपादन के साथ अपवाद वर्ग बना सकता है।

हालांकि, कई वास्तविक दुनिया अनुप्रयोगों में, त्रुटि प्रबंधन 70% काम हो सकता है, इसलिए यह वास्तव में गेम का हिस्सा है।

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

यह आपके प्रस्तुतकर्ताओं/नियंत्रकों से पूरी तरह से अपवाद हैंडलिंग लेता है।

<bean id="exceptionResolver" 
     class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> 

    <property name="exceptionMappings"> 
    <props> 
     <prop key="UserNotFoundException"> 
     rescues/UserNotFound 
     </prop> 
     <prop key="HibernateJdbcException"> 
     rescues/databaseProblem 
     </prop> 
     <prop key="java.net.ConnectException"> 
     rescues/networkTimeout 
     </prop> 
     <prop key="ValidationException"> 
     rescues/validationError 
     </prop> 
     <prop key="EnvironmentNotConfiguredException"> 
     rescues/environmentNotConfigured 
     </prop> 
     <prop key="MessageRejectedPleaseRetryException"> 
     rescues/messageRejected 
     </prop> 
    </props> 
    </property> 
    <property name="defaultErrorView" value="rescues/general" /> 
</bean>