降低圈复杂度的最佳方法

Best way for Cyclomatic complexity reduction

以下方法的圈复杂度为 13 我遵循一些使用三元运算符的方法来处理小的 if else,但对于长代码最好的方法是什么 什么设计模式用于 resuce if else 条件或任何其他方式来减少圈复杂度,因为 sonarQube 显示圈复杂度错误。 我是新手帮我理解一下这个过程

  @RequestMapping(value = "/submitUser", method=RequestMethod.POST)
            public String submitUser(@ModelAttribute User userBean,Locale locale, RedirectAttributes redirectAttributes, HttpSession session, Model model) {
        boolean status = false, isAdd = false;
        String imagePath = "", task = "";
        isAdd = userBean.getAdd();
        /*if(isAdd) {
                    task = "add";
                } else {          // replace this by task=isAdd?"add":"edit";
                    task = "edit"; //
                }*/
                GlobalLogger.logApplicationDebugLog("Received request to " + task + " user ", LOGGER);
        if (session != null && session.getAttribute("UserImagePath") != null) {
            imagePath = session.getAttribute("UserImagePath").toString();
                }
                int currentUserId = Integer.parseInt(session.getAttribute(SessionKeyConstants.USER_ID).toString());
                try {
                    status = iuser.submitUser(userBean, imagePath,currentUserId);
                    if(isAdd) {
                        if (status) {
                            GlobalLogger.logInfoLog("User "+userBean.getUserName()+" has been " + task + "ed successfully", LOGGER);
                            redirectAttributes.addFlashAttribute("successMsg", messageSource.getMessage("operationMsg.addUserSuccess", new String[] {userBean.getEmpEmail()}, locale));
                            return "redirect:/users.action";
                        } else {
                            GlobalLogger.logApplicationDebugLog("Error in adding user "+userBean.getUserName(), LOGGER);
                            redirectAttributes.addFlashAttribute("errorMsg", messageSource.getMessage("operationMsg.addUserFailure", new String[] {}, locale));
                            redirectAttributes.addFlashAttribute("isAdd", isAdd);
                            redirectAttributes.addFlashAttribute("userBean", userBean);
                            return "redirect:/addUser.action?isAdd=true";
                        }
                    } else {
                        if (status) {
                            GlobalLogger.logInfoLog("User "+userBean.getUserName()+" has been " + task + "ed successfully", LOGGER);
                            redirectAttributes.addFlashAttribute("successMsg", messageSource.getMessage("label.addSuccessMsg", new String[] {userBean.getFirstName()}, locale));
                            return "redirect:/users.action";
                        } else {
                            GlobalLogger.logApplicationDebugLog("Error in adding user "+userBean.getUserName(), LOGGER);
                            redirectAttributes.addFlashAttribute("errorMsg", messageSource.getMessage("label.addFailedMsg", new String[] {userBean.getFirstName()}, locale));
                            redirectAttributes.addFlashAttribute("isAdd", isAdd);
                            redirectAttributes.addFlashAttribute("userBean", userBean);
                            return "redirect:/addUser.action?isAdd=false";
                        }
                    }
                } catch (UserException e) {
                    GlobalLogger.logApplicationDebugLog("User Name or Employee Id exists for user "+userBean.getUserName(), LOGGER);
                    redirectAttributes.addFlashAttribute("userBean", userBean);
                    redirectAttributes.addFlashAttribute("errorMsg", messageSource.getMessage(e.getErrorcode(), new String[] {}, locale));
                    return "redirect:/addUser.action?isAdd=true";
                }
            }

解决方法过长问题的最直接方法是将它们分解成多个部分。将方法的一部分提取到从原始方法调用的单独方法中。通常它可以用 IDE 自动完成,例如Eclipse(菜单Refactor/Extract方法)。

在您的方法中,isAdd==true 和 false 的代码几乎相同。您可以将此代码提取到单独的方法中,例如。 String redirectUser(boolean isAdd, boolean status, <other attribs>) {...}。这样你的方法就简单多了。

第一个变化很简单——提取方法(这个可以自动完成):

    @RequestMapping(value = "/submitUser", method=RequestMethod.POST)
public String submitUser(@ModelAttribute User userBean,Locale locale, RedirectAttributes redirectAttributes, HttpSession session, Model model) {
    boolean status = false, isAdd = false;
    String imagePath = "", task = "";
    isAdd = userBean.getAdd();
    GlobalLogger.logApplicationDebugLog("Received request to " + task + " user ", LOGGER);
    if (session != null && session.getAttribute("UserImagePath") != null) {
        imagePath = session.getAttribute("UserImagePath").toString();
    }
    int currentUserId = Integer.parseInt(session.getAttribute(SessionKeyConstants.USER_ID).toString());
    try {
        status = iuser.submitUser(userBean, imagePath,currentUserId);
        return redirectUser(userBean, locale, redirectAttributes, status,
                isAdd, task);
    } catch (UserException e) {
        GlobalLogger.logApplicationDebugLog("User Name or Employee Id exists for user "+userBean.getUserName(), LOGGER);
        redirectAttributes.addFlashAttribute("userBean", userBean);
        redirectAttributes.addFlashAttribute("errorMsg", messageSource.getMessage(e.getErrorcode(), new String[] {}, locale));
        return "redirect:/addUser.action?isAdd=true";
    }
}

private String redirectUser(User userBean, Locale locale,
        RedirectAttributes redirectAttributes, boolean status,
        boolean isAdd, String task) {
    if(isAdd) {
        if (status) {
            GlobalLogger.logInfoLog("User "+userBean.getUserName()+" has been " + task + "ed successfully", LOGGER);
            redirectAttributes.addFlashAttribute("successMsg", messageSource.getMessage("operationMsg.addUserSuccess", new String[] {userBean.getEmpEmail()}, locale));
            return "redirect:/users.action";
        } else {
            GlobalLogger.logApplicationDebugLog("Error in adding user "+userBean.getUserName(), LOGGER);
            redirectAttributes.addFlashAttribute("errorMsg", messageSource.getMessage("operationMsg.addUserFailure", new String[] {}, locale));
            redirectAttributes.addFlashAttribute("isAdd", isAdd);
            redirectAttributes.addFlashAttribute("userBean", userBean);
            return "redirect:/addUser.action?isAdd=true";
        }
    } else {
        if (status) {
            GlobalLogger.logInfoLog("User "+userBean.getUserName()+" has been " + task + "ed successfully", LOGGER);
            redirectAttributes.addFlashAttribute("successMsg", messageSource.getMessage("label.addSuccessMsg", new String[] {userBean.getFirstName()}, locale));
            return "redirect:/users.action";
        } else {
            GlobalLogger.logApplicationDebugLog("Error in adding user "+userBean.getUserName(), LOGGER);
            redirectAttributes.addFlashAttribute("errorMsg", messageSource.getMessage("label.addFailedMsg", new String[] {userBean.getFirstName()}, locale));
            redirectAttributes.addFlashAttribute("isAdd", isAdd);
            redirectAttributes.addFlashAttribute("userBean", userBean);
            return "redirect:/addUser.action?isAdd=false";
        }
    }
}

现在,您可以比较if的两个案例,因为它们非常相似。也许您可以重写它们以避免重复。例如,而不是 return "redirect:/addUser.action?isAdd=true";你可以写 return "redirect:/addUser.action?isAdd=" + isAdd.

重构是一个迭代过程。您应该进行小的更改,运行 单元测试以确保没有任何问题,然后重复直到结果令人满意。