Почему тихая потеря хуже падения
Упавший скрипт чинят в тот же день: он виден, он мешает, у него есть трассировка. Скрипт, который взял четверть данных и бодро отчитался, живёт месяцами и всё это время производит выводы. Опаснее всего второй порядок эффекта — выводы выглядят нормально. «Клиент молчит», «в этом направлении заявок нет», «тональность нейтральная» читаются как факты о рынке, хотя это факты о фильтре.
Дважды за неделю вывод «клиент молчит» оказался неправдой: переписка шла, просто до сборщика не доезжала. Такие случаи и переводят класс из «неудобно» в «дорого».
Код возврата не про данные. Нулевой код возврата отвечает на вопрос «программа дошла до конца», а не «программа обработала ваш материал». Между этими вопросами лежит любой фильтр выборки, любое условие совпадения и любой класс символов.
Сюжет первый: фильтр под вчерашний формат
Экспортёр тянул диалоги условием, написанным под прежний способ адресации собеседника. Формат сменился, часть чатов на новый уже перешла, и условие перестало их находить — не с ошибкой, а как «ничего не найдено, значит ничего и нет».
| Что показала база коллектора за неделю | Доля |
|---|---|
| Активных личных чатов уже на новом формате адресации | 74,9% |
| Из них полностью анонимных — привычного идентификатора нет вовсе | 43,2% |
| Активной переписки, которую экспортёр молча отсекал | ≈75% |
| Сообщений об ошибке за всю неделю | 0 |
В реестр ошибок случай ушёл отдельным классом К9 с формулировкой «коллектор слеп к 75% чатов». Ценность формулировки в том, что она проверяемая: любой следующий сборщик обязан печатать, сколько записей он взял и сколько отбросил условием — и второе число нужнее первого.
Сюжет второй: одна причина, четыре инструмента
Слепота к казахской графике начиналась как дефект обезличивателя персональных данных — его мы разбирали отдельно. Оказалось, что причина живёт не в нём: класс символов, которым инструменты описывают «букву», не знал казахских букв. Дальше эффект расходится по всему, что этот класс использует.
| Инструмент | Как ломалось | Было → стало |
|---|---|---|
| Оценка тональности | казахский адрес и имя в тексте не распознавались | 0 из 2 → 2 из 2 |
| Извлечение маршрута | топонимы не считались топонимами, плечо маршрута молча терялось | — |
| Матчер строк | казахская буква работала как разделитель слова: сравнивались огрызки, без единого предупреждения | — |
| Голосовая заявка | адрес из казахской речи не извлекался, лид приходил без адреса — заявку переспрашивали | 0 из 3 → 3 из 3 |
Матчер в этом списке — самый неприятный. Инструмент, сравнивающий обрезанные строки, не ошибается громко: он выдаёт «совпадений нет» и долю сходства, и оба ответа выглядят как результат сравнения. Проверяется он единственным способом — подложить заведомо совпадающую пару и убедиться, что совпадение найдено.
Сюжет третий: инструмент не знает класса ваших данных
Третья история из той же семьи, но без потери — с путаницей. Детектор чувствительных данных считал персональными данными реквизиты организаций, потому что не знал правила: в местном идентификаторе один из разрядов отличает организацию от человека. Одно правило в коде — и целый пласт ложных тревог исчезает.
Второе правило из той же заметки записано как рабочий принцип: не расширяй поверхность чужой задачи. Когда по ходу работы под руками оказываются чувствительные данные, соблазн «заодно положить рядом, лишним не будет» велик, и логика «утечки же не случится» звучит убедительно. Даже когда она верна, каждая новая копия — ещё одно место, которое кто-то потом обязан охранять.
Что забрать себе
- Считайте отброшенное, а не взятое. Строка «взято N записей» бесполезна без строки «отсечено условием M». Второе число и есть предмет проверки.
- Проверяйте инструмент на алфавите своей страны. Регулярное выражение, не знающее букв языка, на котором к вам пишут, — не редкость, а норма по умолчанию.
- Позитивный контроль на совпадение. Подложите паре строк заведомое совпадение и убедитесь, что матчер его видит; «совпадений нет» — самый тихий из всех дефектов.
- Формат внешней системы меняется без вас. Условие выборки, написанное под прежний формат, не ломается — оно просто перестаёт находить, и это надо ловить счётчиком.
- Дефект и класс дефекта закрываются разным. Правка в одной точке — дефект; поиск всех вхождений того же кода — класс.
- Не плодите копии чувствительных данных «заодно». Отсутствие утечки сегодня не отменяет расширенной поверхности завтра.