Качество кода на Python: инструменты и Best Practices

качество кода, Качество кода на Python: инструменты и Best Practices

В этой статье мы разберем, каким должен быть высококачественный код на Python, а также рассмотрим, что можно сделать для улучшения качества вашего собственного кода.

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

Что такое качество кода?

Естественно, вы хотите, чтобы ваш код был качественным (кто ж не хочет?). Но для этого нужно сначала определиться с тем, что следует понимать под словом «качество».

Быстрый поиск в Google выдает множество результатов с определениями качества кода. И, как выясняется, этот термин разные люди понимают по-разному.

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

  • он делает то, что должен делать,
  • он не имеет дефектов и проблем,
  • его легко читать, поддерживать и расширять.

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

Почему качество кода имеет значение?

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

Код НЕ делает то, что должен делать

Удовлетворение требований — это основа любого продукта, хоть программного, хоть нет. Мы создаем программы, чтобы они что-то делали. Если в конечном итоге они это «что-то» не делают, о высоком качестве ПО речь определенно не идет. Если конечный продукт не соответствует требованиям, вряд ли стоит говорить даже о низком качестве.

Код содержит дефекты и проблемы

Если что-либо, чем вы пользуетесь, создает вам проблемы, вы вряд ли назовете такой продукт высококачественным. А если этот продукт будет достаточно плох, вы вообще прекратите им пользоваться.

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

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

Мы стараемся не допускать подобных проблем с нашими программами. Если в программе что-то ломается в крайних случаях (edge cases) или дефекты приводят к нежелательному поведению, этот продукт не является высококачественным.

Код сложно читать, поддерживать или расширять

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

Если код легко понять, вы сможете куда быстрее проанализировать проблему и предложить решение. А если код сложный и запутанный, вы и провозитесь дольше, и, возможно, сделаете какие-то неверные допущения.

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

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

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

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

качество кода, Качество кода на Python: инструменты и Best Practices

Как улучшить качество кода на Python

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

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

Итак, давайте начнем с самой догматичной темы: стиля кода.

Руководства по стилю

О, да. Старый добрый спор: пробелы или табы.

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

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

Руководства по стилю нужны, чтобы облегчить написание читаемого, поддерживаемого и расширяемого кода.

Что касается Python, в его экосистеме есть общепринятый стандарт написания кода. Он был написан (частично) создателем самого языка.

PEP 8 — руководство по стилю написания кода на Python, которым разработчики пользуются чаще всего. Если не знаете, с чего начать, это прекрасная отправная точка.

(Аббревиатура PEP расшифровывается как Python Enhancement Proposals — «предложения по улучшению Python». PEP-ов много, все посвящены разным темам. Для удобства им присвоены индексы. Почитать подробнее можно здесь, — прим. ред. Pythonist.ru).

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

Эти руководства определяют то, каким должен быть стиль написания кода. Но как принудительно внедрить этот стиль? И как насчет дефектов и проблем в коде: их-то как обнаружить? Вот тут в игру вступают линтеры.

Линтеры

Что такое линтер?

Для начала давайте поговорим о ворсинках (англ. lint — «пушинки, ворсинки», — прим. перев.). Этих маленьких надоедливых штуках, которые неизвестно откуда появляются на вашей одежде. Без ворсинок одежда выглядит куда лучше и опрятнее. Ваш код в этом плане не отличается от одежды. Мелкие ошибки, стилистические отклонения и опасная логика не улучшают самочувствие вашего кода.

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

(Линтеры также называют статическими анализаторами. Самый первый такой анализатор был создан в 1978 году для языка C; эта утилита называлась lint. Со временем название перешло на все подобные инструменты, — прим. ред. Pythonist.ru).

Кроме того, большинство редакторов кода и IDE умеют запускать линтеры в фоне, чтобы они отслеживали ошибки по мере набора кода. В результате среда разработки может подсвечивать, подчеркивать или еще как-то выделять проблемные места в коде еще до того как вы его запустите. Это похоже на продвинутую проверку правописания, только для кода. Ошибки подчеркиваются волнистыми красными линиями в точности, как в вашем любимом текстовом редакторе.

Линтеры анализируют код в поисках самых разных «ворсинок». Эти недостатки кода можно условно разделить на следующие категории:

1. Логические ошибки

  • Ошибки в коде
  • Код, который может выдать непредусмотренный результат
  • Опасные паттерны кода

2. Стилистические ошибки

  • Код, не соответствующий определенным соглашениям.

Есть также инструменты для анализа кода, предоставляющие дополнительную информацию. Эти инструменты не относятся к числу линтеров, но используются вместе с ними для улучшения качества кода.

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

Какие линтеры можно выбрать для кода на Python?

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

Flake8: распознает и логические, и стилистические ошибки. В нем проверки стиля и сложности, выполняемые pycodestyle, добавлены к поиску логических ошибок PyFlakes. Этот инструмент объединяет следующие линтеры:

  • PyFlakes
  • pycodestyle (прежде — pep8)
  • Mccabe

Pylama: инструмент проверки кода, составленный из многочисленных линтеров и прочих инструментов для анализа кода. В его составе вы найдете:

  • pycodestyle (прежде — pep8)
  • pydocstyle (прежде — pep257)
  • PyFlakes
  • Mccabe
  • Pylint
  • Radon
  • gjslint

А вот несколько отдельных линтеров с указанием категории и короткими описаниями:

ЛинтерКатегорияОписание
Pylintлогика и стильПроверяет ошибки, пытается принудительно приводить код к стандартному виду, ищет запахи кода
PyFlakesлогикаАнализирует программы на предмет разнообразных ошибок
pycodestyleстильПроверяет, соответствует ли код соглашениям в PEP 8
pydocstyleстильПроверяет, соответствует ли код соглашениям относительно docstring
BanditлогикаАнализирует код на предмет распространенных проблем безопасности
MyPyлогикаПроверяет статические типы

А вот несколько инструментов для анализа и форматирования кода:

ИнструментКатегорияОписание
MccabeанализПроверяет цикломатическую сложность
RadonанализАнализирует различные показатели кода (количество строк, сложность и т. д.)
BlackформатированиеБескомпромиссно форматирует код на Python
IsortформатированиеФорматирует импорты, сортируя их в алфавитном порядке и разбивая по разделам

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