有没有其他方法来处理这样的嵌套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);
}
答案 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);
}