- PVSM.RU - https://www.pvsm.ru -
Если вспомнить все ТЗ с описаниями валидации полей — они всегда выглядили примерно так:
Требования часто приходят набором простых однозначных фраз. А мы, программисты, переводим эти требования в код.
Можно превращать их в одно ультимативное регулярное выражение, вроде
const validateLogin = login => /^[a-zA-z_d]{6,12}$/.test(login);
Но лучше писать более простые функций которые легче читать и связывать с непосредственным ТЗ:
const charMatch = new RegExp('^[a-zA-Z_0-9]*$');
const validateLogin = login => {
if (login.length < 6) return false;
if (login.length > 12) return false;
if (!charMatch.test(login)) return false;
return true;
};
А что если ещё сильнее упростить этот код до чего-то вроде:
const validateLogin = login =>
validate(login)
.notLessThan(6)
.notLongerThan(12)
.hasOnly(['a-z','A-Z','0-9','_']);
Основная идея заключается в том, что требования к валидации зачастую можно разложить на список независимых типичных утверждений. А эти утвержджени (asserts) можно собрать в коллекцию и переиспользовать.
Именно этим и занимается библиотека validate.it.js [1]. Ядро которой не превышает и ста строк и делает не так уж много:
Вышеописанное значит, что выполнив код вроде этого:
validate('Pa$$w0rd')
.hasLettersLatin()
.hasNumbers()
.has("!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "_", "+");
Вы получите вот такой результат.
{
ok: true,
base: 'Pa$$w0rd',
asserts: ['hasLettersLatin', 'hasNumbers', 'has'],
errors: []
}
Думаю это и так очевидно, но немного распишу
ok
bool — статус валидации
true
— валидация прошла успешноfalse
— валидация проваленаbase
string — валидируемая строкаasserts
array — список имён вызванных assert'ов в порядке очерёдности их вызоваerrors
array — массив отчётов в формате Validation Report [2] всех провалившихся assert'овВот пример провалившейся валидации
validate('bob')
.hasLettersLatin()
.hasNumbers();
// -->
{
ok: false,
base: 'bob',
asserts: ['hasLettersLatin', 'hasNumbers'],
errors: [
{
path: [],
rule: 'hasNumbers',
details: {
string: 'bob',
subStrings: ["1","2","3","4","5","6","7","8","9","0"],
found: false,
message: '"bob" has no numbers'
}
}
]
}
Эта простая идея позволяет писать код валидации максимально приближённым к требованиям. При этом сами assert'ы получаются очень простыми и являются чистыми функциями [3]. Их легко поддерживать, тестировать, и добавлять новые.
Кстати да, если вам не хватает какого-то assert'а — вы легко можете на-лету добавить его через @static .extend
[4] или использовать assert .eval
[5].
Но не жадничайте своих assert'ов сообществу. Станьте контрибьютером!
А теперь сюрприз. Самих assert'ов в библиотеке ещё практически и нет. Только парочка базовых вроде .has
, .match
, .eval
и ещё немного для примеров. Нету даже тех, которые я использовал в листингах этого поста. Всё дело в том, что мне хотелось привлечь внимание к идее, а не к реализации.
Более того, я считаю, что моё видение необходимых assert'ов может сильно отличаться от видения сообщества. И, делая этот инструмент "под себя" я могу сделать его неудобным для других JS разработчиков. И у меня возникла идея — привлечь к созданию этого инструмента JS сообщество. Что бы самому ничего не делать он покрывал потребности сообщества, а не мои собственные.
Я приглашаю JS разработчиков стать контрибьютерами validate.it.js [1].
Всех кто хочет контрибьютить в опенсорс, но не знает с какого проекта начать.
Всех кто хочет сделать для себя и для всего сообщества удобный инструмент валидации.
Вместе мы сможем наполнить коллекцию реально необходимыми всем нам assert'ами.
При этом контрибьютером может быть разработчик любого уровня. Ведь кто-то захочет заняться валидацией по длине строки, а кому-то, например, интереснее реализовывать проверку на соответствие даты всем вариантам стандарта ISO 8601.
К pull-request'ам предъявляются весьма мягкие требования:
Кстати о вышеупомянутых VR которыми наполняется массив .errors
в случае провалившихся assert'ов. Я искал какой-то стандарт для представления ошибок валидации. И по своему опыту знал, что банального true
/false
и даже null
/'error message'
недостаточно. И судя по всему, такого стандарта на сегодняшний день нету.
Зато есть замечательная идея [6] читателя rumkin [7]
"Универсальный интерфейс отчётов валидации" — @rumkin [8] / Validation Report [9]. git
Это простой DTO [10], который позволяет передать максимально подробную информацию о причинах провала валидации. Состоит из:
path
array — местоположение объекта проверки. В контексте валидации строк — это всегда пустой массив []
.rule
string — имя assert'а или правило по которому проводилась валидация.details
object — детали или описание в "машино-понятном виде" причины провала валидации. У этого параметра нету чётко-стандартизированный структуры, кроме одного поля:
details.message
string — описание в "человеко-понятном виде". Это не стандартное для VR поле, но в рамках данного проекта оно обязательно.Пример:
{
path: [],
rule: 'notLongerThen',
details: {
string: 'markopolo',
length: 9,
max: 6,
message: '"markopolo" longer then 6 characters'
}
}
rumkin [7], кстати, написал небольшой тул для генерации Validation Report'ов. но ради 0Dependecy [11] я не использую конкретно эту реализацию. Благо генерация VR достаточно простая задача.
Будет здорово, если VR однажды станут стандартом, хотя бы локальным.
Не стесняйтесь задавать вопросы — буду только рад расширить contributer's guide [12] или ридми проекта.
Автор: titulusdesiderio
Источник [13]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/javascript/275324
Ссылки в тексте:
[1] validate.it.js: https://github.com/titulus/validate.it.js
[2] Validation Report: #validation-report
[3] чистыми функциями: https://ru.wikipedia.org/wiki/%D0%A7%D0%B8%D1%81%D1%82%D0%B0%D1%8F_%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D1%8F
[4] @static .extend
: https://github.com/titulus/validate.it.js/#extend
[5] assert .eval
: https://github.com/titulus/validate.it.js/#eval
[6] идея: https://habrahabr.ru/post/348530
[7] rumkin: https://habrahabr.ru/users/rumkin/
[8] @rumkin: https://github.com/rumkin
[9] Validation Report: https://github.com/rumkin/validation-report
[10] DTO: https://ru.wikipedia.org/wiki/DTO
[11] 0Dependecy: http://khanlou.com/2015/11/zero-dependencies/
[12] contributer's guide: https://github.com/titulus/validate.it.js/blob/master/CONTRIBUTING.md
[13] Источник: https://habrahabr.ru/post/350438/?utm_campaign=350438
Нажмите здесь для печати.