Пакетная проверка номеров отличается от одиночной не масштабом, а природой ошибок. Когда строк сотни тысяч, случайные опечатки перестают быть главной проблемой: на первый план выходят систематические дефекты выгрузки, дубли и мусорные символы, которых в одиночном вводе просто не бывает. Ниже разберём правильный порядок шагов, классы результатов, работу с дублями и пустыми значениями, разбиение больших наборов и требования к отчёту.
Чем пакетная проверка отличается от одиночной?
При одиночном вводе перед нами человек, который видит своё значение и может его исправить. При пакетной обработке перед нами файл, у которого нет автора в зоне доступа: непонятно, кто его составлял, чем руководствовался и что считал правильным.
Отсюда три различия, определяющие всю конструкцию.
Первое — источник ошибок. В одиночном вводе преобладают опечатки набора. В файле преобладают дефекты выгрузки: лишние пробелы, неразрывные символы, строки, обрезанные при экспорте, значения, склеенные из двух полей.
Второе — цена остановки. Одиночный ввод можно отклонить и попросить исправить. Файл на сотни тысяч строк отклонить целиком нельзя: его нужно обработать до конца и вернуть разбор.
Третье — цель. При одиночной проверке цель — не пропустить неверное значение. При пакетной цель — дать такую картину данных, по которой можно принять решение: что исправить, что отбросить, что уточнить у владельца источника.
Почему первым шагом идёт очистка, а не арифметика?
Соблазн начать с вычисления контрольной цифры понятен: это самая содержательная часть. Но в файле большинство расхождений возникает не из-за арифметики, а из-за того, что строки записаны по-разному.
Что нужно убрать до любых сравнений. Разделители: пробелы, дефисы, точки, косые черты. Невидимые символы: неразрывные пробелы, знаки нулевой ширины, следы копирования из текстовых редакторов. Ведущий апостроф, который таблицы добавляют перед длинной числовой строкой. Различия регистра у букв. Полноширинные варианты знаков, если файл проходил через восточноазиатские системы.
Каждый из этих дефектов выглядит безобидно, а вместе они дают эффект, который невозможно переоценить: одна и та же запись встречается в файле в нескольких видах и считается разными значениями. Дубли не находятся, сверка не сходится, отчёт врёт.
Отсюда правило: очистка выполняется один раз, в самом начале, и её результат сохраняется. Все дальнейшие шаги — сравнение, разбор, определение системы — работают только с очищенным значением. Общая логика такой подготовки описана в материале про устройство проверки номера.
На какие классы делятся результаты проверки?
Двух классов «прошло» и «не прошло» недостаточно. Рабочий набор выглядит так.
| Класс | Признак | Что делать с записью |
|---|---|---|
| Согласовано | строке подошла система, цифра сходится | использовать, помня о смысловых проверках |
| Не сходится | формат подошёл, арифметика нет | отправить на перепроверку источника |
| Формат нарушен | состав знаков или длина не подходят | исправить формат, если это возможно |
| Только формат | система найдена, алгоритма нет | не выдавать суждение о значении |
| Система неизвестна | подходящей системы нет | уточнить у владельца данных |
| Дубль | значение уже встречалось выше | оставить одну запись по правилу проекта |
Шестой класс заслуживает отдельного внимания. Дубли в пакетной обработке — не техническая мелочь, а содержательная проблема: если один и тот же объект проходит дважды, все вычисления по нему удвоятся, а сверка с эталоном разойдётся. Поэтому признак дубля нужно выявлять до агрегации, а не после.
Порядок классов тоже имеет значение. Сначала формат, потом система, потом арифметика, и только затем дубли. Если искать дубли по неочищенным строкам, две записи, записанные по-разному, не совпадут, и обе уйдут в обработку.
Как обращаться с дублями, пустыми значениями и большими файлами?
Дубли. Сравнивайте очищенные значения, а не исходные строки. Если система допускает несколько корректных форм записи одного номера, дубль определяется по каноническому виду. Что делать с найденным дублем, решает не код, а правило проекта: иногда нужно оставить первую запись, иногда последнюю, иногда объединить поля.
Пустые значения. Их не следует сваливать в общий класс ошибок формата. Пустое поле — это отсутствие данных, а не неверные данные; действия отличаются. Отдельный класс пустых значений полезен ещё и потому, что позволяет увидеть, в каком поле выгрузки данные теряются систематически.
Большие файлы. Читайте их частями и обрабатывайте по мере чтения. Держать весь набор в памяти не нужно и опасно: на большом файле это приводит к отказу, причём в самый неподходящий момент. Разбиение на части требует отдельного решения — как считать дубли, если одинаковые строки попали в разные части. Ответ обычно такой: либо дубли определяются с помощью отдельного прохода, либо обрабатывается весь набор с записью промежуточных результатов.
Ещё одно решение — что делать с ошибкой внутри части. Прерывать весь проход из-за одной строки неразумно: файл не будет обработан никогда. Правильнее зафиксировать проблему и продолжить, вернув её в отчёт.
Каким должен быть отчёт, чтобы по нему можно было работать?
Отчёт существует не для того, чтобы показать качество работы, а для того, чтобы по нему исправляли данные. Значит, в нём должно быть то, что позволяет найти строку.
Что обязательно должно попадать в отчёт: номер строки в исходном файле, исходное значение в том виде, в каком оно пришло, очищенное значение, класс результата и краткое пояснение. Без исходного значения невозможно отличить дефект выгрузки от опечатки, а без номера строки невозможно вернуться к источнику.
Чего в отчёте быть не должно. Обобщённых оценок вместо разбора: сводка вроде «доля успешных около семидесяти процентов» не помогает исправить ни одной строки. Формулировок, переносящих результат проверки на реальность объекта: в отчёте по пакетной обработке нет места словам о том, что запись существует или действует.
| Что включить | Зачем это нужно |
|---|---|
| Номер строки | чтобы найти запись в исходном файле |
| Исходное значение | чтобы увидеть дефект выгрузки |
| Очищенное значение | чтобы понять, что именно проверялось |
| Класс результата | чтобы распределить работу |
| Пояснение | чтобы не разбираться заново в каждой строке |
Отдельно стоит фиксировать, какие правила применялись при обработке. Если через месяц тот же файл даст другой результат, причина будет либо в новых данных, либо в изменившихся правилах, и различить их без записи версии правил невозможно.
Как разработчику выстроить обработку
Первое — разделите конвейер на независимые ступени, которые не мешают друг другу: очистка, определение системы, проверка, поиск дублей, формирование отчёта. Каждая ступень должна быть проверяема на небольшом наборе отдельно от остальных.
Второе — следите за повторяемостью. Один и тот же файл при одном и том же наборе правил должен давать один и тот же отчёт. Если результат меняется от запуска к запуску, значит, где-то остался порядок, зависящий от случайности или от порядка чтения частей.
Третье — обрабатывайте записи так, чтобы повторный проход по уже обработанной строке не портил результат. Это особенно важно, когда обработка идёт частями и после сбоя её перезапускают: без такого свойства после сбоя придётся начинать сначала.
Четвёртое — помните главное ограничение всей этой работы. Она устанавливает согласованность и формат, но не подтверждает существование записей. Отчёт по пакетной обработке описывает данные, а не реальность, и его выводы нельзя переносить на людей, организации или счета. Об этом же говорит материал про номера без контрольной цифры, где отсутствие алгоритма делает границы проверки ещё заметнее.
Что делать дальше
Возьмите один реальный файл выгрузки и проверьте, что произойдёт с ним на каждом шаге по отдельности: чистка, система, арифметика, дубли. Чаще всего обнаруживается, что основная часть потерь происходит до арифметики. Затем добавьте в отчёт номер строки и исходное значение, если их там ещё нет.
Сравнить ожидаемое поведение удобно на инструменте проверки: он показывает, какие системы подходят строке и какое состояние получается в каждом случае. Все строки и списки, фигурирующие в примерах этой статьи, собраны как учебные: они не содержат данных реальных людей или организаций, а перед запуском обработки на настоящей выгрузке её следует обезличить и держать в изолированном контуре.