Есть ли способ упростить этот исходный код? - PullRequest
0 голосов
/ 12 февраля 2020

В настоящее время я реализую API доски объявлений, используя загрузочную пружину. Сценарий с исходным кодом, который я собираюсь показать вам, касается изменения доски объявлений или комментариев,

Оба должны предоставить пароль во время комментариев или ввода доски объявлений перед изменением.

Итак, я просто использую 'isBoard' для ввода: скрытое значение для выполнения 'findById' в 'boardRepository' и сравниваю его с соответствующие функции passwordEncoder, а затем обновляют логическое значение.

Однако приведенный ниже код показывает, что один и тот же лог c дублируется и используется. Есть ли способ сделать это проще?

 @Transactional
public boolean tryToUpdateArticleOrReply(Long id, String password, boolean isBoard) throws ApiException {
    AtomicBoolean result = new AtomicBoolean(false);

    if(isBoard) {
         boardRepository.findById(id).ifPresent(
                board -> {
                    result.compareAndSet(passwordEncoder.matches(board.getUserPass(), password), true);
                }
         );
    } else {
        replyRepository.findById(id).ifPresent(
                reply -> {
                    result.compareAndSet(passwordEncoder.matches(reply.getUserPass(), password), true);
                }
        );
    }
    if(result.get())
      return result.get();

    throw new ApiException("INVALID_USER_PASS", "you submitted invaild password.", new ApiExceptionData().add("user_pass", password));
}

Ответы [ 2 ]

1 голос
/ 12 февраля 2020

Если ваши методы findById и getUserPass исходят из интерфейсов (а метод findById возвращает интерфейс, из которого поступает getUserPass), то вы можете просто сделать:

private boolean check(FindByIdInterface repository,
                      Long id,
                      String password) {
    return repository.findById(id)
            .map(result -> 
                passwordEncoder.matches(
                    result.getUserPass(), password))
            .orElse(false); 
}

И затем просто назовите его там, где вы выбираете repository для передачи на основе вашей переменной isBoard. isBoard ? boardRepository : replyRepository


Если они не происходят из общего интерфейса (ов), то вы можете эффективно «притвориться», что они делают, используя некоторые из функциональных интерфейсов java .

/* R = repository type, T = return type of 'findById' */
private <R, T> check(Function<R, Optional<T>> getByIdMapper,
                     Function<T, String> getUserPassMapper,
                     R repository,
                     Long id,
                     String password) {
    return getByIdMapper.apply(repository)
            .map(result ->
                passwordEncoder.matches(
                    getUserPassMapper.apply(result),
                    password))
            .orElse(false);
}

А затем назовите его примерно так:

if (isBoard) {
    return check(BoardRepository::getById,
                 Board::getUserPass,
                 boardRepository, id, password);
} else {
    // ...
}

Обратите внимание, что ни в одном случае AtomicBoolean не требовалось.

0 голосов
/ 12 февраля 2020

Вы можете сделать это следующим образом:

@Transactional
public boolean tryToUpdateArticleOrReply(Long id, String password, boolean isBoard) throws ApiException {
    Optional<String> optUserPass;
    if (isBoard) {
        optUserPass = boardRepository.findById(id).map(Board::getUserPass);
    else {
        optUserPass = replyRepository.findById(id).map(Reply::getUserPass);
    }
    if (optUserPass.isPresent() && passwordEncoder.matches(password, optUserPass.get()))
        return true;
    throw new ApiException("INVALID_USER_PASS", "you submitted invaild password.", new ApiExceptionData().add("user_pass", password));
}

Примечание 1: Название метода выглядит немного не так.

Примечание 2: Зачем boolean возвращать тип, когда он может только когда-либо возвращать true?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...