Советы о том, как быть вежливым с собой и своими коллегами при разработке кода для продуктов данных

Продукты данных — это программные приложения.

Как специалисты по данным, мы создаем продукты данных, то есть продукты, которые используют данные для решения реальных проблем. Продукты данных могут принимать самые разные формы и формы в зависимости от решаемой проблемы и включать в себя статические отчеты, информационные панели в реальном времени, интерактивные веб-приложения, веб-сервисы на основе машинного обучения и т. д. Что объединяет эти типы продуктов, так это то, что их создание требует написания код, напр. на Python, R, Julia и/или диалекте SQL. Из-за этого большинство продуктов данных, по сути, являются программными приложениями, хотя и различной сложности.

Сложность кода данного продукта данных зависит не только от характера этого продукта, но и от стадии его разработки. CRISP-DM — известный фреймворк, описывающий, что происходит на разных этапах проектов Data Science. CRISP-DM включает шесть основных этапов: (i) понимание бизнеса, (ii) понимание данных, (iii) подготовка данных, (iv) моделирование, (v) оценка и (vi) развертывание. По мере продвижения проекта требования к качеству и надежности базовой кодовой базы обычно возрастают. Более того, проекты в области науки о данных часто требуют хорошо скоординированных усилий самых разных участников, таких как заинтересованные стороны бизнеса, другие специалисты по данным, инженеры по данным, специалисты по ИТ-операциям и т. д. Таким образом, чтобы сделать весь процесс максимально плавным и эффективным и свести к минимуму связанные с этим бизнес-риски, хороший Data Scientist должен (среди многого другого) уметь писать хороший код.

Но что именно делает хороший код? Пожалуй, наиболее лаконичный ответ на этот вопрос можно найти в следующей иллюстрации, открывающей популярную книгу Чистый код Р. К. Мартина:

Чтобы уменьшить WTF в минуту в коде Data Science, мы можем следовать некоторым передовым практикам, разработанным за десятилетия в области Разработки программного обеспечения. В моей работе в качестве Data Scientist и консультанта я обнаружил, что следующие передовые практики и принципы особенно актуальны и полезны:

  • присоединение к проекту новых членов команды занимает минимум времени и средств;
  • код написан по модульному принципу, контролируется версиями и модульно тестируется;
  • приложение полностью настраивается и не содержит жестко закодированных значений, управляющих его выполнением;
  • приложение переносимо между средами выполнения;
  • приложение масштабируется без изменения инструментов, архитектуры или методов разработки;
  • ни один код не развертывается в рабочей среде без экспертной проверки;
  • существует инфраструктура мониторинга, позволяющая отслеживать и понимать, как приложение ведет себя в продакшене.

Ниже представлены краткие комментарии к этим передовым практикам в контексте науки о данных, а также некоторые рекомендации по их реализации. Эта статья может представлять особый интерес для специалистов по данным на ранних этапах их карьеры. Тем не менее, я считаю, что опытные профессионалы и менеджеры по науке о данных также могут найти здесь полезную информацию.

Написать идеальный фрагмент кода за один раз почти невозможно, и это нормально.

Четко сформулированные требования в проектах Data Science встречаются редко. Например, заинтересованные стороны бизнеса могут захотеть спрогнозировать определенное количество с помощью модели машинного обучения, но они редко смогут что-либо сказать о приемлемой неопределенности для этого прогноза. Многие другие неизвестные могут еще больше затруднить и замедлить проекты Data Science, например:

  • Можно ли решить проблему с помощью данных?
  • Какие данные помогут решить эту проблему?
  • Могут ли специалисты по данным получить доступ к этим данным?
  • Имеющиеся данные достаточного качества и содержат ли они достаточно сильный «сигнал»?
  • Сколько будет стоить настроить и поддерживать фид с необходимыми данными в будущем?
  • Существуют ли какие-либо нормативные ограничения для использования определенных типов данных?

