मेरे मूल्य चेकर फ़ंक्शन को एक बूलियन और एक संदेश दोनों वापस करने की आवश्यकता है


14

मेरे पास वैल्यू चेकिंग फंक्शन है, क्रेडिट कार्ड नंबर चेकिंग फंक्शन की तरह कुछ, जो एक स्ट्रिंग में पास किया गया है, और यह जांचने की जरूरत है कि वैल्यू सही फॉर्मेट की है।

यदि यह सही प्रारूप है तो इसे सही तरीके से वापस करने की आवश्यकता है।

यदि यह सही प्रारूप नहीं है, तो इसे गलत तरीके से वापस करने की आवश्यकता है, और हमें यह भी बताएं कि मूल्य में गलत क्या है।

सवाल यह है कि इसे हासिल करने का सबसे अच्छा तरीका क्या है?

यहां कुछ उपाय दिए गए हैं:

1. अर्थ बताने के लिए पूर्णांक / एनम रिटर्न कोड का उपयोग करें:

String[] returnCodeLookup = 
[
"Value contains wrong number of characters, should contain 10 characters",
"Value should end with 1", 
"Value should be a multiple of 3"
]

private int valueChecker(String value)
{
    /*check value*/
    return returnCode;
}

rc = checkValue(valueToBeChecked);
if rc == 0
{
    /*continue as normal*/
}
else
{
    print("Invalid value format: ") + returnCodeLookup[rc];
}

मुझे यह समाधान पसंद नहीं है क्योंकि इसे चीजों के कॉलर पक्ष पर कार्यान्वयन की आवश्यकता है।

2. एक रिटर्नकोड क्लास बनाएं

Class ReturnCode()
{
    private boolean success;
    private String message;

    public boolean getSuccess()
    {
        return this.success;
    }

    public String getMessage()
    {
        return this.message; 
    }
}

private ReturnCode valueChecker(String value)
{
    /*check value*/
    return returnCode;
}

rc = checkValue(valueToBeChecked);
if rc.getSuccess()
{
    /*continue as normal*/
}
else
{
    print("Invalid value format: ") + rc.getMessage();
}

यह समाधान सुव्यवस्थित है, लेकिन ऐसा लगता है कि यह ओवरकिल / पहिया को सुदृढ़ करना है।

3. अपवाद का उपयोग करें।

private boolean valueChecker(String value)
{
    if int(value)%3 != 0 throw InvalidFormatException("Value should be a multiple of 3";
    /*etc*/
    return True;
}

try {
rc = checkValue(valueToBeChecked);
}

catch (InvalidFormatException e)
{
     print e.toString();
}

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


'[..] जाँचें कि मान सही प्रारूप का है।' क्या नाम प्रारूपकार नहीं होना चाहिए , तब?
एंडी

सही / गलत परिणाम बेमानी लगता है। क्या यह केवल सफलता का संकेत देने के लिए एक खाली या अशक्त स्ट्रिंग लौटा सकता है? यह लगभग 50 वर्षों के लिए UNIX के लिए काम किया है। :-)
user949300

जवाबों:


14

अधिक जटिल रिटर्न ऑब्जेक्ट का उपयोग करें जो दोनों चिंताओं को घेरता है। उदाहरण:

public interface IValidationResult {
  boolean isSuccess();
  String getMessage();
}

इसके कई फायदे हैं:

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

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


मुझे स्वीकार करना चाहिए कि यह समाधान मेरी तुलना में बेहतर है। मेरा थ्रेडसेफ़ नहीं है।
ट्यूलेंस कोर्डोवा

@ user61852 हालांकि यह परिणाम वस्तु के लिए एक इंटरफ़ेस का एक उच्च स्तरीय अवलोकन है, मुझे लगता है कि यहां लक्ष्य यह है कि सत्यापन कोड का अपना ऑब्जेक्ट होगा जिसमें कोई राज्य नहीं होगा। इससे यह अपरिवर्तनीय होगा, जिसके कई लाभ हैं जो हम इस साइट पर बार-बार बात करते हैं।

