Java是否嵌套了?其他方法?

时间:2016-07-15 11:37:29

标签: java performance if-statement

有没有其他方法来处理这样的嵌套if else语句?我到处都读到太多,如果其他陈述都不好。这是处理此类案件的正确方法还是需要重构?

User user = loginHistoryService.findByUsername(loginRequest.getUsername());
    boolean isPasswordValid = bcryptPasswordEncoder.matches(loginRequest.getPassword(), user.getPassword());
    if (user.isDeleted()) {
        throw new AccountDeletedAuthException("Account is Deleted");
    } else if (user.isLocked()) {
        if (DateUtil
                .addHours(user.getLockedTime(), Integer.parseInt(
                        messageSource.getMessage(Constants.UNLOCK_ACCOUNT_AFTER_XX_HOURS, null, "24", null)))
                .compareTo(DateUtil.getCurrentDateTime()) < 0 && isPasswordValid) {
            logger.info("|*|*| Unlocking account. Account Lock Timer Over.. |*|*|*|");
            loginHistoryService.lockUserAccount(user.getUserId(), false);
        } else {
            throw new LockedException("Account is Locked");
        }
    } else if (user.getUserStatusId() == UserStatus.INACTIVE.getStatusCode()) {
        throw new InactiveAccountAuthException("Account is Inactive");
    } else if (user.getUserStatusId() == UserStatus.PENDING_VERIFICATION.getStatusCode()) {
        throw new DisabledException("".trim() + user.getUserId());
    } else if (!isPasswordValid) {

        List<Integer> loginAttemptStatuses = loginHistoryService.getLastThreeLoginAttempts(user.getUserId());
        loginHistoryService.createLoginHistoryEntry(user.getUserId(), LoginStatus.FAILURE.getStatusCode());
        int consecutiveFailedAttempts = 0;
        for (int tempIndex = 0; tempIndex < loginAttemptStatuses.size(); tempIndex++) {
            if (loginAttemptStatuses.get(tempIndex).intValue() == LoginStatus.FAILURE.getStatusCode()) {
                consecutiveFailedAttempts++;
            } else {
                break;
            }
        }
        if (consecutiveFailedAttempts == 3) {
            loginHistoryService.lockUserAccount(user.getUserId(), true);
        }
        throw new InvalidPasswordAuthException("".trim() + consecutiveFailedAttempts);
    }

2 个答案:

答案 0 :(得分:3)

有时,在处理业务逻辑时,您将拥有这样的结构。您可以通过切换声明来清理它,但在这种情况下它不会有太大帮助。

我没有尝试解决这个问题,而是试图重构这个巨大的块,以避免在如此多的抽象层之间跳跃。

以此块为例:

else if (user.isLocked()) {
    if (DateUtil
            .addHours(user.getLockedTime(), Integer.parseInt(
                    messageSource.getMessage(Constants.UNLOCK_ACCOUNT_AFTER_XX_HOURS, null, "24", null)))
            .compareTo(DateUtil.getCurrentDateTime()) < 0 && isPasswordValid) {
        logger.info("|*|*| Unlocking account. Account Lock Timer Over.. |*|*|*|");
        loginHistoryService.lockUserAccount(user.getUserId(), false);
}

在块的开头,我们正在处理"user level abstraction layer",询问用户是否被锁定。最后,我们也处于相同的抽象级别,解锁用户。但在两者之间,我们下去解析一些整数,执行一些日期算术并做其他不敬虔的事情,比如从messagesource中提取数据。

考虑把这些事情拉出来。将上面的代码块与下面的代码进行比较:

else if(user.isLocked() && canUnlockUser(user)) {
    logger.info("|*|*| Unlocking account. Account Lock Timer Over.. |*|*|*|");
    loginHistoryService.lockUserAccount(user.getUserId(), false);
}

或保持与您的代码等效(感谢tobias_k指出)

else if(user.isLocked()) {
    if(canUnlockUser(user)){
        logger.info("|*|*| Unlocking account. Account Lock Timer Over.. |*|*|*|");
        loginHistoryService.lockUserAccount(user.getUserId(), false);
    } else {
        throw new LockedException("Account is Locked");
    }       
}

尼斯!我实际上可以从第一眼看到发生了什么。你可以将它应用于整个混乱。

另一件事会增加我提到的块的可读性: 考虑同时制作loginHistoryService.lockUserAccount()loginHistoryService.unlockUserAccount()方法。像这样传递布尔标志是不可读的,丑陋的并且容易引入错误。所以,最后,该块将读取

else if(user.isLocked() && canUnlockUser(user)) {
    logger.info("|*|*| Unlocking account. Account Lock Timer Over.. |*|*|*|");
    loginHistoryService.unlockUserAccount(user.getUserId());
}

else if(user.isLocked()) {
    if(canUnlockUser(user)){
        logger.info("|*|*| Unlocking account. Account Lock Timer Over.. |*|*|*|");
        loginHistoryService.lockUserAccount(user.getUserId(), false);
    } else {
        throw new LockedException("Account is Locked");
    }       
}

答案 1 :(得分:2)

您的代码并不复杂,但阅读起来有点复杂。 在你的位置,我会处理我的Java代码格式化一点点。 然后,我将在私有方法中移动每个大的子条件块代码。 许多嵌入式&#34; if&#34;可能变得难以阅读和维护。将它们拆分为具有相关名称的私有方法可能很方便。

在你的情况下,我发现它是。 它可能看起来像那样:

User user = loginHistoryService.findByUsername(loginRequest.getUsername()); 
boolean isPasswordValid = bcryptPasswordEncoder.matches(loginRequest.getPassword(), user.getPassword());

if (user.isDeleted()) {
    throw new AccountDeletedAuthException("Account is Deleted");
}
else if (user.isLocked()) {
    handleWhenUserLocked(user);
}
else if (user.getUserStatusId() == UserStatus.INACTIVE.getStatusCode()) {
    throw new InactiveAccountAuthException("Account is Inactive");
}
else if (user.getUserStatusId() == UserStatus.PENDING_VERIFICATION.getStatusCode()) {
    throw new DisabledException("".trim() + user.getUserId());
}
else if (!isPasswordValid) {
    handleWhenPasswordNotValid(user);
}