В результате проекты Data Science часто требуют много времени и ресурсов, становятся очень итеративными (см. CRISP-DM, упомянутый выше) и могут полностью потерпеть неудачу. Учитывая очень рискованный характер проектов Data Science, особенно на их ранних стадиях, нет особого смысла писать код промышленного уровня с первого дня. Вместо этого полезно подходить к разработке кода более прагматично, подобно тому, как это делается в проекты по разработке программного обеспечения.

Один из подходов к разработке программного обеспечения, который я нахожу особенно актуальным, предлагает рассматривать эволюцию кодовой базы приложения с точки зрения следующих этапов: заставьте это работать, сделайте это правильно, сделайте это быстро. В контексте Data Science эти этапы можно интерпретировать следующим образом:

  • Заставьте это работать: разработайте прототип решения для имеющейся бизнес-задачи, чтобы проанализировать это решение, извлечь из него уроки и решить, оправданы ли дальнейшая разработка и развертывание. Например, это может включать быстрое построение прогностической модели на ограниченной выборке данных с использованием гиперпараметров по умолчанию. Код на этом этапе не обязательно должен быть «красивым».
  • Сделайте это правильно: переход к этому этапу будет оправдан, если работа по разработке прототипа показала многообещающий результат и было принято решение о разработке и внедрении полноценного информационного продукта. Код прототипа теперь выбрасывается, а новый код производственного уровня пишется в соответствии с соответствующими требованиями и рекомендациями.
  • Сделайте это быстро: этот этап, скорее всего, будет достигнут после запуска развернутого приложения в рабочей среде в течение некоторого времени. Наблюдение за поведением продукта данных «в дикой природе» часто выявляет все виды вычислительной неэффективности. Хотя сам продукт может приносить ожидаемую ценность для бизнеса, такая неэффективность может снизить общую рентабельность инвестиций в проект из-за ненужных затрат (например, из-за вычислительных затрат на облачной платформе). Когда это происходит, может потребоваться вернуться к кодовой базе приложения и попытаться ее оптимизировать.

Давайте теперь углубимся в каждую из этих идей и посмотрим, как меняются требования к качеству кода по мере развития проекта.

I. Как заставить это работать

Сначала создайте прототип

Наука о данных, как и любая другая наука, занимается выяснением вещей, поиском того, что работает, а что нет для данной проблемы. Вот почему в начале проекта важно начать с малого и сначала создать прототип. По данным Википедии,

«Прототип — это ранний образец, модель или выпуск продукта, созданный для проверки концепции или процесса».

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

Фактическая форма, которую прототипы принимают в проектах Data Science, зависит от решаемой проблемы. Примеры включают, но не ограничиваются:

  • часть исследовательского анализа, демонстрирующая ценность имеющихся данных;
  • быстрая и грязная прогностическая модель, показатели производительности которой помогают понять, можно ли решить проблему с помощью данных;
  • веб-приложение, работающее локально на статическом наборе данных и созданное для сбора ранних отзывов конечных пользователей.

Код прототипа — это одноразовый код

Код прототипа решения следует рассматривать как одноразовый код. Как специалист по данным, ведущий проект, или как руководитель проекта, вы должны очень четко объяснить это своим заинтересованным сторонам. Цитируя одну из моих любимых книг Программист-прагматик (Hunt & Hunt 2019),

«Легко ввести в заблуждение кажущаяся завершенность продемонстрированного прототипа, и спонсоры проекта или руководство могут настаивать на развертывании прототипа (или его потомка), если вы не устанавливаете правильных ожиданий. Напомните им, что вы можете построить отличный прототип нового автомобиля из пробкового дерева и изоленты, но вы не будете пытаться вести его в час-пик!»

Прототипы информационных продуктов не на самом деле должны быть написаны в виде кода. Чтобы двигаться быстрее, прототип можно (а иногда, возможно, даже нужно) построить с использованием инструментов Data Science с низким или нулевым кодом. Однако, когда прототип записывается как код, следует помнить о некоторых правилах и запретах.

Что нормально делать при создании прототипа в виде кода

