2014-05-19 6 views
7

मेरे पास एक जावा कोड है जिसमें एक ही विधि में एकाधिक रिटर्न स्टेटमेंट हैं। लेकिन कोड सफाई उद्देश्य के लिए, मेरे पास प्रति विधि केवल एक वापसी विवरण हो सकता है। इस पर काबू पाने के लिए क्या किया जा सकता है।किसी विधि में वापसी विवरणों की संख्या को कम करने

यहाँ मेरी कोड से एक विधि है: -

public ActionForward login(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 

     // Kill any old sessions 
     //request.getSession().invalidate(); 
     DynaValidatorForm dynaform = (DynaValidatorForm)form; 

     // validate the form 
     ActionErrors errors = form.validate(mapping, request); 
     if(!errors.isEmpty()) { 
      this.saveErrors(request, errors); 
      return mapping.getInputForward(); 
     } 

     // first check if token is set 
     if(!isTokenValid(request, true)) { 
      String errmsg="There was a problem with your login. Please close your browser then reopen it and try again. Make sure to click the Login button only ONCE."; 
      request.setAttribute("errormessage", errmsg); 
      saveToken(request); 
      return mapping.findForward(ConstantLibrary.FWD_CONTINUE); 
     } 

     // check the form for input errors 
     String errmsg = checkInput(form); 
     if (errmsg != null) { 
      request.setAttribute("errormessage", errmsg); 
      saveToken(request); 
      return mapping.findForward(ConstantLibrary.FWD_CONTINUE); 
     } 

     // no input errors detected 
     String resumekey = null; 
     // check for valid login 
     ObjectFactory objFactory = ObjectFactory.getInstance(); 
     DataAccessor dataAccessor = objFactory.getDataAccessor(); 

     request.setCharacterEncoding("UTF-8"); 
     String testcode = dynaform.getString("testcode").trim(); 
     String studentname = dynaform.getString("yourname").trim(); 


     String password = dynaform.getString("password").trim(); 

     // 4/3/07 - passwords going forward are ALL lower case 
     if (!CaslsUtils.isEmpty(password)) { 
      password = password.toLowerCase(); 
     } 

     try{ 
       resumekey = new String(studentname.getBytes("ISO-8859-1"),"UTF-8"); 

      } catch (Exception e) { 
       log_.error("Error converting item content data to UTF-8 encoding. ",e); 
      } 

     String hashWord = CaslsUtils.encryptString(password); 
     // Make sure this is short enough to fit in the db 
     if (hashWord.length() > ConstantLibrary.MAX_PASSWORD_LENGTH) { 
      hashWord = hashWord.substring(0, ConstantLibrary.MAX_PASSWORD_LENGTH); 
     } 

     Login login = dataAccessor.getLogin(testcode, hashWord, false); 

     if (login == null || !login.getUsertype().equals(Login.USERTYPE_SUBJECT)) { 
      request.setAttribute("errormessage", "Incorrect test code or password."); 
      saveToken(request); 
      return mapping.findForward(ConstantLibrary.FWD_CONTINUE); 
     } 

     // Check if the login has expired 
     if (login.getLoginexpires() != null && login.getLoginexpires().before(new Date())) { 
      request.setAttribute("errormessage", "Your login has expired."); 
      saveToken(request); 
      return mapping.findForward(ConstantLibrary.FWD_CONTINUE); 
     } 

     // Check if the password has expired 
     if (login.getPasswordexpires() != null && login.getPasswordexpires().before(new Date())) { 
      request.setAttribute("errormessage", "Your login password has expired."); 
      saveToken(request); 
      return mapping.findForward(ConstantLibrary.FWD_CONTINUE); 
     } 

     HttpSession session = request.getSession(); 
     session.setAttribute(ConstantLibrary.SESSION_LOGIN, login); 
     session.setAttribute(ConstantLibrary.SESSION_STUDENTNAME, studentname); 
     List<Testtaker> testtakers = null; 
     try { 
      //invalidate the old session if the incoming user is already logged in. 
      synchronized(this){ 
      invalidateExistingSessionOfCurrentUser(request, studentname, testcode); 
      testtakers = dataAccessor.getTesttakersByResumeKey(studentname, login);// Adding this code to call getTesttakersByResumeKey instead of getTesttakers to improve the performance of the application during student login 
      } 
     } catch (Exception e) { 
      log.error("Exception when calling getTesttakers"); 
      CaslsUtils.outputLoggingData(log_, request); 
      throw e; 
     } 
     session = request.getSession(); 
     if(testtakers!=null) 
     { 
     if(testtakers.size() == 0) { 
      // new student -> start fresh 
      log_.debug("starting a fresh test"); 

      // if this is a demo test, skip the consent pages and dump them directly to the select test page 
      if (login.getTestengine().equals(Itemmaster.TESTENGINE_DEMO)) { 
       return mapping.findForward("continue-panel"); 
      } 
     } 
      // send them to fill out the profile 

      // check for custom profiles 
      String[] surveynames = new String[4]; 
      List<Logingroup> logingroups = dataAccessor.getLoginGroupsByLogin(login.getLoginid()); 
      for(Logingroup logingroup : logingroups) { 
       Groupmaster group = logingroup.getGroupmaster(); 
       log_.debug(String.format("group: {groupid: %d, grouptype: %s, groupname: %s}", new Object[] {group.getGroupid(), group.getGrouptype(), group.getName()})); 
       Set<Groupsurvey> surveys = group.getGroupsurveys(); 
       if(surveys.size() > 0) { 
        // grab the first (and only) one 
        Groupsurvey survey = surveys.toArray(new Groupsurvey[0])[0]; 
        if(group.getGrouptype().equalsIgnoreCase(Groupmaster.GROUPTYPE_CLASS)) { 
         surveynames[0] = survey.getSurveyname(); 
        } else if (group.getGrouptype().equalsIgnoreCase(Groupmaster.GROUPTYPE_SCHOOL)){ 
         surveynames[1] = survey.getSurveyname(); 
        } else if (group.getGrouptype().equalsIgnoreCase(Groupmaster.GROUPTYPE_DISTRICT)){ 
         surveynames[2] = survey.getSurveyname(); 
        } else if (group.getGrouptype().equalsIgnoreCase(Groupmaster.GROUPTYPE_STATE)){ 
         surveynames[3] = survey.getSurveyname(); 
        } 
       } 
      } 

      // match the most grandular survey 
      for(int i=0; i < surveynames.length; ++i) { 
       if(surveynames[i] != null) { 
        saveToken(request); 
        return mapping.findForward("student-profile-"+surveynames[i]); 
       } 
      } 
      // no custom profile, send them to the default 
      saveToken(request); 
      return mapping.findForward("student-profile"); 
     } 

     // get the set of availible panels 
     Set<Panel> availiblePanels = dataAccessor.getAvailiblePanels(login, studentname); 
     if(availiblePanels.size() == 0) { 
      // no panels availible. send to all done! 
      log_.debug(String.format("No panels availible for Login:%s with resumekey:%s", login.toString(), studentname)); 
      session.setAttribute("logoutpage", true); 
      resetToken(request); 
      return mapping.findForward("continue-alldone"); 
     } 
     //Eventum #427 - Prevent test takers from retaking a finished test. 
     TestSubjectResult testSubjecResult=dataAccessor.getTestSubjectResult(login, resumekey); 
     if(testSubjecResult != null){ 
      if(testSubjecResult.getRdscore() != null && testSubjecResult.getWrscore() != null && testSubjecResult.getLsscore() != null && testSubjecResult.getOlscore() != null){ 
       if(testSubjecResult.getRdscore().getFinishtime() != null && testSubjecResult.getWrscore().getFinishtime() != null && testSubjecResult.getLsscore().getFinishtime() != null && testSubjecResult.getOlscore().getFinishtime() != null){ 
        log_.debug(String.format("Already completed all the Skill Tests.", login.toString(), studentname)); 
        session.setAttribute("logoutpage", true); 
        resetToken(request); 
        return mapping.findForward("continue-alldone"); 
       } 
      } 
     } 
     // get a list of resumeable testtakers 
     List<Testtaker> resumeableTesttakers = new ArrayList<Testtaker>(); 
     for(Testtaker testtaker : testtakers) { 
      if(testtaker.getPhase().equals(ConstantLibrary.PHASE_GOODBYE)) { 
       // testtaker is done with test. skip. 
       continue; 
      } 
      if(testtaker.getCurrentpanelid() == null) { 
       // testtaker is the profile testtaker 
       continue; 
      } 
      resumeableTesttakers.add(testtaker); 
     } 
     // sort them from least recent to latest 
     Collections.sort(resumeableTesttakers, new Comparator<Testtaker>() { 
      @Override 
      public int compare(Testtaker o1, Testtaker o2) { 
       // TODO Auto-generated method stub 
       //return 0; 
       return new CompareToBuilder() 
        .append(o1.getLasttouched(), o2.getLasttouched()) 
        .toComparison(); 
      } 
     }); 

     if(resumeableTesttakers.size() == 0 && availiblePanels.size() > 0) { 
      // nobody is resumeable but there are panels left to take 
      // send them to the panel choice 
      // TODO: This is probably a misuse of Struts. 
      log_.info("No resumeable testtakers. Sending to panel select"); 
      saveToken(request); 
      ActionForward myForward = (new ActionForward("/do/capstartpanel?capStartPanelAction=retest&lasttesttakerid=" 
        + testtakers.get(0).getTesttakerid(), true)); 
      return myForward;// mapping.findForward(ConstantLibrary.FWD_CONTINUE + "-panel"); 
     } else { 
      // grab the one most recently created and take their test 
      log_.info(String.format("Resuming with choice of %d testtakers", resumeableTesttakers.size())); 
      // we're forwarding to resume at this point, so we should do the some of the initialization 
      // that would have happened if we were still using getTesttaker() instead of getTesttakers() above. 

      session.setAttribute(ConstantLibrary.SESSION_LOGIN, login); 
      session.setAttribute(ConstantLibrary.SESSION_TESTTAKER, resumeableTesttakers.get(resumeableTesttakers.size()-1)); 
      saveToken(request); 
      return mapping.findForward(ConstantLibrary.FWD_RESUME); 
     } 

    } 
