Правила валидации грязных данных: как заранее описать недопустимые значения, дубликаты и форматы, чтобы ИИ встроил проверки в продукт.

«Грязные» данные - это не обязательно что-то явно «неправильное». Чаще это значения, которые выглядят нормально, но не подходят вашим правилам. Из-за них появляются дубли, странные отчеты, сбои в логике и тихие ошибки, которые всплывают слишком поздно.
Обычно к грязным данным относят:
Такие ошибки выгоднее ловить до записи в базу. Когда грязные данные уже попали внутрь, они начинают расползаться: участвуют в расчетах, уходят в интеграции, копируются в новые таблицы. Исправление превращается в отдельный проект: нужно найти записи, понять контекст и не сломать то, что на них уже завязано. Проверка на входе проще: пользователь или процесс импорта сразу получает понятную причину отказа.
Чаще всего проблемы рождаются в трех местах: в формах (человек вводит как привык), при импорте из файлов (Excel, CSV, выгрузки из старых систем) и в интеграциях (разные сервисы по-разному называют одно и то же поле). Типичный пример - телефон: в одном файле он хранится как "+7...", в другом как "8...", в третьем как число без ведущих нулей.
Важно различать проверку и очистку:
Практичный подход - сочетать оба шага: сначала безопасная очистка (то, что не меняет смысл), затем строгая валидация.
Если правила описаны заранее и достаточно конкретно, их можно внедрить одинаково в форму, API и импорт. Так проще держать единое поведение и не получать ситуацию «на форме проходит, а в импорте нет».
Если данные приходят из файлов, форм, CRM или от партнера, почти всегда всплывает один и тот же набор проблем. Базовые правила можно описать заранее и встроить в продукт так, чтобы ошибки ловились до сохранения.
Первое, что стоит запретить, - «псевдоданные». Они выглядят как заполненное поле, но по факту ничего не значат: пробелы, "-", "не знаю", "нет", "тест", "asdf", "qwerty", иногда даже "0" там, где ноль невозможен.
Полезно заранее разделить поля на:
Тогда правило становится понятным: пустые значения и «заглушки» запрещены только там, где поле должно иметь смысл.
Форматы ломаются чаще всего: даты, телефон, email, ИНН, денежные суммы. Хорошо работает двухуровневая проверка:
Отдельно стоит проверить длину строк и нежелательные символы. Даже без атак пользователи вставляют переносы строк, табы, невидимые пробелы, кавычки, куски HTML. Минимальный базовый набор обычно такой: тримминг пробелов по краям, запрет управляющих символов, ограничение максимальной длины и нормализация регистра там, где это уместно.
Пример с телефоном: можно принимать значения вида +7XXXXXXXXXX, но перед проверкой очищать пробелы, скобки и дефисы. Если после очистки осталось не 11 цифр (для РФ), запись не проходит.
Точные дубли - одинаковые значения ключевых полей (например, email или телефон). «Почти одинаковые» - когда смысл тот же, но отличается одна буква, пробел, формат номера или регистр: Ivanov vs Иванов, mail.ru vs MAIL.RU, +7 999... vs 8999....
Заранее решите:
Даже идеально отформатированные данные могут быть неверными по смыслу. Типовой пример: дата окончания раньше даты начала. Другие частые случаи: возраст не совпадает с датой рождения, скидка больше суммы заказа, «страна = Россия», а телефон не российский (если вы это вообще проверяете).
Такие правила удобнее формулировать как простые условия «если - то». Их легче переносить между формой, API и импортом.
Проверки нужны не только «чтобы ругаться», а чтобы было понятно, что делать дальше. Заранее определите:
Если вы собираете продукт через TakProsto (takprosto.ai), удобно сразу проговорить эти правила как требования: какие поля обязательны, как нормализовать значения, какие проверки критичные и что считать дублем. Тогда одно и то же поведение проще провести через формы, API и импорт.
Формулировки уровня «поле не должно быть пустым» редко спасают. Нужно договориться, что именно считается недопустимым и как система реагирует. Это и есть практическая валидация: вы описываете правило один раз, а дальше оно одинаково работает во всех точках входа.
Сначала разделите поля на обязательные и необязательные. Обязательное поле - без него запись теряет смысл (например, телефон для SMS-уведомлений). Необязательное - можно сохранить запись и без него (например, отчество).
Дальше для каждого поля перечислите «плохие» значения на реальных примерах: "-", "нет", "не знаю", "0", "test", "asdf", "12345". Для поля «Город» запретом может быть явная ерунда или опечатка вроде "Москвааа", а для «ИНН» - строки вида "0000000000" или "1111111111".
Отдельно зафиксируйте, что считать пустым. Импорты часто ломаются не из-за настоящего null, а из-за «почти пустых» значений:
0 там, где 0 не имеет смысла (например, возраст)null)Затем решите, что делать при нарушении. Помогает простая матрица: блокируем сохранение или отмечаем как подозрительное. Например, «email пустой» для обязательного поля - ошибка, запись не проходит. А «город не распознан» - предупреждение: запись сохраняется, но поле очищается или помечается.
Сообщения лучше писать так, чтобы человек сразу понял, что исправить. Не «Ошибка валидации», а «Телефон пустой или содержит только пробелы. Введите номер в формате +7...». Такие формулировки одинаково полезны и в интерфейсе, и в логах импорта.
Мини-сценарий: при импорте клиентов поле «Комментарий» необязательное, поэтому "-" можно заменить на пусто и продолжить. А поле «Телефон» обязательное, поэтому значения "нет" и "00000000000" должны останавливать загрузку строки и показывать понятную причину.
Самые частые ошибки - это разные привычки ввода. Один пишет дату как 01.02.2026, другой как 2026-02-01, третий добавляет время. Если это не зафиксировать, правила начнут спорить сами с собой.
Для даты и времени называйте точный шаблон и часовой пояс. Не «дата», а «ДД.ММ.ГГГГ», с примером: 31.01.2026. Если нужно время, уточните формат: 31.01.2026 14:30 (24-часовой), и решите, нужны ли секунды.
Для чисел заранее определите диапазон и точность. Например:
Сразу оговорите отрицательные значения: где они разрешены (например, корректировка), а где нет (количество, цена).
Укажите минимум и максимум длины, а также допустимые символы. Примеры:
Отдельно договоритесь про пробелы: обрезать по краям, заменять двойные пробелы на один, запрещать невидимые символы.
Для телефона и email полезно описать нормализацию:
+7XXXXXXXXXX, отклонять, если после нормализации не 11 цифр@ или есть пробелы внутриЕсли вы ожидаете, что правила будут автоматически переноситься в форму и бэкенд, формулируйте их как короткий набор требований:
Локаль лучше согласовать заранее. Если пользователь вводит «1,5», а система ждет «1.5», вы получите странные округления и «тихие» ошибки.
Дубликаты почти всегда появляются там, где есть импорт, ручной ввод и несколько источников. Если их не ловить, отчеты «разъезжаются», менеджеры звонят одному клиенту дважды, а автоматизация начинает опираться на неверную картину.
Сначала выберите «ключ дубликата». Это может быть одно поле (email, телефон, ИНН) или связка (ФИО + дата рождения, компания + ИНН, адрес + квартира). Один и тот же набор правил даст разные результаты в зависимости от этого решения.
Дальше разделите дубли на два типа:
Для похожих дублей заранее опишите нормализацию: обрезать пробелы, привести email к нижнему регистру, оставить только цифры в телефоне, убрать лишние точки в конце. Если для ваших данных допустимо, отдельно зафиксируйте, что делать с «ё/е».
Затем определите действие при обнаружении дубликата. Вариантов немного, важно выбрать один (или пару) и держать его везде:
Если вы объединяете записи, задайте правило «победителя». На практике часто работает простое: «при merge не затирать заполненное пустым, а даты и статусы брать из более новой записи».
Отдельно опишите конфликты: например, «один email, но разные телефоны». Решение может быть таким: хранить оба телефона, выбрать подтвержденный, либо остановить импорт и отправить на ручную проверку.
Чтобы проверки появились без сюрпризов, начните не с кода, а с точного описания. Чем конкретнее правила, тем меньше споров в команде и тем предсказуемее результат.
Зафиксируйте, откуда приходят данные и в каком виде: CSV из бухгалтерии, ручной ввод в форме, интеграция по API. Укажите кодировку, разделители, какие поля могут быть пустыми, какие значения чаще ломаются (пробелы, запятые в числах, разные раскладки).
Самый понятный формат - «поле - правило - примеры», с валидными и невалидными значениями.
Дальше задайте поведение системы при ошибке. Один и тот же «плохой» файл можно обрабатывать по-разному: блокировать загрузку целиком, пропускать строку, сохранять, но помечать статусом «нужна проверка». Это лучше прописать явно по типам ошибок (критические и некритические).
И еще одна вещь, которую часто забывают: тестовые кейсы. Попросите набор из 5-10 позитивных и 5-10 негативных примеров на каждое важное правило и зафиксируйте критерии приемки: сообщения понятны, поведение при частичных ошибках соответствует спецификации, сервер не принимает «мусор», даже если его обошли через импорт.
Представим простую CRM, куда менеджер загружает клиентов из CSV: name, email, phone, company, created_at. Файл собран из нескольких источников, поэтому внутри есть пропуски, лишние пробелы и «почти телефоны». Если пустить такое сразу в базу, вы получите повторяющиеся карточки, невозможность связаться с клиентом и странную аналитику.
Типичные «грязные» значения, которые встречаются уже в первом импорте:
phone пустой или равен -, нет, 0phone выглядит как «+7 (999)» (маска без номера) или «8 999 123-45-6» (не хватает цифры)email с пробелами: ivan@site.ru или с запятыми вместо точекname состоит из пробелов или «Неизвестно»created_at в формате 12/31/24 вместо ожидаемого 2024-12-31Чтобы импорт был предсказуемым, заранее разделите правила на две группы: что исправляем автоматически и что отклоняем.
Автоисправления - только те, что можно сделать однозначно и безопасно: обрезать пробелы по краям, нормализовать email по регистру, привести телефон к единому виду (оставить только цифры, для РФ заменить начальную 8 на 7). С датами аккуратнее: если формат двусмысленный, лучше не «угадывать», а отклонять с понятной ошибкой.
После автоисправлений применяйте жесткие правила. Например, отклоняйте строку, если email пустой или не проходит базовую проверку, телефон после очистки не содержит 11 цифр (для РФ), name пустой или слишком короткий, дата не распознана или находится в будущем (если это запрещено вашей логикой).
Отдельная боль - дубликаты. Допустим, в файле две строки с одним email, но разными именами: «Иван Петров» и «Иван П.». Если email - главный ключ клиента, новая карточка не создается. Дальше вы выбираете поведение: обновить существующую по правилам приоритета полей или пропустить строку. Например, имя не перезаписывать, если новое имя короче и похоже на сокращение.
Пользователь должен видеть итог импорта и контроль над результатом: сколько строк создано, сколько обновлено, сколько пропущено, сколько ошибок и почему. Тогда не будет ощущения, что записи «пропали».
Первая проблема - правила звучат как пожелания, а не как инструкции. Фраза «телефон должен быть правильным» заставляет всех угадывать: какой формат правильный, какие страны поддерживать, что делать с пробелами и кодом.
Плохой признак - правило без примера. Дайте 1-2 допустимых и 1-2 недопустимых значения, и проверка станет предсказуемой.
Вторая ошибка - смешивать формат и смысл в одной строке. «Email в формате @ и должен принадлежать корпоративному домену» - это две разные проверки с разными подсказками пользователю и разными действиями. Формат часто можно исправить (убрать пробелы, нормализовать регистр), а смысл требует решения (разрешать ли публичные домены, отправлять ли на проверку).
Третья ошибка - описать нарушение, но не последствия. «Запрещены пустые значения» - и что дальше? Остановить импорт, пропустить строку, подставить значение по умолчанию, пометить как черновик? Без этого в продукте появится хаос: разные экраны будут вести себя по-разному.
Четвертая ошибка - проверки есть только в интерфейсе. Пользователь может обойти UI через импорт, интеграцию или прямой запрос. Любое правило, которое влияет на качество данных, должно проверяться на сервере.
Пятая ошибка - нет тестовых данных для крайних случаев. В реальном мире всплывают лишние пробелы, «+7(999)…», ведущие нули, смешанные языки и странные разделители. Это нужно проверять заранее.
Если держать правила в компактном и проверяемом виде, обычно хватает пяти пунктов:
Перед тем как встраивать правила, стоит быстро проверить, что они описаны достаточно точно.
Сначала определитесь с обязательными полями и тем, что вы считаете пустым значением. Для одного поля это может быть пустая строка, для другого - строка из пробелов, для третьего - 0 или «не выбрано». Если это не зафиксировать, одни и те же «пустоты» будут вести себя по-разному в разных частях системы.
Затем добавьте короткие примеры. Для каждого поля обычно хватает 3-5 вариантов «нормально» и «нельзя». Примеры помогают одинаково понимать формат, допустимые символы и типичные ошибки. Для телефона, например: "+7 999 123-45-67" можно, "9991234567" можно (если вы это допускаете), "+7-ABC" нельзя.
Проверьте себя по пунктам:
В конце прогоните небольшой набор тестов на крайние случаи: длины строк, диапазоны чисел, даты (включая 29 февраля), разные разделители, ведущие нули.
Главный риск - оставить правила в переписке или в голове одного человека. Зафиксируйте их как простой «контракт данных»: что валидно, что отклоняем, а что исправляем.
Хороший контракт можно держать в одном документе или рядом с кодом. Важно, чтобы там были не только форматы, но и смысл: какие значения считаются «неизвестно», как трактовать пустые поля, какие справочники допустимы.
Дальше внедряйте постепенно. Начните с потока, где боль максимальная (обычно импорт). Когда он станет предсказуемым, переносите те же принципы на формы, API и фоновые интеграции. Так правила не расползутся на разные «версии правды».
Заранее договоритесь о границе автоисправлений. Пробелы по краям и приведение телефона к единому формату обычно можно делать автоматически. А «угадывание» ИНН или склейка разных клиентов - только вручную.
Если вы делаете это в TakProsto, удобно работать от требований: описать контракт и примеры в planning mode, попросить сгенерировать проверки на стороне клиента и сервера, а затем сохранить результат снапшотом, чтобы при неудачном изменении быстро откатиться.
Версионирование правил тоже важно. Сегодня вы запрещаете "-" в телефоне, а завтра решаете принимать и чистить. При ошибке в новой версии нужно иметь возможность откатиться, иначе вы либо начнете терять данные, либо пропустите мусор.
Мини-сценарий: вы меняете правило для поля email, и импорт начинает отклонять 30% файла из-за старых адресов без домена. Если правила версионированы, вы откатываетесь, добавляете режим «предупреждение вместо ошибки» для этого случая и выпускаете новую версию уже с понятной политикой.
Это значения, которые формально «похожи на правду», но нарушают ваши правила. Из‑за них появляются дубли, неверные расчеты, странные отчеты и ошибки, которые замечают слишком поздно.
Потому что исправлять внутри базы дороже: данные уже участвуют в расчетах, уходят в интеграции и копируются дальше. На входе проще остановить ошибку и сразу показать понятную причину, что нужно исправить.
Начните с безопасной очистки, которая не меняет смысл: обрезать пробелы по краям, убрать скобки и дефисы в телефоне, привести домен email к нижнему регистру. Затем применяйте строгую валидацию и отклоняйте то, что после очистки все равно не соответствует правилам.
Зафиксируйте единый «контракт данных»: одинаковые форматы, одинаковые определения пустоты, одинаковые действия при ошибках. Затем применяйте этот контракт во всех точках входа, а ключевые правила обязательно проверяйте на сервере.
Определите для каждого обязательного поля, что считается пустым: null, пустая строка, строка из пробелов, а также служебные «заглушки» вроде "-", "нет", "n/a". Для необязательных полей такие значения лучше очищать до пусто, а не хранить как данные.
Задайте один формат и добавьте пример, а потом проверьте «разумность». Например, дата должна быть в конкретном шаблоне и существовать как календарная дата, а сумма — попадать в допустимый диапазон и иметь нужную точность.
Сначала выберите ключ, по которому вы считаете записи одинаковыми, например email или телефон. Затем нормализуйте значения перед сравнением, чтобы «+7…» и «8…» или разный регистр не создавали ложные различия.
Обычно есть три понятных варианта: блокировать создание, обновлять существующую запись по правилам приоритета, либо помечать как «нужна проверка». Если выбираете объединение, заранее решите, какие поля «побеждают» при конфликте и что никогда нельзя затирать пустым.
По умолчанию блокируйте критичные ошибки, которые делают запись бессмысленной, например обязательный телефон или email невалиден. Некритичные вещи лучше пропускать с предупреждением, чтобы импорт был предсказуемым, а пользователь видел, что именно исправлять.
Опишите правила в виде мини-спеки «поле — правило — примеры можно/нельзя» и добавьте ожидаемое поведение при нарушении. В TakProsto удобно сначала зафиксировать это в planning mode, затем попросить внедрить проверки на клиенте и сервере, а после изменений сохранять снапшот для быстрого отката.