Поскольку код прототипа одноразовый, он:

  • не должен быть «красивым» или оптимизированным для скорости вычислений, так как скорость разработки на данном этапе гораздо важнее;
  • не должен быть документирован на том же уровне, что и код производственного уровня (однако должно быть достаточно комментариев и/или заметок на основе Markdown, чтобы понять, что делает код, и обеспечить его воспроизводимость);
  • не требует контроля версий (хотя настройка контроля версий в начале любого проекта — всегда хорошая идея);
  • допустимо иметь жестко запрограммированные значения (но не конфиденциальные, такие как пароли, ключи API и т. д.);
  • могут быть записаны и сохранены в Jupyter Notebook или аналогичном носителе (например, R Markdown Notebook) вместо того, чтобы быть организованы в библиотеку функций и/или набор готовых сценариев.

Что недопустимо делать при создании прототипа в виде кода

Хотя код прототипа является одноразовым, всегда есть шанс, что проект перейдет к следующему этапу, который включает разработку полноценного информационного продукта. Таким образом, всегда следует прилагать все усилия для написания кода прототипа, максимально похожего на код промышленного уровня. Это может существенно ускорить последующий процесс разработки. Как минимум, вот что недопустимо делать при создании прототипа в виде кода (дальнейшее обсуждение см. ниже):

  • использование загадочных или сокращенных имен переменных и функций;
  • смешение стилей кода (например, случайное использование camelCase и snake_case для именования переменных и функций в таких языках, как Python или R, или использование имен команд в верхнем и нижнем регистре в SQL);
  • вообще не использовать комментарии в коде;
  • наличие конфиденциальных значений (паролей, ключей API и т. д.), открытых в коде;
  • не хранить записные книжки или сценарии с кодом прототипа для дальнейшего использования.

II. Делая это правильно

Если этап прототипирования показал положительные результаты, проект может перейти к разработке готового к производству решения. Процесс предоставления продукта данных пользователям-людям или другим системам называется развертыванием. Развертывание продуктов обработки данных часто влечет за собой множество жестких требований, включая, но не ограничиваясь:

  • специфичные для проекта SLA (например, достаточно низкое время отклика от API, который обслуживает предсказания моделей, высокая доступность и параллелизм для веб-приложений и т. д.);
  • инфраструктура для полностью автоматизированного и масштабируемого развертывания и запуска приложения (DevOps/MLOps);
  • инфраструктура для надежной доставки входных данных высокого качества, когда и если это требуется приложению;
  • инфраструктура для мониторинга операционных (например, загрузка ЦП) и связанных с продуктом показателей (например, точность прогнозов);
  • постоянная оперативная поддержка критически важных для бизнеса приложений и т.д.

Многие из этих требований должны быть выполнены командами Data Engineering, MLOps и DevOps. Более того, по мере развития проекта роль этих инженерных групп становится все более важной. Тем не менее, специалисты по данным также должны «исправить ситуацию» со своей стороны. Давайте посмотрим, что это означает с точки зрения качества кода.

Используйте описательные имена переменных

Можете ли вы предположить, что означают x, y и z в приведенном ниже фрагменте кода?

z = x / y^2

Не зная контекста, к которому применяется этот код, практически невозможно сказать, что представляет собой каждая из трех переменных. Но что, если вместо этого мы перепишем эту строку кода следующим образом:

body_mass_index = body_mass / body_height^2

Теперь совершенно ясно, что делает код — он вычисляет индекс массы тела путем деления массы тела на рост в квадрате. Более того, этот код полностью самодокументируемый — нет необходимости в каких-либо дополнительных комментариях относительно того, что он вычисляет.

Очень важно понимать, что производственный код пишется не для нас самих, а главным образом для других людей — тех, кто в какой-то момент будет его просматривать, вносить в него свой вклад или поддерживать его в будущем. Использование описательных имендля переменных, функций и других объектов поможет значительно сократить когнитивные усилия, необходимые для понимания что делает код и сделает код более удобным для сопровождения.

Используйте единый стиль кодирования

