Анализ данных - это ранний этап разработки, когда вы изучаете предметную область и определяете требования для их преобразования в программное обеспечение. Это формальное определение может заставить подумать, что анализ данных это деятельность, которую стоит оставить на системных аналитиков. А программисты должны сосредоточиться на написании кода, который те спроектируют. Если мы строго последуем парадигме разработки, то возможно, это будет правильная идея. Опытные программисты становятся архитекторами, а лучшие архитекторы становятся бизнес-аналитиками и отвечают за требования к данным и выдают программистам четко определенное задание для написания кода. Но это не совсем так, так как данные это ядро любой деятельности программистов. Что бы вы не делали в своей программе, вы либо передаете, либо изменяете данные. Бизнес-аналитик изучает требования в широком виде, архитектор в чуть более узком разрезе, так что, когда проблема приходит к вам, кажется, что все, что вам надо сделать, это применить нужные алгоритмы и начать взаимодействовать с имеющимися данными.
Это не так.
Неважно, на каком этапе вы начинаете работать с данными, они всегда остаются главной заботой в хорошо спроектированном приложении. Если вы внимательно посмотрите, как бизнес-аналитик извлекает требования из запросов клиентов, то поймете, что данные играют фундаментальную роль. Аналитик создает так называемые диаграммы потоков данных, где указаны источники данных, и обозначен поток информации. Определив, какие данные будут частью системы, архитектор начнет формировать источники данных с точки зрения баз данных, протоколов обмена данными и форматов файлов. После этого задачу можно передавать программисту. Но процесс на этом не заканчивается, потому что вы (программист) даже после подобной тщательной обработки данных должны проанализировать их, чтобы выполнить задачу оптимальным способом. В основе вашей работы лежит идея Никлауса Вирта, создателя нескольких языков программирования. "Алгоритмы + Структуры данных = Программы". Алгоритм никогда не существует отдельно, делая что-то сам по себе. Каждый алгоритм обязательно взаимодействует как минимум с какой-то частью данных.
Таким образом, раз алгоритмы не функционируют в вакууме, вы должны анализировать и данные, которые кто-то передал вам для разработки, и данные, которые надо воплотить в коде. Вот простой пример. Вы пишите программу для поиска книг в библиотеки. Согласно вашей спецификации пользователь может выбрать книги по сочетанию жанра, автора, названию, издателю, году издания и числу страниц. Конечная цель вашего модуля - создать корректный запрос SQL для отправки в базе данных. Основываясь на этих требованиях, вы можете выбирать варианты. Можно проверять каждый параметр по очереди, используя оператор "switch" или несколько последовательных "if". Можно создать массив параметров и проверять, есть ли в нем каждый параметр. Можно создать (или использовать) абстрактный объект для контроля данных, от которого унаследовать конкретные параметры и связать их с механизмом управления событиями. Если в требованиях есть настройка производительности запроса через проверку параметров в определенном порядке, то вы можете рассмотреть применение дерева компонентов для построения SQL-запроса. Как видно, выбор алгоритма зависит от данных, которые вы решите использовать или создать. Подобные решения часто отделяют эффективные алгоритмы от провальных. Однако, эффективность здесь не единственная проблема. Вы можете создать десяток переменных и сделать их максимально эффективными. Но такой код не будет легко поддерживаемым. Возможно, выбор подходящего контейнера для хранения всех ваших переменных поможет сохранить ту же скорость алгоритма и вдобавок сделает код более понятным для ваших коллег, когда они вернутся к нему в следующем году. Более того, хорошо выбранная структура данных позволит им легко расширить функциональность вашего кода без переписывания уже имеющихся частей. В конечном счете ваш выбор данных определяет, как долго просуществует ваш код.
Еще один пример для размышлений. Предположим, у вас задача найти все слова в словаре с тремя и более анаграммами. При этом анаграмма должна быть другим словом в этом же словаре. Если вы будете думать об этой задаче, как о задаче на вычисление, то вы придете к бесконечным вычислениям в попытке вычислить все комбинации анаграмм для каждого слова и сравнить их со всеми остальными словами в словаре. Однако, анализируя исходные данные, вы можете заметить, что каждое слово можно представить как запись с самим словом и сортированным массивом из его букв в виде ID. С этим знанием нахождение анаграмм превращается в сортировку этого массива и нахождение слов с аналогичным ID. Прямой алгоритм может потребовать несколько дней на выполнение, тогда как более хитрый выполняется за несколько секунд. Вспомните этот пример, когда в следующий раз вы столкнетесь с неразрешимой проблемой.
Следующее: Командные навыки. Как управлять временем разработки