+21

वास्तव में एक विधि में एकाधिक रिटर्न के साथ कुछ भी गलत नहीं है ... कभी-कभी यह एकाधिक रिटर्न पाने के लिए और अधिक समझ में आता है, कभी-कभी यह एक ही वापसी के लिए अधिक समझ में आता है। स्थिति के लिए सही एक उठाओ। प्रति विधि एकल वापसी को मजबूर करना सबसे अच्छा विचार नहीं है। – awksp

+5

देखें [यह] (https://programmers.stackexchange.com/questions/118703/where-did-the-notion-of-one-return-only-come-from) एक स्पष्टीकरण के लिए प्रश्न जहां "केवल एक वापसी "से आया और क्यों यह वास्तव में और ज़रूरी नहीं है। – awksp

+0

खैर, दुह, निश्चित रूप से एक ही वापसी के लिए गोटो का उपयोग करें! – PlasmaHH

उत्तर

3

मैं विधि के शुरू में एक एक कार्रवाई आगे चर सेट होगा।

ActionForward actionForwardToReturn = null; 

तो इन दो पंक्तियों के साथ इन दो पंक्तियों में से प्रत्येक

return mapping.getInputForward(); 

return mapping.findForward(ConstantLibrary.FWD_CONTINUE); 

बदल देते हैं:

actionForwardToReturn = mapping.getInputForward() 

actionForwardToReturn = mapping.findForward(ConstantLibrary.FWD_CONTINUE); 

अंत में चर लौट आते हैं।

return actionForwardToReturn; 

यह भी मुश्किल :) एक तरफ ध्यान दें पर