Когнитивные усилия, необходимые для чтения и понимания фрагмента кода, могут быть дополнительно уменьшены, если этот код отформатирован в соответствии со стандартом. Все основные языки программирования имеют свои официальные руководства по стилю. Не имеет большого значения, какой именно стиль выберет команда разработчиков, потому что в конечном итоге все зависит от согласованности. Тем не менее, это действительно помогает, если команда выбирает один стиль и придерживается его, и тогда каждый член команды становится коллективной ответственностью за обеспечение использования принятого стиля. Примеры стилей кода, обычно используемых для языков Data Science, включают PEP8 (Python), tidyverse (R) и Руководство по стилю SQL Саймона Холивелла (SQL).

Чтобы писать стилистически выдержанный код, не задумываясь о правилах выбранного стиля, используйте интегрированную среду разработки (IDE), например VSCode, PyCharm или RStudio. Популярные Jupyter Notebooks могут быть удобны для создания прототипов, однако они не предназначеныдля написания кода производственного уровня, поскольку им не хватает большинства функций профессиональной IDE. предложения (например, подсветка кода и автоматическое форматирование, проверка типов в реальном времени, переход к определениям функций и классов, управление зависимостями, интеграция с системами контроля версий и т. д.). Код, выполняемый из Jupyter Notebook, также подвержен многим проблемам безопасности и всякого рода непредсказуемому поведению.

Если по какой-то причине ваша любимая IDE не может автоматически форматировать код в соответствии с заданным стилем, используйте для этого специальную библиотеку, например pylint или flake8 для Python, lintr или styler для R и sqlfluff. для SQL.

Пишите модульный код

Модульный код — это код, разбитый на небольшие независимые части (например, функции), каждая из которых выполняет одно действие и только одно действие. Такая организация кода значительно упрощает сопровождение, отладку, тестирование, обмен с другими людьми и, в конечном счете, помогает быстрее писать новые программы.

При проектировании и написании функций придерживайтесь следующих рекомендаций:

  • Будьте краткими. Если вы обнаружите, что ваша функция содержит десятки строк кода, подумайте о том, чтобы разбить этот код еще больше.
  • Сделайте код легким для чтения и понимания. В дополнение к использованию описательных имен этого можно достичь, избегая узкоспециализированных конструкций языка программирования, используемого в проекте (например, сложных списков, чрезмерно длинных цепочек методов или декораторов в Python), если только они не ускоряют код значительно.
  • Сведите к минимуму количество аргументов функции. Это не жесткое правило, и есть исключения, но если функция, которую вы пишете, имеет более 3–5 аргументов, вероятно, она делает слишком много действий, поэтому подумайте о том, чтобы еще больше разбить ее код.

В Интернете полно примеров того, как можно модульно разделить код Python. Для R есть отличная книга в свободном доступе R Packages. Много полезных рекомендаций такого рода для специалистов по данным также можно найти в блоге Laszlo Sragner.

Никогда не жестко кодируйте конфиденциальную информацию

Чтобы быть безопасным, производственный код должен никогдараскрывать какую-либо конфиденциальную информацию в виде жестко запрограммированных констант. Примеры конфиденциальной информации включают дескрипторы ресурсов для баз данных, пароли пользователей, учетные данные для сторонних сервисов (например, облачных сервисов или платформ социальных сетей) и т. д. Хорошей лакмусовой бумажкой того, правильно ли ваш код учитывает такие переменные, является то, может ли он быть с открытым исходным кодом в любой момент без ущерба для каких-либо учетных данных. Методология Twelve-Factor App рекомендует хранить конфиденциальную информацию в переменных среды. Один из удобных и безопасных способов работы с такими переменными заключается в их хранении в виде пар ключ-значение в специальном .env файле, который никогда не передается в удаленный репозиторий кода приложения. Библиотеки для чтения таких файлов и их содержимого существуют как в Python, так и в R.

Явно объявить все зависимости в файле манифеста

Часто можно увидеть продукты данных, кодовая база которых зависит от десятков специализированных библиотек. Код может хорошо работать на локальной машине разработчика, где все эти зависимости установлены и работают корректно. Однако перенос приложений в рабочие среды часто приводит к поломке, если зависимости кода не управляются должным образом. Чтобы избежать таких проблем, необходимо полностью и точно объявить все зависимости через манифест объявления зависимостей. Этот манифест принимает разные формы в зависимости от языка, например. файл requirements.txt в приложениях Python или файл DESCRIPTION в пакетах R.

