Статьи

Предикаты Google Guava

Поэтому на днях я работал над некоторыми довольно хитрыми правилами проверки входящего идентификатора кода. Например,

999392304II + TJAJEIAJTI901119

или

EPFOOMNNVLLALOWEIITOE.

Система, в которой создается этот код, довольно требовательна к тому, как эти коды должны выглядеть. (Ради этого поста в блоге я придумаю здесь некоторые бизнес-правила, на самом деле они немного отличаются, но их природа одинакова):

  • Код не может быть нулевым или пустой строкой (конечно)
  • Если в коде есть только буквы (AZ), он должен быть длиннее 10 символов, но меньше 20
  • С другой стороны, если есть буквы, смешанные с цифрами, это должно быть ровно 10 или 15 символов
  • Только номера не допускаются
  • Другие символы не допускаются, но знаки + разрешены, если код начинается с 999. В этом случае максимальная длина равна 10.

Вместо того, чтобы просто следовать этим правилам, я реализовал их, используя
Предикаты из
Google Guava . Я был очень доволен результатом и хотел сравнить его с тем, как будет выглядеть классическое решение.

Я создал
небольшой проект на Github, который демонстрирует вышеуказанные правила. Есть две ветви:

ifelse — старый императивный способ, использующий if и else
Предикат — Новый функциональный способ, использующий предикаты

Обе ветви проходят один и тот же набор тестов. Я не буду клясться в правильности реализации, поскольку сейчас ночью 01:59, и тесты не очень обширные.

Производительность не является большой вещью в этой функции проверки.
Мы имеем дело с кодами, которые поступают каждые несколько секунд, поэтому у нас есть много миллисекунд, чтобы потратить код, чтобы он выглядел как можно лучше. Кроме того, мое регулярное выражение отстой, я знаю.

Вот краткий обзор того, что я закончил с использованием if и else:

(
Источник на Github )

    public static boolean isCodeAllowed(String code) {
        return isNotNullOrEmpty(code) &&
               onlyLettersCorrectLength(code) &&
               lettersAndNumbersCorrectLength(code) &&
               numbersOnlyNotAllowed(code) &&
               plusSignOnlyParticularity(code);
    }

И здесь используются предикаты:
( Источник на Github )

    public static boolean isCodeAllowed(String code) {
        Predicate<String> predicate = and(
                not(NULL_OR_EMPTY),
                ONLY_LETTERS_CORRECT_LENGTH,
                LETTERS_AND_NUMBERS_CORRECT_LENGTH,
                not(matching(NUMBERS_ONLY)),
                PLUS_SIGN_PARTICULARITY);
        return predicate.apply(code);
    }

 


Чтобы по-настоящему оценить различия, лучше всего взглянуть на целые классы на Github. Это проект Maven, поэтому вы можете импортировать его в IDEA или Eclipse и использовать Git для перехода между двумя ветвями для сравнения.

Я не говорю, что способ предикатов легче читать или писать, но в нем есть что-то функциональное и декларативное, которое кажется … мощным. Хорошая особенность этих предикатов заключается в том, что их можно легко комбинировать с друг другом и повторно использовать в других местах, например, при фильтрации коллекций с использованием других утилит Guava.

Обратите внимание, что полное решение в стиле предикатов намного больше, но во всем виноваты те базовые предикаты, которые я определил для определения соответствия, shorterThan, longThan и correctLength.

Если бы мы имели дело с языком, который должным образом поддерживал функции (предикат — это функция, которая переходит в истину / ложь), он, вероятно, выглядел бы намного лучше. Возможно, с Java 8 я могу немного уменьшить код ..


Я только что прочитал, что разработчики Guava собираются включить новые свободные интерфейсы для объединения предикатов более элегантным способом, чем стиль префикса, который я использовал выше.
Может быть что-то вроде

 new FluentPredicate().not(NULL_OR_EMPTY).and(ONLY_LETTERS).build(). 

Узнайте больше
здесь о FluentPredicates и т. Д. Они не могут быть слишком далеко, с точки зрения выпуска.

Для других ресурсов Гуавы, проверьте
мою коллекцию здесь .

С http://blog.tfnico.com/2011/12/google-guavas-predicates.html