यदि मॉडल डेटा को मान्य कर रहा है, तो क्या उसे खराब इनपुट पर अपवाद नहीं फेंकना चाहिए?


9

इस SO प्रश्न को पढ़कर ऐसा लगता है कि उपयोगकर्ता इनपुट को मान्य करने के लिए अपवादों को फेंक दिया गया है।

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

क्या मेरा आधार यह है कि व्यापार परत पर सत्यापन गलत होना चाहिए?

मैं क्या करूं

तो मेरा कोड आमतौर पर इस तरह समाप्त होता है:

<?php
class Person
{
  private $name;
  private $age;

  public function setName($n) {
    $n = trim($n);
    if (mb_strlen($n) == 0) {
      throw new ValidationException("Name cannot be empty");
    }
    $this->name = $n;
  }

  public function setAge($a) {
    if (!is_int($a)) {
      if (!ctype_digit(trim($a))) {
        throw new ValidationException("Age $a is not valid");
      }
      $a = (int)$a;
    }
    if ($a < 0 || $a > 150) {
      throw new ValidationException("Age $a is out of bounds");
    }
    $this->age = $a;
  }

  // other getters, setters and methods
}

नियंत्रक में, मैं बस मॉडल को इनपुट डेटा पास करता हूं, और उपयोगकर्ता को त्रुटि दिखाने के लिए अपवादों को पकड़ता हूं:

<?php
$person = new Person();
$errors = array();

// global try for all exceptions other than ValidationException
try {

  // validation and process (if everything ok)
  try {
    $person->setAge($_POST['age']);
  } catch (ValidationException $e) {
    $errors['age'] = $e->getMessage();
  }

  try {
    $person->setName($_POST['name']);
  } catch (ValidationException $e) {
    $errors['name'] = $e->getMessage();
  }

  ...
} catch (Exception $e) {
  // log the error, send 500 internal server error to the client
  // and finish the request
}

if (count($errors) == 0) {
  // process
} else {
  showErrorsToUser($errors);
}

क्या यह एक बुरी पद्धति है?

वैकल्पिक विधि

क्या मुझे isValidAge($a)उस रिटर्न के सही / गलत होने के तरीके बनाने चाहिए और फिर उन्हें कंट्रोलर से कॉल करना चाहिए?

<?php
class Person
{
  private $name;
  private $age;

  public function setName($n) {
    $n = trim($n);
    if ($this->isValidName($n)) {
      $this->name = $n;
    } else {
      throw new Exception("Invalid name");
    }
  }

  public function setAge($a) {
    if ($this->isValidAge($a)) {
      $this->age = $a;
    } else {
      throw new Exception("Invalid age");
    }
  }

  public function isValidName($n) {
    $n = trim($n);
    if (mb_strlen($n) == 0) {
      return false;
    }
    return true;
  }

  public function isValidAge($a) {
    if (!is_int($a)) {
      if (!ctype_digit(trim($a))) {
        return false;
      }
      $a = (int)$a;
    }
    if ($a < 0 || $a > 150) {
      return false;
    }
    return true;
  }

  // other getters, setters and methods
}

और नियंत्रक मूल रूप से समान होगा, बस कोशिश / पकड़ने के बजाय अब हैं यदि / नहीं:

<?php
$person = new Person();
$errors = array();
if ($person->isValidAge($age)) {
  $person->setAge($age);
} catch (Exception $e) {
  $errors['age'] = "Invalid age";
}

if ($person->isValidName($name)) {
  $person->setName($name);
} catch (Exception $e) {
  $errors['name'] = "Invalid name";
}

...

if (count($errors) == 0) {
  // process
} else {
  showErrorsToUser($errors);
}

तो मुझे क्या करना चाहिए?

मैं अपनी मूल विधि से बहुत खुश हूं, और मेरे सहकर्मियों को जिन्हें मैंने सामान्य रूप से दिखाया है, उन्हें पसंद आया है। इसके बावजूद, क्या मुझे वैकल्पिक विधि में बदलना चाहिए? या मैं यह बहुत गलत कर रहा हूं और मुझे दूसरा रास्ता तलाशना चाहिए?