Кроме того, рекомендуется использовать инструмент изоляции зависимостей во время выполнения приложения, чтобы избежать помех со стороны хост-системы. Обычно используемые примеры таких инструментов в Python: venv, virtualenv и conda окружения. Аналогичный инструмент — renv — существует и для R.

Используйте единый репозиторий кода с контролем версий

Код продукта данных, предназначенного для производства, должен контролироваться версиями(VC) ихраниться в удаленном репозитории, доступном для других участников проекта. Git, пожалуй, наиболее часто используемая система VC, и в настоящее время ожидается, что специалисты по данным, разрабатывающие готовые к производству продукты данных, должны быть знакомы, по крайней мере, с ее основными принципами. Этим основам, а также более продвинутым методам можно научиться из многочисленных ресурсов, таких как книга Pro Git, Happy Git and GitHub for the UserR или Oh Shit, Git! ?!"" Веб-сайт. Наиболее часто используемые платформы для удаленного управления репозиторием кода — «GitHub, Bitbucket и GitLab.

VC важен по ряду причин, включая следующие:

  • это позволяет сотрудничать между участниками проекта;
  • в случае поломки позволяет откатиться на предыдущую рабочую версию приложения;
  • обеспечивает автоматизированную непрерывную интеграцию и развертывание;
  • он обеспечивает полную прозрачность, что может быть особенно важно для целей аудита в регулируемых отраслях.

Кодовая база данного приложения должна храниться в одном репозитории, и разные приложения не должны использовать одни и те же фрагменты кода. Если вы обнаружите, что повторно используете один и тот же код в разных приложениях или проектах, пришло время выделить этот многократно используемый код в отдельную библиотекус собственной кодовой базой.

Используйте файл конфигурации для хранения неконфиденциальных параметров приложения.

Согласно методологии Двенадцатифакторное приложение,

Конфигурация приложения — это все, что может различаться между «развертываниями (постановка, производство, среда разработки и т. д.)».

Это включает в себя все виды учетных данных, URI ресурсов, пароли, а также переменные, относящиеся к науке о данных, такие как гиперпараметры модели, значения для вменения отсутствующих наблюдений, имена входных и выходных наборов данных и т. д.

Почти гарантировано, что продукту данных, предназначенному для производства, потребуется конфигурация. Одним из примеров того, почему это может быть так, является то, что запуск приложения в среде разработки не требует такой большой вычислительной мощности, как в рабочей среде. Вместо жесткого кодирования соответствующих значений вычислительных ресурсов (например, параметров экземпляра AWS EC2) в основной код приложения гораздо разумнее рассматривать эти значения как параметры конфигурации.

Параметры конфига можно хранить множеством разных способов. Методология Twelve-Factor App рекомендует хранить их в переменных окружения. Однако некоторые приложения могут иметь слишком много параметров, чтобы их можно было отслеживать в виде переменных среды. В таких случаях более разумно поместить неконфиденциальные параметры в специальный файл конфигурации с контролируемой версией и использовать переменные среды для хранения только конфиденциальных параметров.

Наиболее распространенными форматами файлов конфигурации являются JSON и YAML. Файлы YAML удобочитаемы и поэтому часто предпочтительнее. Файлы конфигурации YAML можно легко читать и анализировать как в Python (например, с использованием библиотек anyconfig или pyyaml), так и в R (например, с использованием пакетов yaml или config).

Оснастите свое приложение механизмом ведения журнала

Журналы — это поток упорядоченных по времени событий, собранных из выходных потоков всех активных процессов и вспомогательных служб приложения. Эти события обычно записываются в текстовый файл на диске сервера, по одному событию в строке. Они генерируются непрерывно, пока работает приложение. Цель журналов — обеспечить видимость поведения работающего приложения. В результате журналы чрезвычайно полезны для обнаружения сбоев и ошибок, оповещения, расчета времени, затрачиваемого на выполнение различных задач, и т. д. Как и в случае с другими программными приложениями, специалистам по данным настоятельно рекомендуется внедрять механизмы журналирования в продукты данных, которые должны быть развернуты в производство. Для этого есть простые в использовании библиотеки (например, logging в Python и log4r в R).