एक इंटरफ़ेस क्यों आवश्यक है?
dwjohnston

1
@dwjohnston एक इंटरफ़ेस आवश्यक नहीं है, लेकिन यह एक अच्छा विचार है। वंशानुक्रम एक बहुत मजबूत प्रकार का युग्मन है जिसका उपयोग केवल आवश्यक होने पर ही किया जाना चाहिए।

वैकल्पिक रूप से, आप आगे को सरल बना सकते हैं। सफलता दिलचस्प नहीं है, इसलिए एक निरंतर घोषित करें जो IValidationResult.SUCCESSएक खाली त्रुटि संदेश देता है। तब आपका तर्क ऐसा लगता हैif (result != SUCCESS) { doStuff(result.getMessage()); }
मॉर्गन

2

उपरोक्त में से कोई भी, एक ValueChecker वर्ग का उपयोग न करें

आपको लचीलापन देने के लिए पहला इंटरफ़ेस:

public interface IValueChecker {
    public boolean checkValue(String value);
    public String getLastMessage();
}

फिर जितने की जरूरत है उतने ही मूल्य-निर्धारण लागू करें:

public class MyVeryEspecificValueChecker implements IValueChecker {
    private String lastMessage="";
    @Override
    public boolean checkValue(String value) {
        boolean valid=false;
        // perform check, updates "valid" and "lastMessage"
        return valid;
    }
    @Override
    public String getLastMessage() {
        return lastMessage;
    }
}

नमूना ग्राहक कोड:

public class TestValueChecker {
    public static void main(String[] args) {
        String valueToCheck="213123-YUYAS-27163-10";
        IValueChecker vc = new MyVeryEspecificValueChecker();
        vc.checkValue(valueToCheck);
        System.out.println(vc.getLastMessage());
    }
}

इसका यह फायदा है कि आपके पास कई अलग-अलग मूल्य के चेकर हो सकते हैं।


1
मुझे यकीन नहीं है कि मैं राज्य को ध्यान में रखते हुए मूल्य चेकर को पसंद करता हूं, अंतिम मूल्य को देखने के तरीके के बिना।
पीटर के।

1

मेरा उत्तर @ स्नोमैन के दृष्टिकोण का विस्तार करता है। मूल रूप से, प्रत्येक सत्यापन, प्रत्येक व्यावसायिक नियम और प्रत्येक व्यवसाय-तर्क को कुछ प्रतिक्रियाओं में परिणाम देने में सक्षम होना चाहिए - कम से कम, वेब अनुप्रयोगों में। यह प्रतिक्रिया, बदले में, एक कॉलर को प्रदर्शित की जाती है। यह मुझे निम्नलिखित इंटरफ़ेस में लाया (यह php है, लेकिन सवाल प्रकृति में भाषा-अज्ञेय है):

interface Action
{
    /**
     * @param Request $request
     * @throws RuntimeException
     * @return Response
     */
    public function act(Request $request);
}

एक अभिव्यक्ति की तरह अभिनय करने वाले स्विच ऑपरेटर का निर्माण, कथन की तरह नहीं, आवेदन सेवा की तरह लग रहा है:

class MyApplicationService implements Action
{
    private $dataStorage;

    public function __construct(UserDataStorage $dataStorage)
    {
        $this->dataStorage = $dataStorage;
    }

    public function act(Request $request)
    {
        return
            (new _SwitchTrue(
                new _Case(
                    new EmailIsInvalid(),
                    new EmailIsInvalidResponse()
                ),
                new _Case(
                    new PasswordIsInvalid(),
                    new PasswordIsInvalidResponse()
                ),
                new _Case(
                    new EmailAlreadyRegistered($this->dataStorage),
                    new EmailAlreadyRegisteredResponse()
                ),
                new _Default(
                    new class implements Action
                    {
                        public function act(Request $request)
                        {
                            // business logic goes here

                            return new UserRegisteredResponse();
                        }
                    }
                )
            ))
                ->act($request)
            ;
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.