В нашей прошлой статье мы рассказывали о функциональных зависимостях и их применении в эксплорации и очистке данных. Сейчас расскажем о разработке информационных систем. Как сделать нужную для бизнеса информационную систему (ИС), которая полностью работает, и при этом не работает? Очень просто. Предоставьте разработчикам ИС ограниченный набор тестовых данных и лишите их возможности сопровождения системы на реальных данных. Очень часто заказчики забывают важность предоставления своевременного и полного набора данных для информационных систем, что в итоге приводит к весьма плачевным результатам. В этой статье мы поделимся своим опытом в этой сфере и попытаемся обосновать важность получения правильных тестовых данных.   Для начала давайте разберемся, откуда вообще могут взяться данные для вашей системы.  Есть следующие варианты: Разрабатываемая информационная система и есть первоисточник данных. Важно отметить, что под первоисточником подразумевается не юридическая значимость, а то, что данные вводятся и контролируются полностью ИС. Разрабатываемые системы получают данные из другой системы, которая является первоисточником данных.  Разрабатываемая система получает данные, первоисточником которых являются реальные документы или ИС, которые фактически не вели контроль целостности хранимых данных. Первый и второй вариант достаточно просты для обработки и понимания, а вот третий является очень опасным. Особенно если он выглядит, как второй и, при этом, жизненный путь данных очень сложный. Например, такой, как представлен на рисунке (ИС3 – источник данных для нашей системы). Цепочек преобразования может быть намного больше. Вот чем может быть опасна такая ситуация: представители заказчика, с которыми происходит обсуждение разработки ИС, могут быть искренне убеждены в качестве своих данных и в отсутствии в них проблем. А даже если они в курсе возможных проблем, то на этапе заключения договора об этом могут скромно умолчать. Ведь с их точки зрения, лучше данные – меньше работ по их загрузке – меньше сумма контракта.  Обычно люди, которые никогда серьезно не занимались обработкой данных, верят сразу в несколько мифов о свои данных: Бизнес-идентификатор уникален. Это не так, даже если это прописано по закону. Именно поэтому при заполнении паспорта вас просят указать не только серию, номер, ФИО, но и дополнительную информацию. Также на территории РФ не являются уникальными такие данные как СНИЛС и ИНН. Результат налицо: две посылки, которые были отправлены по одному номеру отслеживания? Легко. Два объекта недвижимости, которые имеют один кадастровый номер – получите, распишитесь.  Данные структурированы и имеют четкие связи, прописанные по ключам. Так тоже бывает далеко не всегда. При разработке ИС часто наблюдается такая картина. Аналитики создают красивую и подробную ER-модель, в которой прописаны все ограничения и ссылки (foreign keys). А при поступление реальных данных этих ограничений становится все меньше и меньше – просто потому, что в систему попадают данные, которые им не удовлетворяют.  Данные реальных объектов не меняются. Хорошо, про изменение паспорта и что с этим делать все знают. Каждый паспорт содержит сведения о ранее выданном документе. А вот как быть с адресами? Например, мы вполне могли купить квартиру в г. Ленинград, ул. Железняка, дом 12. А продавать уже в г. Санкт-Петербург, Малый пр., дом 12. В конце нулевых нормой было считать телефон уникальным для конкретного абонента. Если сценарии смена номера телефона еще прорабатывались, то вот сценарий отказа от номера телефона и возвращение в его оборот – нет.  Данные форматированы. Предположим, что информационная система поставщик данных хранит данные в реляционной СУБД. Насчет связей мы уже проговорили, на них не полагаемся. И кажется, что со всем остальным проблем не будет. Но не тут-то было: бывает всякое. Например, даты могут хранится не в виде специального типа данных, а просто в виде текста. Почему? Приведем простой пример.  Клерк ошибся и внес в бумажный документ дату постройки здания, например, 30.02.1974. В бумажном виде опечатка и опечатка, как говорят автолюбители – на скорость не влияет. А в цифровом виде ее в систему не загрузить. Выход? Храним в виде текста. А если храним дату в виде текста, то ожидайте там и 12 января 1984, и 01.янв.2993 и вообще какой угодно формат.  Таких мифов достаточно много, если у вас есть свои – поделитесь в комментариях.  Первое, что нужно – понять первоисточник данных. Если мы осознаем, что первоисточник - это бумажные документы, видим сложную и не простую судьбу данных, то бьем в колокол. Риски успешного ввода системы в промышленную эксплуатацию сильно возрастают и дальше мы действуем исходя из понимания – с промышленными данными точно будут проблемы. Если не принять мер, данные легко могут превратится в лютого врага создаваемой системы.  В идеальном мире, конечно, заказчик предоставляем разработчикам полную реплику своих промышленных данных, на которых разработчик ИС может проводить исследования и анализ. К сожалению, в реальной жизни такой вариант не всегда (а скорее даже – редко) возможен. Промышленные данные могут содержать персональные данные, чувствительную для бизнеса информацию или просто иметь такие объемы, что передать их или обработать на тестовых стендах просто не представляется возможным.  С другой стороны, заказчик тоже отлично понимает, что без тестовых данных систему протестировать и разработать не получится. И тут мы приступаем к самому сложному и интересному – получению тестовых данных. Или, что важнее – получение знаний о данных с тем, чтобы мы смогли каким-то образом получить доверенный набор тестовых данных.  Анализ и получение достоверных выборок является предметом исследования специального направления в обработке данных – Управление тестовыми данными (Test Data Management, TDM). Главная задача TDM - сформировать тестовые данные (test dataset) заданного объема так, чтобы они максимально точно отражали исходные данные (или говорят входной dataset input) – как статистически, так и все возможные значения атрибутов для максимального количества атрибутов. Надо всегда помнить, что знания о данных можно разделить на следующие категории: Структура и семантика данных. Другими словами – модель данных и как она представлена в хранилище данных. Сами данные – что именно хранится, их значения. Требования к форматно-логическому контролю и их соблюдение. Нефункциональные метрики данных – размеры записей, их структурные характеристики и т.п. Анализ структуры и семантики данных представляет особый интерес для бизнес-аналитиков и их задачи по построению бизнес-процессов. С точки зрения тестовых данных здесь самое главное - наличие полей с чувствительной информацией и правила их обработки.  Одним из методов подготовки данных является маскирование реальных данных случайными. Иногда это сделать достаточно просто – например, в случае имени или фамилии. А иногда просто заменить не получится. Причин тут может быть две: Структура идентификатора часто содержит семантические данные. Например, номер карты содержит информацию о платежной системе. ИНН содержит информацию о выданном подразделение ФСИН. Идентификатор может включать контрольную цифру. Такие цифры содержатся в номере банковского счета, СНИЛС, ИНН и т.д. Правильно спроектированные системы учитывают эти особенности. Вы наверняка замечали, что Интернет-банки оперативно могут сказать «счет не существует». Поэтому, если тестовые данные будут маскироваться или генерироваться – эти правила необходимо учитывать. Более подробно об этом можно прочитать здесь  и здесь.  Помимо структуры данных, необходимо изучить и сами хранимые данные. Обычно это самый понятный шаг, и забыть про него совсем уж сложно. Тем не менее, стоит отметить следующие  важные моменты при анализе: Возможные границы значений. Здесь важно выявить реальные границы значений, а заодно и проверить удовлетворяют ли они семантическим границам. Например, дата регистрации сделки – очевидно, что она не может быть из будущего. Тем не менее, мы встречали регистрации сделок из далекого 9999 года. Заполненность данных. Речь идет о проверке, насколько те или иные атрибуты заполнены значениями, ведь там, где ИС ожидает данные на вход, оно может оказаться пустым или некорректным. При этом стоит учитывать, что наличие жесткого ограничения в схеме данных еще не дает гарантий о заполненности данных. В колонке типа varchar стоит not null, проверка на пустую строку после удаления пробелов? Не беда. Опытный оператор всегда знает, как обойти проблему – текст «пусто», «не установлено» или же просто «---» легко позволит обойти такую проверку.  Максимальные размеры полей. Имеется в виду размер строк, файлов и т.п. Напомним, средние размеры нам здесь не помощники, стоит учитывать только максимальные. При среднем размере возвращаемого файла в 500Кб, встречаются файлы больше 1Гб.  Наличие справочников. Предположим, что на вход системы передается большой набор XML файлов, часть полей из которые содержит справочные значения в виде кодов. Надо обязательно проверить, что эти справочники еще существуют, и к ним есть доступ, а по кодам возвращаются актуальные значения.  Про модель данных и качество мы говорим чуть позже, а здесь хочется остановиться на нефункциональных метриках. Основные метрики: Количество записей по всем сущностям, справочникам и т.д. Речь идет о количестве строк в таблицах, и о количество файлов. Средний размер записи по всем сущностям. Здесь иногда полезно бывает понять, какие именно поля или части записи дают ее больший размер. Например, в случае описания земельного участка большую часть записи дают координаты участка. Максимальный размер записи. Про этот показатель многие забывают, но он является очень важным. Известен случай, когда разработчики,исходя из среднего размера записи в 10кб, взяли за основу MongoDB, у которой есть ограничение на один документ в 16Мб. Казалось бы, запас прочности – более чем три порядка. И, как вы уже догадались, нашлись документы более чем 16Мб. Максимальный размер документа оказался порядка 1Гб. Количество полей в сущностях. Да именно так – считаем, сколько полей есть в каждой сущности. Отдельный акцент на данные, которые хранятся в документах. Как правило, количество полей для одного типа сущности может меняться от документа к документу.  И тогда надо искать максимальные значения. Давайте еще раз остановимся на размерах. Средние размеры подходят для решения только одной задачи – оценить, сколько нужно оборудования для хранения данных. Ни для чего другого они не годятся. Всегда нужно узнавать максимальные размеры – только они могут служить основной для принятия проектных решений.  Даже хорошо изученные данные ничего не значат, если нам не на чем тестировать и отлаживать информационную систему. Существуют следующие крайние возможности получения данных: Отладка происходит на копии реальных промышленных данных.  Идеальный вариант, который возникает крайне редко, да и то только на несущественных для бизнеса данных.  Худший вариант – заказчик не предоставил никаких данных для отладки вообще.  Между этими полюсами есть различные варианты. Нан диаграмме показан путь от наиболее благоприятного варианта к самому плохому. Отдельно проговорим следующие моменты. Проанализировать надо любой набор данных, который передал заказчик. Это обязательно, и скорее всего, что-то новое (и неприятное) вы для себя откроете.  По нашему опыту наиболее часто встречается вариант формирование тестовых на подмножестве реальных данных заказчика. Здесь нас поджидает первый «подводный камень». Дело в том, что на малом наборе данных (небольшая выборка из входных, либо синтезированные данные) не видны все возможные случаи и комбинации значений данных, с которыми работает ИС. Есть еще и психологический момент: программисты обычно прорабатывают только положительные сценарии, а остальное перекладывают на отделы тестирования/контроля качества. Да, понятно, что эти отделы должным образом обрабатывают все сценарии, подготовят для этого данные, но дело в том, что они готовят данные, исходя из логики ИС, и не смотрят в изначальную модель и уж тем более на все возможные значения входных данных. Что, если какой-то фрагмент модели будет не покрыт тест-кейсами/сценариями? Если перепробуют не все возможные значения данных? Если, в конце концов, банально не хватит времени на все сценарии и сочетания значений данных? Здесь на помощь приходит класс инструментов под названием «Управление тестовыми знаниями» (Test DataManagement или TDM), который позволяет формировать «правильные» (лучше сказать «репрезентативные») выборки данных. До выделения таких программ в отдельный класс пользовались отдельными скриптами по профилированию данных (потом они переросли в инструменты классов DataProfiler и Data Insight). В итоге задача программ TDM была сформулирована очень просто – сформировать тестовые данные (testdataset) заданного объема так, чтобы они максимально точно отражали исходные данные (или говорят входной dataset input) – как статистически, так и все возможные значения атрибутов для максимального количества атрибутов. Приведем простой по формулировке пример, который иллюстрирует такую задачу: построить максимально репрезентативную выборку на 1% данных (т.е. объемом в 100 раз меньше реальных входных данных). С первого взгляда может показаться, что это похоже на обратную задачу классификации, где тестовый dataset является тренировочным множеством, а исходный dataset - проверяемым, а относительная энтропия (или расстояние Кульбака-Лейблера) является оценкой качества приближения. Не будем углубляться в математику этого процесса, отметим лишь интересный факт, что прямая задача является классической задачей классификации (и этим методом тренирует соответствующие нейронные сети), а обратная – для программ TDM. В такой интерпретации задач перестает быть тривиальной, т.к. чтобы учесть все возможные комбинации значений данных, объем тестовых может оказаться значительно больше исходных. И это очень справедливое замечание. Такими же инструментами можно сгенерировать тестовые данные не только для функциональных тестов, но и для замеров производительности. В итоге правильное использование TDM помогает решить следующие задачи: На ранних этапах разработки ИС позволяет создать небольшой, но репрезентативный (в сравнении с исходными данными) test dataset, с которым удобно разработчикам выполнять свои задачи. Можно синтезировать test dataset нужных объемов и проводить тесты на производительность ИС на случай длительной эксплуатации и роста данных. Позволяет сгенерировать полный dataset, который учтет все возможные значения данных, чтобы проверить функциональность ИС на них, с учетом возможности появления данных в будущем. Замаскировать чувствительные данные с помощью специальных алгоритмов, учитывая при этом наличие контрольных цифры, возможную семантику структуры и т.п. В конце затронем немаловажную тему про зону ответственности за корректную работу информационной системы с промышленными данными. Для начала рассмотрим две крайности. Если заказчик дал полный доступ к данным для анализа и составления на их основе тестового набора данных, то ответственность за корректную работу полностью ложится на разработчика. С другой стороны, если заказчик не предоставил вообще ничего, то и ожидать корректной работы на реальных данных он не может. А что, если мы идем по промежуточному сценарию? Полных данных заказчик по той или иной причине предоставить не может в силу разных причин (не готов, политика конфиденциальности и пр.)? И просит сдавать ИС на определенных данных, которые как мы прекрасно понимаем, являются лишь фрагментом, либо вообще случайно сгенерированной информацией. При этом, заказчик говорит: «Мы потом сами все данные загрузим».  Все, что мы можем посоветовать заказчику в данном случае – никогда так не делать! Очень мала вероятность, что специалисты заказчика сумеют самостоятельно загрузить весь объем промышленных данных в систему.  Хотя бы первый раз ему точно потребуется помощь разработчика. Разработчик может помочь быстрее и эффективнее загрузить данные в систему (осуществить т.н. первичную загрузку данных), оперативно исправить какие-то неучтенные и неожиданные форматы данных, коллизии в них. Оптимизировать работу системы, если первоначальная оценка данных по размеру оказалась некорректной и т.п. Разработчику контракта в ситуации, когда заказчик не предоставляет доступ к реальным данным для анализа мы можем посовать действовать в юридической плоскости. Внимательно читайте контракт и по возможности прописывайте, что вы сдаете ИС на определенных данных, предоставленных заказчиком. Укажите, что за соответствия данных несет ответственность именно заказчик. Как можно более подробно опишите характеристики данных, их природу. А если такой возможности нет (неизменяемый договор, госконтракт и пр.), то крепко задумайтесь – ведь за этим могут последовать очень серьезные разбирательства с заказчиком вплоть до судебных тяжб. Еще один совет заказчику. Все серьезные контракты включают гарантийный обязательства со стороны разработчика в течение нескольких месяцев или лет. Обязательно вводите ИС в эксплуатацию как можно раньше – пока исполнитель еще помнит систему, хорошо в ней разбирается. Реальные данные часто заставляют очень сильно подумать, что с ними делать в уже готовой системе – и чем больше у вас поддержки со стороны разработчика, тем всем будет лучше. Стоит помнить, что именно при загрузке полных данных и работе с ними в ИС могут возникнуть проблемы и ошибки, которые не были учтены из-за отсутствия реальных входных данных. И чем больше их объем и они (данные) более разнообразны (иногда говорят широки) – тем выше вероятность этого. И получится ситуация, с которой мы начали эту статью – Информационная система полностью работает (на тестовых данных) и при этом не работает (на реальных данных). Леонид Выговский Сергей Кузнецов