Следует отметить, что приложения на основе машинного обучения нуждаются в дополнительном мониторингеиз-за недетерминированного характерасоответствующих алгоритмов. Примеры таких дополнительных метрик включают показатели качества входных и выходных данных, дрейф данных, точность прогнозов и другие количественные показатели, зависящие от приложения. Это, в свою очередь, требует от команды проекта дополнительных затрат времени и усилий на создание (часто сложной) инфраструктуры для эксплуатации и поддержки развернутых моделей. К сожалению, на данный момент не существует стандартных подходов к построению такой инфраструктуры — команде проекта предстоит выбрать то, что необходимо для их конкретного информационного продукта, и решить, как лучше всего реализовать соответствующие механизмы мониторинга. В некоторых случаях можно также выбрать коммерческое решение для мониторинга, например, предлагаемое AWS SageMaker, Microsoft Azure ML и т. д.

Проверьте свой код на корректность

Ни один код не должен запускаться в производство без подтверждения того, что он делает то, что должен делать. Лучший способ убедиться в этом — написать набор тестов для конкретных вариантов использования, которые затем можно будет автоматически запускать в критические моменты времени (например, при каждом pull request). Этот вид тестирования часто называют модульным тестированием», где модульное тестирование относится к низкоуровневым тестовым примерам, написанным на том же языке, что и производственный код, которые напрямую обращаются к его объекты и члены(Hunt & Hunt 2019). Модульные тесты обычно пишутся для отдельных функций, но также могут охватывать классы и модули более высокого уровня.

Существует два основных подхода к написанию автоматизированных тестов. Один из них — это когда сначала пишется функция или какой-то другой кусок функционала, а потом к ней пишутся тесты. Другой подход известен как разработка через тестирование и подразумевает, что сначала пишутся тесты в соответствии с ожидаемым поведением модуля функциональности, и только затем кодируется сам модуль. У каждого из этих методов есть свои плюсы и минусы, и какой из них лучше — это своего рода философская дискуссия. На практике не имеет большого значения, какой метод использовать, если команда придерживается последовательного подхода к работе.

Все основные языки программирования имеют специальные библиотеки для создания автоматизированных тестов кода. Примеры включают unittest и pytest для Python и testthat для R.

Важным понятием в модульном тестировании является покрытие кода — процент кода, покрываемый автоматическими тестами. Эта метрика недолжна быть равна 100 % (более того, на практике часто сложно достичь высокого покрытия кода, особенно в больших проектах). Некоторые из общих рекомендаций в этом отношении сводятся к следующему:

  • напишите тест для каждой ситуации, когда вы испытываете искушение ввести что-то в оператор print, чтобы увидеть, работает ли код так, как ожидалось;
  • избегайте тестирования простого кода, в котором вы уверены, что он будет работать;
  • всегда пишите тест, когда обнаруживаете ошибку.

Покрытие кода может быть автоматически рассчитано с помощью различных инструментов, таких как библиотека coverage в Python или covr в R. Также существуют специализированные коммерческие платформы, которые могут рассчитывать покрытие кода, отслеживать его для каждого проекта во времени и визуализировать результаты. . Хороший пример — Кодеков.

Как минимум, модульные тесты должны запускаться локально на компьютере разработчика и предоставляться в репозитории проекта, чтобы другие участники проекта могли их повторно запускать. Однако правильный способ сделать это в настоящее время — полностью автоматически запускать тесты на выделенном сервере автоматизации (например, Jenkins) или с использованием других инструментов непрерывной интеграции (например, GitHub Actions, GitLab CI, CircleCI). ", и т. д.).

Убедитесь, что хотя бы один человек рецензирует ваш код.

Фрагмент кода вполне может быть без ошибок и чисто отформатирован, но почти всегда есть определенные аспекты, которые можно улучшить еще больше. Например, автор кода может использовать определенные языковые конструкции, которые затрудняют прочтение этого кода другими людьми и понимание того, что он делает (например, длинные цепочки методов, запутанные обработки списков и т. д.). Во многих случаях имеет смысл упростить эти конструкции ради удобочитаемости. Выявление частей кода, которые можно улучшить, требует «свежего взгляда», и рецензент может помочь в этом. Рецензентом обычно является кто-то из команды, который знаком с проектом или непосредственно участвует в нем.

