- Оригинальный адрес:How to write a production-level code in Data Science?
- Оригинальный автор:Venkatesh Pappakrishnan, Ph.D.
- Перевод с:Программа перевода самородков
- Постоянная ссылка на эту статью:GitHub.com/rare earth/gold-no…
- Переводчик:sisibeloved
- Корректор:AceLeeWinnie, yqian1991
Способность писать код производственного уровня является одним из желанных навыков специалиста по данным, независимо от того, указано ли это явно в описании работы или нет. Это может быть не слишком сложно для специалиста по данным, ставшего инженером-программистом, который может уже иметь большой опыт разработки и развертывания производственного кода.
Этот пост предназначен для тех, кто плохо знаком с написанием кода производственного уровня и заинтересован в его изучении, например, для недавних выпускников колледжей или специалистов, работающих в области науки о данных (и планирующих трансформацию). Для них написание производственного кода может показаться сложной задачей.
Я расскажу о нескольких советах по написанию кода производственного уровня, поэтому, пожалуйста, попрактикуйтесь, и эта статья не требует каких-либо знаний в области обработки данных.
1. Сохраняйте модульность
Это важный навык, которым должен овладеть любой инженер-программист. Его основная идея состоит в том, чтобы разделить огромные блоки кода на небольшие независимые сегменты кода (функции) на основе их функций. Он состоит из двух частей.
(i) Разбейте код на небольшие части, каждая из которых выполняет определенную функцию (может содержать подфункции).
(ii) Объедините эти функции в модули (или файлы Python) в зависимости от использования. Это также помогает поддерживать порядок и поддерживать код.
Начните с разбиения огромного блока кода на множество простых функций, каждая из которых содержит ввод и вывод в определенном формате. Как упоминалось выше, каждая функция должна реализовывать одну ответственность, такую какУдалите выбросы из данных, замените ошибочные значения, оцените модель, рассчитайте стандартное отклонение (RMSE, также переводится как среднеквадратичное отклонение).и Т. Д. Старайтесь разбивать эти функции на функции, которые выполняют подзадачи в более мелких единицах, пока вы не сможете их разбить.
функция низкого уровня — Базовые функции, которые не подлежат дальнейшей декомпозиции. Например, вычисление стандартного отклонения (RMSE) или стандартной оценки (Z-оценка) данных. Некоторые из этих функций можно широко использовать для реализации алгоритмов или обучения моделей машинного обучения.
функция среднего слоя- Используйте одну или несколько функций низкого уровня и/или других функций среднего уровня для реализации функциональности. Например,Удалите выбросы в ваших данныхфункция будет использоватьРассчитать стандартную оценкуфункция удаления выбросов и сохранения только данных в пределах определенной границы;ошибкафункция будет использоватьРассчитать стандартное отклонениефункция для получения стандартного отклонения.
верхняя функция- Используйте одну или несколько функций среднего уровня и функций низкого уровня для реализации функций. Например, функция обучения модели использует несколько функций, таких как функция случайного получения выборочных данных, функция оценки модели и функция матрицы.
Наконец, разделите все повторно используемые функции низкого и среднего уровня в один файл Python (который можно импортировать как модули), а все остальные выделенные функции низкого и среднего уровня — в другой файл Python. Все высокоуровневые функции должны быть сгруппированы в один файл Python. Этот файл Python описывает каждый шаг разработки алгоритма — от объединения данных из нескольких источников до построения моделей машинного обучения.
Хотя нет необходимости придерживаться правил, я все же рекомендую вам следовать этому процессу, шаг за шагом, пока вы не выработаете свой собственный стиль кодирования.
2. Инструменты ведения журнала и мониторинга
Инструмент регистрации и мониторинга (LI) похож на черный ящик в самолете, который записывает все, что происходит в кабине. Основная цель LI — записывать достоверную информацию о времени выполнения кода, чтобы разработчики могли отлаживать и улучшать производительность кода (например, сокращая время выполнения) при возникновении ошибок.
Так в чем же разница между инструментами ведения журнала и мониторинга?
(i) протоколирование- Записывать в журнал только важную информацию, такую как критические сбои во время выполнения, и структурированные данные, такие как промежуточные результаты, которые сам код будет использовать позже. Во время разработки и тестирования доступны различные уровни журналов, такие как отладка, информация, предупреждение и ошибка. Однако во время производства этого следует избегать любой ценой.
Логирование должно быть как можно более кратким и содержать только ту информацию, которая требует внимания сопровождающего и требует немедленной обработки.
(ii) инструмент мониторинга- Запишите любую другую информацию, отсутствующую в журнале, которая поможет нам проверить шаги, которые выполняет код, и, при необходимости, поможет улучшить производительность. Чем больше данных, тем больше информации может дать инструмент мониторинга.
Проверять шаги выполнения кода — мы должны записывать такую информацию, как имя задачи, промежуточные результаты, пройденные шаги и т. д. Это поможет нам проверить результаты и подтвердить, что алгоритм следует ожидаемым шагам. Недопустимые результаты или странные алгоритмы выполнения могут не вызывать достаточно серьезных ошибок, чтобы их можно было зарегистрировать. Поэтому запись этой информации обязательна.
Повышение производительности —— Мы должны регистрировать время, используемое каждой задачей/подзадачей, и память, занимаемую каждой переменной. Это поможет нам улучшить код, внести необходимые изменения, оптимизировать код для более быстрой работы и ограничить потребление памяти (или найти утечки памяти, распространенные в Python).
Инструмент мониторинга записывает всю другую информацию, которая остается в журнале, что поможет нам проверить шаги, выполняемые кодом, и при необходимости поможет улучшить производительность. Для этого чем больше данных, тем лучше.
3. Оптимизация кода
Оптимизация кода включает снижение временной сложности (время выполнения) и уменьшение пространственной сложности (занимаемой памяти). Сложность времени/пространства обычно выражается как O(x), где x — многочлен от времени или пространства, который также известен какОбозначение большого O. Время и пространственная сложность используются для измеренияАлгоритмическая эффективность.
Например, предположим, что у нас есть размерnвложенныйforцикл, каждый запуск занимает около 2 секунд, после чего следует простойforцикл, каждый запуск занимает 4 секунды. Тогда уравнение затрат времени можно записать в виде
Потребление времени ≈ 2n²+4n = O(n²+n) = O(n²)
При использовании записи с большим O мы должны опустить постоянный член (потому чтоnпренебрежимо мал, так как стремится к бесконечности) и коэффициент. Коэффициенты или коэффициенты масштабирования игнорируются, потому что мы мало можем повлиять на них при оптимизации. Обратите внимание, что коэффициенты в выражении для абсолютного потребления времени относятся кforПроизведение количества циклов и времени, затрачиваемого на каждый запуск, и коэффициенты в O (n² + n) представляютforКоличество петель (1 двойной слойforпетля и 1 один слойforцикл). Точно так же мы можем избавиться от младших членов в уравнении. Следовательно, временная сложность описанного выше процесса составляет O(n²).
Теперь наша цель — заменить неэффективные части кода менее сложной по времени схемой. Например, O(n) лучше, чем O(n²). Наиболее часто занимающая много времени часть кодаforпетли, наименее распространенные, но менееforХудшие циклы - это рекурсивные функции (временная сложность O (ветка ^ глубина)). Попробуйте заменить как можно больше модулей или функций Python.forциклы, эти функции часто пишутся на C, а не на Python, и сильно оптимизированы для короткого времени выполнения.
Я настоятельно рекомендую прочитать Гейл Макдауэлл."Интервью с программистом Золотой код》Глава книги «Большой алгоритм». На самом деле, чтение всей книги может улучшить ваши навыки программирования.
4. Модульное тестирование
модульный тест- Автоматизировать тестирование кода на основе функциональности
Перед запуском в производство ваш код должен пройти несколько этапов тестирования и отладки. Обычно это разбивается на три уровня — разработка, подготовка и производство. В некоторых компаниях существует этап развертывания в смоделированной среде реальной производственной системы перед развертыванием в производственной среде. Когда код развертывается в рабочей среде, он не должен иметь явных проблем и должен уметь обрабатывать потенциальные исключения.
Чтобы иметь возможность выявлять широкий спектр проблем, которые могут возникнуть, нам необходимо тестировать разные сценарии, разные наборы данных, разные пограничные случаи и т. д. Когда мы вносим серьезные изменения в код, неэффективно каждый раз выполнять тестовый код вручную. Поэтому выберите модульный тест, содержащий набор тестовых случаев, и выполняйте его всякий раз, когда мы хотим протестировать код.
Мы должны добавить различные тестовые примеры с ожидаемыми результатами, чтобы протестировать наш код. Модуль модульного тестирования просматривает тестовые примеры один за другим и сравнивает вывод кода с ожидаемым значением. Если ожидаемый результат не достигнут, тест не пройден — это означает, что ваш код может выдавать ошибки при развертывании в продакшене. Нам нужно отлаживать код и повторять процесс, пока не пройдут все тестовые случаи.
Жизнь коротка, поэтому у Python естьunittestмодуль для реализации модульного тестирования.
5. Совместимость
В продакшене вполне возможно, что ваш код не является отдельной функцией или модулем. Он будет интегрирован в экосистему кода компании, и ваш код должен работать синхронно с остальной частью экосистемы без каких-либо ошибок/сбоев.
Например, предположим, что вы разработали алгоритм рекомендаций. Весь процесс обычно состоит из извлечения последних данных из базы данных, обновления/генерации рекомендаций и сохранения их в базе данных, которые будут считываться внешней средой (например, веб-страницей через API) для отображения рекомендуемых элементы пользователю. это очень просто! Этот процесс похож на цепочку, новая ссылка должна быть закрыта предыдущей и следующей ссылками, иначе процесс рекомендации не будет выполнен. Точно так же каждый процесс должен функционировать так, как ожидается.
Каждый процесс имеет четкие входные и выходные требования, ожидаемое время отклика и многое другое. Когда другие модули запрашивают рекомендацию по обновлению (с веб-страницы), ваш код должен возвращать ожидаемое значение в нужном формате в течение приемлемого времени. Если результатом является неожиданное значение (рекомендуется покупать молоко при покупке электроники), нежелательный формат (рекомендуется в виде текста, а не изображения) или неприемлемое время (сегодня никто не хочет ждать несколько минут, чтобы получить рекомендации) - это означает, что код не синхронизирован с системой.
Лучший способ избежать этого — обсудить требования с соответствующей командой до начала разработки. Если это не сработает, ознакомьтесь с документацией по коду (скорее всего, вы найдете там много информации) или напишите документацию по коду самостоятельно, если это необходимо, чтобы понять требования.
6. Контроль версий
Git — одно из лучших изобретений в области управления исходным кодом за последние годы, система контроля версий, которая отслеживает изменения кода на вашем компьютере. По сравнению со многими существующими системами контроля/отслеживания версий, Git используется наиболее широко.
Этот процесс просто «изменить и зафиксировать». Может быть, я слишком легко выражаюсь. В этом процессе есть много шагов, таких как ветвление для разработки, локальная фиксация изменений, извлечение файлов с удаленного компьютера, отправка файлов в удаленные ветки и многое другое для более глубокого изучения.
Каждый раз, когда мы вносим изменения в код, вместо того, чтобы сохранять файл под другим именем, мы фиксируем изменения, что означает перезапись старого файла новыми изменениями и присвоение этой фиксации идентификатора фиксации. Всякий раз, когда мы вносим изменения в код, мы обычно добавляем комментарии к фиксации. Если вам не нравятся изменения, сделанные в последней фиксации, и вы хотите вернуться к предыдущей версии, вы можете легко сделать это с помощью идентификатора фиксации. Git очень полезен для разработки и обслуживания кода.
Вы, вероятно, уже понимаете важность контроля версий для производственных систем и необходимость изучения Git. Чтобы предотвратить непредвиденные ошибки в новых версиях, мы должны иметь возможность вернуться к стабильным старым версиям в любое время.
7. Удобочитаемость
Код, который вы пишете, также должен быть простым для понимания другими, по крайней мере, членами вашей команды. Кроме того, если вы не следуете надлежащим соглашениям об именах, может быть трудно понять ваш собственный код даже через несколько месяцев после того, как вы его написали.
(i) Соответствующие имена переменных и функций
Имена переменных и функций должны говорить сами за себя. Когда кто-то читает ваш код, должно быть легко понять, что содержит каждая переменная и что делает каждая функция, по крайней мере, в некоторой степени.
Вполне допустимо давать функции или переменной длинное имя, четко определяющее ее функцию/роль, а не короткие бессмысленные имена, такие как x, y, z и т. д. И старайтесь не превышать 30 символов для имен переменных и 50-60 символов для имен функций.
Раньше ширина кода по стандарту IBM составляла 80 символов, что полностью устарело. Сейчас это около 120 символов по стандартам GitHub. Взяв 1/4 ширины страницы, мы получим длину имени 30 переменных, которая достаточно длинна, но не заполняет всю страницу. Имена функций могут быть немного длиннее, но опять же они не должны занимать всю страницу. Итак, взяв 1/2 ширины страницы, мы получим 60.
Например, переменная среднего возраста азиатских мужчин в выборочных данных может быть записана какmean_age_men_Asiaвместоageилиx. Аналогичные правила применяются к именам функций.
(ii) строки документации и комментарии
В дополнение к соответствующим именам переменных и функций должны быть предоставлены комментарии, если это необходимо, чтобы помочь читателям понять код.
строка документации - применяется к функциям/классам/модулям. Первые несколько строк текста в определении функции описывают, что делает функция, а также ее входные и выходные данные. Этот текст необходимо заключить в 3 двойных кавычки.
def <function_name>:
"""<docstring>"""
return <output>
Примечания- может быть размещен в любом месте кода, чтобы сообщить читателю, что делает конкретная строка или раздел кода. Если мы дадим переменным и функциям собственные имена, потребность в комментариях значительно уменьшится — большая часть кода не требует пояснений.
Обзор кода:
Хотя это не является прямым шагом к написанию кода производственного качества, рецензирование кода экспертами поможет улучшить ваши навыки кодирования.
Никто не может написать идеальный код, если у этого человека нет более 10 лет опыта. В коде всегда есть место для улучшения. Я видел, как профессионалы с многолетним опытом пишут ужасный код, и я видел новичков, получающих степень бакалавра с отличными навыками кодирования — всегда можно найти кого-то лучше вас. Все зависит от того, сколько времени вложено в обучение и практику, а самое главное, практика делает совершенным.
Я знаю, что всегда есть люди лучше тебя, но не обязательно в твоей команде. Может быть, ты лучший в команде. В этом случае все еще нормально, чтобы другие члены команды тестировали ваш код и оставляли отзывы. Даже если они не так хороши, как вы, они могут заметить что-то, что вы упустили из виду.
Обзоры кода особенно важны, когда вы находитесь на ранних этапах своей карьеры. Это значительно улучшит ваши навыки кодирования. Следуйте приведенным ниже инструкциям, чтобы успешно просмотреть свой код.
(i) Завершение всего кода разработки, тестирования и отладки. Старайтесь не совершать ошибок низкого уровня. Затем попросите своих приятелей помочь с код-ревью.
(ii) перешлите им ссылку на ваш код. Отправляйте их по одному вместо того, чтобы заставлять их просматривать несколько сценариев одновременно. Мнения, которые они дают для первого сценария, могут относиться и к другим сценариям. Перед отправкой второго сценария на проверку обязательно примените эти изменения (если применимо) к другому сценарию.
(iii) Дайте им неделю или две на чтение и тестирование кода для каждой итерации. Также предоставьте всю информацию, необходимую для тестирования кода, например пример ввода, ограничения и т. д.
(iv) опросите каждого из них и прислушайтесь к их советам. Помните, что вам не нужно принимать все предложения в вашем коде, просто выбирайте те, которые, по вашему мнению, могут улучшить ваш код.
(v) Повторяйте, пока вы и ваша команда не будете удовлетворены. Попробуйте исправить или улучшить свой код в первые несколько итераций (до 3-4), иначе у вас может сложиться плохое впечатление, что вы не умеете кодировать достаточно.
Надеюсь, эта статья поможет вам.
С нетерпением ждем ваших отзывов.
Если вы обнаружите ошибки в переводе или в других областях, требующих доработки, добро пожаловать наПрограмма перевода самородковВы также можете получить соответствующие бонусные баллы за доработку перевода и PR. начало статьиПостоянная ссылка на эту статьюЭто ссылка MarkDown этой статьи на GitHub.
Программа перевода самородковэто сообщество, которое переводит высококачественные технические статьи из Интернета сНаггетсДелитесь статьями на английском языке на . Охват контентаAndroid,iOS,внешний интерфейс,задняя часть,блокчейн,продукт,дизайн,искусственный интеллектЕсли вы хотите видеть более качественные переводы, пожалуйста, продолжайте обращать вниманиеПрограмма перевода самородков,официальный Вейбо,Знай колонку.