... (वास्तव में इस सवाल का जवाब मूल) नहीं होना चाहिए:

एकाधिक वापसी बयान यह मुश्किल डिबग करने के लिए कर सकते हैं कोड।

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

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

+0

आपने अभी समझाया है कि ओपी इसे क्यों करना चाह सकता है। तो क्या? –

+0

हाँ आप सही हैं। मैं अपना उत्तर –

3

एकाधिक रिटर्न स्टेटमेंट्स को हटाने के प्रयास में एक विधि में जोड़ा गया जटिलता कई बार इसके लायक नहीं है, खासकर आपके जैसे तरीके में।
इस मामले में उनका उपयोग करने में कुछ भी गलत नहीं है।

10

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

ActionForward result = null; 
//scenario 1 
result = ... 
//scenario 2 
result = ... 
//scenario 3 
result = ... 
//finally 
return result; 

आशा इस मदद करता है में वृद्धि होगी, लेकिन, यह मेरे लिए बहुत मतलब नहीं है

3

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

उपयोग @Octopus की विधि आप पूरी तरह से एक वापसी कथन

10

के रूप में दूसरों के द्वारा कहा, एक भी वापसी कथन आवश्यक रूप से अपने कोड क्लीनर नहीं है होने के लिए किया है। हालांकि, इस मामले में छोटे टुकड़ों में विधि को विभाजित करने से शायद कोड अधिक पठनीय हो जाता है।

उदाहरण के लिए, इस भाग:

If(tokenNotSet() || formHasErrors()){ 
    return mapping.findForward(ConstantLibrary.FWD_CONTINUE); 
} 

कई स्थानों एल्गोरिथ्म की संरचना अधिक हो जाता है पर ऐसा करने से:

// first check if token is set 
    if(!isTokenValid(request, true)) { 
     String errmsg="There was a problem with your login. Please close your browser then reopen it and try again. Make sure to click the Login button only ONCE."; 
     request.setAttribute("errormessage", errmsg); 
     saveToken(request); 
     return mapping.findForward(ConstantLibrary.FWD_CONTINUE); 
    } 

    // check the form for input errors 
    String errmsg = checkInput(form); 
    if (errmsg != null) { 
     request.setAttribute("errormessage", errmsg); 
     saveToken(request); 
     return mapping.findForward(ConstantLibrary.FWD_CONTINUE); 
    } 

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

+3

बदल दूंगा, तो आप साइड इफेक्ट्स वाले कार्यों के साथ अपने कोड को प्रतिस्थापित करने का प्रस्ताव करते हैं? आपके उदाहरण में, "tokenNotSet()" फ़ंक्शन saveToken() को भी कॉल करेगा? वास्तव में बुरा अभ्यास। – pkExec

+1

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

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