Экспертная оценка также важна при внесении изменений в кодовую базу, которые могут существенно повлиять на конечных пользователей.

В целом, цель рецензирования состоит в том, чтобы упростить код, сделать очевидные улучшения с точки зрения скорости его выполнения, а также выявить функциональные ошибки (т. делает).

Лучший способ организовать проверку кода и автоматически отслеживать ее ход — назначить рецензента по запросу на включение с помощью соответствующей функциональности платформы управления удаленным репозиторием. Все основные платформы VC предлагают такую ​​​​функциональность.

Документируйте вещи, религиозно

Производственный код должен документироваться. Без документации будет очень сложно поддерживать код в долгосрочной перспективе, эффективно распространять его и быстро и без проблем интегрировать новых членов команды. Следующие рекомендации помогут в создании хорошо документированной кодовой базы:

  • При написании классов, методов или чистых функций используйте строки документациидля Python или аналогичный специфичный для языка механизм, если вы работаете с другими языками. Использование этих стандартных механизмов очень полезно, потому что: (i) они автоматически создают файлы справки, которые можно вызвать из консоли, чтобы понять, что делает данный класс или функция и какие аргументы она ожидает; (ii) они позволяют использовать специальные библиотеки (например, sphinx, pydoc или pdoc для Python, roxygen2 в сочетании с pkgdown для R) для создания готовой к использованию в Интернете документации (т. е. в виде HTML-файлы), которыми можно легко поделиться с другими людьми внутри организации или публично.
  • При написании скриптов (i) добавьте комментарий вверху и кратко объясните цель скрипта; (ii) предоставить дополнительные комментариив местах, которые иначе было бы сложно понять.
  • В удаленном репозитории проекта предоставьте файл README, в котором объясняются все важные сведения об этом репозитории (включая описание его структуры, имя сопровождающего(их), инструкции по установке и, если применимо, ссылки на внешнюю вспомогательную документацию для всего проекта).

III. Делаем это быстро

Развернутое приложение может выявить различные неэффективные вычисления и узкие места. Однако, прежде чем броситься в рефакторинг кода, полезно вспомнить следующие правила оптимизации»:

  1. Первое правило оптимизации: не
  2. Второе правило оптимизации: пока не…
  3. Профиль перед оптимизацией

Другими словами, всегда полезно убедиться, что проблема реальна, прежде чем тратить свое драгоценное время на ее устранение. Это делается с помощью «профилирования» (согласно Правилу 3 выше), которое в проектах Data Science обычно означает две вещи:

  1. измерение производительности интересующего кода;
  2. рассмотрение запланированной работы по оптимизации в контексте окупаемости всего проекта и создаваемой им ценности для бизнеса.

Тот факт, что фрагмент кода теоретически может быть ускорен, не означает, что так и должно быть. Прирост производительности может оказаться слишком маленьким, чтобы требовать дополнительной работы. И даже если ожидаемый прирост производительности потенциально значителен, команда проекта должна оценить, оправдано ли внесение предлагаемых изменений с экономической точки зрения. Предлагаемая работа по оптимизации будет иметь смысл только в том случае, если ожидаемая рентабельность всего проекта будет положительной и достаточно большой. Таким образом, окончательное решение должны принимать все участники проекта — теперь не только Data Scientist может сделать вывод о том, что работа по оптимизации оправдана.

Заключение

Информационные продукты — это, по сути, программные приложения различной сложности. Тем не менее, специалисты по данным, которые разрабатывают такие приложения, обычно не имеют формального образования в области разработки программного обеспечения. К счастью, овладеть основными принципами разработки программного обеспечения не так уж и сложно. В этой статье представлен краткий обзор таких принципов в контексте науки о данных, и мы надеемся, что она поможет специалистам по данным в написании более качественного кода для своих проектов.

Вам также может понравиться: