Поэтому на днях я работал над некоторыми довольно хитрыми правилами проверки входящего идентификатора кода. Например,
999392304II + TJAJEIAJTI901119
или
EPFOOMNNVLLALOWEIITOE.
Система, в которой создается этот код, довольно требовательна к тому, как эти коды должны выглядеть. (Ради этого поста в блоге я придумаю здесь некоторые бизнес-правила, на самом деле они немного отличаются, но их природа одинакова):
- Код не может быть нулевым или пустой строкой (конечно)
- Если в коде есть только буквы (AZ), он должен быть длиннее 10 символов, но меньше 20
- С другой стороны, если есть буквы, смешанные с цифрами, это должно быть ровно 10 или 15 символов
- Только номера не допускаются
- Другие символы не допускаются, но знаки + разрешены, если код начинается с 999. В этом случае максимальная длина равна 10.
Вместо того, чтобы просто следовать этим правилам, я реализовал их, используя
Предикаты из
Google Guava . Я был очень доволен результатом и хотел сравнить его с тем, как будет выглядеть классическое решение.
Я создал
небольшой проект на Github, который демонстрирует вышеуказанные правила. Есть две ветви:
Обе ветви проходят один и тот же набор тестов. Я не буду клясться в правильности реализации, поскольку сейчас ночью 01:59, и тесты не очень обширные.
Производительность не является большой вещью в этой функции проверки. Мы имеем дело с кодами, которые поступают каждые несколько секунд, поэтому у нас есть много миллисекунд, чтобы потратить код, чтобы он выглядел как можно лучше. Кроме того, мое регулярное выражение отстой, я знаю.
Вот краткий обзор того, что я закончил с использованием if и else:
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