मैंने "मूल" कोड को थोड़ा ValidationExceptionऔर अन्य अपवादों को संशोधित करने के लिए संशोधित किया है
कार्लोस कैंपड्रोस

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

@BartvanIngenSchenau की अच्छी पकड़। मेरे आवेदन हमेशा एकल-भाषा रहे हैं, लेकिन स्थानीयकरण की समस्याओं के बारे में सोचना अच्छा है जो किसी भी कार्यान्वयन में उत्पन्न हो सकते हैं।
कार्लोस कैंपडरो

सत्यापन के लिए अपवाद प्रक्रिया में केवल प्रकारों को इंजेक्ट करने का एक फैंसी तरीका है। आप एक ऑब्जेक्ट लौटाकर एक ही परिणाम प्राप्त कर सकते हैं, जैसे सत्यापन इंटरफ़ेस को लागू करता है IValidateResults
रिएक्टगुलर

जवाबों:


7

अतीत में मैंने जो दृष्टिकोण का उपयोग किया है वह सभी सत्यापन तर्क समर्पित मान्यकरण वर्गों को रखना है।

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

इस दृष्टिकोण के बाद आप मान्यकरण त्रुटियों का इलाज अलग-अलग तरीके से कर सकते हैं जो इस बात पर निर्भर करता है:

  • यदि डेटा इंटीग्रिटी वैलिडेशन मॉडल में विफल रहता है, तो एक अपवाद फेंकें।
  • यदि उपयोगकर्ता इनपुट सत्यापन प्रस्तुति परत में विफल रहता है, तो एक उपयोगी टिप प्रदर्शित करें और अपने मॉडल के मूल्य को धक्का देने में देरी करें।

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

मैं इस बात से सहमत हूं कि सत्यापन के लिए एक पूरी नई कक्षा को जोड़ना ओवरकिल है, कम से कम इस अपेक्षाकृत सरल मामले में। यह बहुत अधिक जटिलता वाली समस्या के लिए उपयोगी हो सकता है।

ठीक है, एक आवेदन के लिए जिसे आप कई लोगों / कंपनियों को बेचने की योजना बनाते हैं, यह समझ में आता है कि यह हो सकता है, क्योंकि प्रत्येक कंपनी के पास किसी व्यक्ति की आयु के लिए एक मान्य सीमा जो मान्य करने के लिए अलग नियम हो सकते हैं। इसलिए यह उपयोगी है, लेकिन मेरी जरूरतों के लिए वास्तव में ओवरकिल है। वैसे भी, आप के लिए +1 भी
कार्लोस कैंपडरो

1
मॉडल से मान्यता को अलग करना एक युग्मन और सामंजस्य के दृष्टिकोण से भी समझ में आता है। इस सरल परिदृश्य में यह ओवरकिल हो सकता है, लेकिन यह केवल एक "क्रॉस फील्ड" सत्यापन नियम लेगा, जिससे सेपरेट वालिडेटर वर्ग को और अधिक आकर्षक बनाया जा सके।
सेठ एम।

8

मैं अपनी मूल विधि से बहुत खुश हूं, और मेरे सहकर्मियों को जिन्हें मैंने सामान्य रूप से दिखाया है, उन्हें पसंद आया है। इसके बावजूद, क्या मुझे वैकल्पिक विधि में बदलना चाहिए? या मैं यह बहुत गलत कर रहा हूं और मुझे दूसरा रास्ता तलाशना चाहिए?

यदि आप और आपके सहकर्मी इससे खुश हैं, तो मुझे बदलने की कोई जरूरत नहीं है।

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


अब ऐसे कई लोग हैं जो कहते हैं कि "अपवाद केवल असाधारण चीजों के लिए उपयोग किए जाने चाहिए, और XYZ असाधारण नहीं हैं"। (उदाहरण के लिए, @ dann1111 का उत्तर ... जहां वह उपयोगकर्ता त्रुटियों को "पूरी तरह से सामान्य" के रूप में लेबल करता है।

उस पर मेरी प्रतिक्रिया यह है कि यह तय करने के लिए कोई उद्देश्य मानदंड नहीं है कि क्या कुछ ("XY Z") असाधारण है या नहीं। यह एक व्यक्तिपरक उपाय है। (तथ्य यह है कि किसी भी कार्यक्रम को उपयोगकर्ता इनपुट में त्रुटियों की जांच करने की आवश्यकता होती है, घटना की त्रुटियों को "सामान्य" नहीं बनाता है। वास्तव में, "सामान्य" एक उद्देश्य दृष्टिकोण से काफी हद तक अर्थहीन है।)

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

अपवादों के खिलाफ दूसरा तर्क यह है कि वे कोड को समझने में कठिन बना सकते हैं। लेकिन फ्लिप-साइड यह है कि जब उन्हें उचित रूप से उपयोग किया जाता है, तो वे कोड को समझने में आसान बना सकते हैं ।


संक्षेप में - अपवादों का उपयोग करने या न करने का निर्णय योग्यता का वजन करने के बाद किया जाना चाहिए ... और कुछ सरलीकृत हठधर्मिता के आधार पर नहीं।


जेनेरिक Exceptionको फेंकने / पकड़ने के बारे में अच्छी बात । मैं वास्तव में कुछ उपवर्गों को फेंक देता हूं Exception, और बसने वालों का कोड आमतौर पर ऐसा कुछ नहीं करता है जो एक और अपवाद फेंक सके।
कार्लोस कैंपडरो

मैंने "मूल" कोड को मान्यता और अपवाद और अन्य अपवादों को संभालने के लिए थोड़ा संशोधित किया है / cc @ dan1111
कार्लोस कैंपडरो

1
+1, मैं हर विधि कॉल के रिटर्न मान की जांच करने के अंधेरे युग में वापस जाने की तुलना में एक वर्णनात्मक मान्यकरण होगा। सरल कोड = संभावित रूप से कम त्रुटियां।
हिनजी

2
@ dan1111 - जब मैं एक राय के लिए अपने अधिकार का सम्मान, अपनी टिप्पणी में कुछ भी नहीं कुछ भी है अन्य राय से। सत्यापन की "सामान्यता" और सत्यापन त्रुटियों को संभालने के लिए तंत्र के बीच कोई तार्किक संबंध नहीं है। आप सब हठधर्मिता कर रहे हैं।
स्टीफन सी

@ स्टेफेनक, प्रतिबिंब पर मुझे लगता है कि मैंने अपने मामले को बहुत दृढ़ता से बताया। मैं मानता हूं कि यह एक व्यक्तिगत प्राथमिकता है।

6

मेरी राय में, एप्लिकेशन त्रुटियों और उपयोगकर्ता त्रुटियों के बीच अंतर करना उपयोगी है , और केवल पूर्व के अपवादों का उपयोग करें।

  • अपवाद का उद्देश्य उन चीजों को कवर करना है जो आपके प्रोग्राम को ठीक से निष्पादित करने से रोकते हैं

    वे अप्रत्याशित घटनाएं हैं जो आपको जारी रखने से रोकती हैं, और उनका डिज़ाइन यह दर्शाता है: वे सामान्य निष्पादन को तोड़ते हैं और एक जगह पर कूदते हैं जो त्रुटि से निपटने की अनुमति देता है।

  • अमान्य इनपुट जैसी उपयोगकर्ता त्रुटियां पूरी तरह से सामान्य हैं (आपके कार्यक्रम के दृष्टिकोण से) और आपके आवेदन द्वारा अप्रत्याशित नहीं मानी जानी चाहिए

    यदि उपयोगकर्ता गलत मान दर्ज करता है और आप एक त्रुटि संदेश प्रदर्शित करते हैं, तो क्या आपका प्रोग्राम "विफल" था या किसी भी तरह से कोई त्रुटि थी? नहीं। आपका आवेदन सफल रहा - एक निश्चित प्रकार का इनपुट दिया गया, इसने उस स्थिति में सही उत्पादन किया।

    उपयोगकर्ता त्रुटियों को संभालना, क्योंकि यह सामान्य निष्पादन का हिस्सा है, आपके सामान्य कार्यक्रम प्रवाह का हिस्सा होना चाहिए, बजाय एक अपवाद के साथ बाहर कूद कर संभाला जाना चाहिए।

बेशक यह उनके इच्छित उद्देश्य के अलावा अन्य अपवादों का उपयोग करने के लिए संभव है, लेकिन ऐसा करने से प्रतिमान भ्रमित होता है और उन त्रुटियों के होने पर गलत व्यवहार का जोखिम होता है।

आपका मूल कोड समस्याग्रस्त है:

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

वैकल्पिक कोड में भी समस्याएं हैं:

  • एक अतिरिक्त, संभवतः अनावश्यक पद्धति isValidAge()शुरू की गई है।
  • अब setAge()विधि को यह मान लेना है कि कॉलर पहले से ही जाँच isValidAge()(एक भयानक धारणा) है या फिर से उम्र को मान्य करता है। यदि यह आयु को फिर से मान्य करता है, तब setAge() भी कुछ प्रकार की त्रुटि से निपटने के लिए प्रदान करना होता है, और आप फिर से एक वर्ग में आते हैं।

सुझाया गया डिज़ाइन

  • मेक setAge()वापसी सफलता पर सच और विफलता पर झूठी।

  • के वापसी मूल्य की जाँच करें setAge()और यदि यह विफल रहा है, तो उपयोगकर्ता को सूचित करें कि उम्र अमान्य थी, अपवाद के साथ नहीं, बल्कि एक सामान्य फ़ंक्शन के साथ जो उपयोगकर्ता को एक त्रुटि प्रदर्शित करता है।


फिर मैं इसे कैसे करूं? वैकल्पिक विधि के साथ मैंने प्रस्तावित किया है या कुछ और पूरी तरह से अलग है जिसके बारे में मैंने नहीं सोचा है? इसके अलावा, क्या मेरा आधार यह है कि "व्यापार परत पर सत्यापन किया जाना चाहिए" गलत है?
कार्लोस कैंपडरो

@ CarlosCampderrós, अपडेट देखें; जैसा कि आपने टिप्पणी की थी मैं उस जानकारी को जोड़ रहा था। आपके मूल डिज़ाइन में सही जगह पर सत्यापन था, लेकिन उस सत्यापन को करने के लिए अपवादों का उपयोग करना एक गलती थी।

वैकल्पिक विधि setAgeफिर से मान्य करने के लिए मजबूर करती है, लेकिन जैसा कि तर्क मूल रूप से है "यदि यह वैध है तो सेट उम्र और अपवाद फेंक दें" यह मुझे वापस एक वर्ग में नहीं ले जाता है।
कार्लोस कैंपडरो

2
एक समस्या मुझे वैकल्पिक पद्धति और सुझाई गई डिज़ाइन दोनों से दिखती है, वे यह समझने की क्षमता खो देती हैं कि उम्र अमान्य क्यों थी। इसे सही या त्रुटि स्ट्रिंग (हाँ, php soooo गंदा है) वापस करने के लिए बनाया जा सकता है, लेकिन इससे बहुत सारी समस्याएं हो सकती हैं, क्योंकि "The entered age is out of bounds" == trueऔर लोगों को हमेशा उपयोग करना चाहिए ===, इसलिए यह दृष्टिकोण उस समस्या की तुलना में अधिक समस्याग्रस्त होगा जो इसे करने की कोशिश करता है हल
कार्लोस कैंपडरो

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

4

मेरे दृष्टिकोण से (मैं एक जावा लड़का हूं) यह पूरी तरह से मान्य है कि आपने इसे कैसे लागू किया।

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

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

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


4

मेरी हास्केल टोपी के साथ, दोनों दृष्टिकोण गलत हैं।

वैचारिक रूप से क्या होता है कि आपके पास पहले बाइट्स का एक गुच्छा है, और पार्स करने और मान्य करने के बाद, आप फिर एक व्यक्ति का निर्माण कर सकते हैं।

व्यक्ति के पास कुछ अपरिवर्तनीयताएं होती हैं, जैसे कि एक नाम और एक उम्र की पूर्वता।

एक व्यक्ति का प्रतिनिधित्व करने में सक्षम होने के नाते, जिसमें केवल एक नाम है, लेकिन कोई भी ऐसी उम्र नहीं है जिसे आप हर कीमत पर बचना चाहते हैं, क्योंकि यही वह योग्यता है। सख्त आक्रमणकारियों का मतलब है कि आपको उदाहरण के लिए बाद में एक उम्र की उपस्थिति की जांच करने की आवश्यकता नहीं है।

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

दुर्भाग्य से, जावा, PHP और अन्य OO भाषाएँ सही विकल्प को सुंदर क्रिया बनाती हैं। उचित जावा एपीआई में, बिल्डर ऑब्जेक्ट्स अक्सर उपयोग किए जाते हैं। इस तरह के एक एपीआई में, एक व्यक्ति बनाना कुछ इस तरह दिखाई देगा:

Person p = new Person.Builder().setName(name).setAge(age).build();

या अधिक क्रिया:

Person.Builder builder = new Person.Builder();
builder.setName(name);
builder.setAge(age);
Person p = builder.build();
// Person object must have name and age here

इन मामलों में, कोई फर्क नहीं पड़ता कि अपवाद कहां फेंके गए हैं या जहां सत्यापन होता है, एक व्यक्ति का उदाहरण प्राप्त करना असंभव है जो अमान्य है।


आपके द्वारा यहां किया गया सभी समस्या बिल्डर वर्ग के पास है, जिसका आपने वास्तव में उत्तर नहीं दिया है।
साइफ्रे

2
मैंने समस्या को बिल्डर.बिल्ट () फ़ंक्शन पर स्थानीय कर दिया है जिसे परमाणु रूप से निष्पादित किया गया है। वह फ़ंक्शन सभी सत्यापन चरणों की एक सूची है। इस दृष्टिकोण और तदर्थ दृष्टिकोण के बीच बहुत बड़ा अंतर है। बिल्डर वर्ग के पास सरल प्रकारों से परे कोई चालकता नहीं है, जबकि व्यक्ति वर्ग में मजबूत आक्रमणकारी होते हैं। सही कार्यक्रमों का निर्माण करना आपके डेटा में मजबूत आक्रमणकारियों को लागू करने के बारे में है।
user239558

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

तीन संभावनाएँ: बिल्ड () विशिष्ट अपवादों को फेंक सकती हैं, जैसे कि ओपी का पहला उदाहरण। एक सार्वजनिक सेट हो सकता है <स्ट्रिंग> मान्य () जो मानव पठनीय त्रुटियों का एक सेट लौटाता है। I18n- तैयार त्रुटियों के लिए एक सार्वजनिक सेट <त्रुटि> मान्य () हो। मुद्दा यह है कि यह एक व्यक्ति वस्तु में रूपांतरण के दौरान होता है।
user239558

2

आम आदमी के शब्दों में:

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

दूसरा दृष्टिकोण मानता है कि उन व्यावसायिक वर्गों को केवल उन नियंत्रकों द्वारा बुलाया जाएगा, और यह कि उन्हें कभी भी अन्य संदर्भ से नहीं बुलाया जाएगा।

व्यावसायिक वर्गों को एक अपवाद को हर बार फेंकना चाहिए एक व्यापार नियम का उल्लंघन होता है।

नियंत्रक या प्रस्तुति परत को यह तय करना होगा कि क्या यह उन्हें फेंकता है या अपवादों को होने से रोकने के लिए इसकी अपनी मान्यता है।

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.