Обложка: Советы Python-новичкам от синьора

Советы Python-новичкам от синьора

Дмитрий Селищев

Дмитрий Селищев

Senior Developer в DataArt

Часть 1. HARD-советы

Code review — на благо проекта

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

Инструментами для код-ревью могут быть платформы GitHub, Bitbucket, Gitlab с их Pull/Merge Request-ами.

Проектируйте перед имплементацией

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

Инструментами для рисования подобных структур могут стать draw.io и plant uml, чтобы распространить их среди других участников процесса для установления стандартов внутри конкретной код-базы.

Вообще, проектирование — тема отдельной большой статьи, а здесь я лишь напоминаю о его необходимости.

Используйте boilerplate-ы

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

Монолит вместо микросервисов

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

Применяйте инструменты поддержания качества кода

Линтер — ваш лучший друг

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

Статический анализатор кода способен проверить код на соответствие PEP8, проверить синтаксис и выявить некоторые плавающие баги еще до запуска (к примеру, использование mutable-типов в default-параметрах keyword-аргументов), способен указать на потенциально опасные места в коде, сообщить о неиспользуемых импортах и многое другое. В общем, это крайне полезный инструмент и для начинающих, и для опытных разработчиков, позволяющий лишить ревью большинства мелких замечаний по качеству именно кода, а не логики в целом.

Инструменты: Flake8 или Pylint (предпочитаю flake8).

Развитый typing — помощник в отладке и развитии проекта

Хоть Python и замечателен динамичностью, все же утиная типизация (duck typing) иногда вводит в заблуждение даже опытных бойцов. Отсутствие необходимости прописывать типы, особенно в неочевидных местах, часто спустя уже парочку месяцев приводит к непониманию, что код вообще делает. Вторая же строчка из PEP20 гласит «Explicit is better than implicit». Соответственно, ничто не мешает сделать поведение нашего собственного кода более явным, добавив типы. Как минимум, во все объявления функций и методов, что позволит нам для любого вызова узнать возвращаемый тип функции и ожидаемый тип аргументов либо с помощью подсказок IDE, либо глянув на объявление этой самой функции. Вместе с inline-документацией это сильно повысит читаемость кода, легкость его повторного использования и debug-а. Более того, можно ввести статическую проверку типизации, что будет принуждать всех следовать тайпингу.

Инструменты: python typing и Mypy.

Однообразное форматирование — меньше разногласий и вопросов

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

Инструменты: Black или autopep8 (предпочитаю black).

Принуждение к статическому анализу и автоформатированию

Все приведенное выше будет бесполезно, если не принуждать каждого выполнять эти требования. Один из хорошо зарекомендовавших себя способов принудить разработчика к статическому анализу и автоформатированию — ввести commit-хуки, которые не дают возможности закоммитить изменения, пока все ошибки не будут исправлены. На практике commit-хуки можно проигнорировать, но при использовании тех же статических анализаторов на CI/CD, такой код все равно не останется без внимания, и нарушитель будет обнаружен.

Инструменты: фреймворк pre-commit, в который можно легко интегрировать black, flake8, mypy, codespell и еще кучу разных статических проверок.

Работайте с Git осмысленно

Используйте готовую модель ветвления в проекте — не изобретайте велосипед. Одна из самых универсальных парадигм работы с гит ветками — Git Flow. Она описывает модель ветвления в репозитории, как разрабатывать фичи, как делать фиксы, как подойти к релизу и хотфиксить уже сделанный релиз. Методология понятная, и более того, для нее уже существует готовый инструмент поверх системного git – git-flow.

Пишите осмысленные commit-сообщения. По commit-сообщениям другие члены команды могут даже узнать, где произошли изменения в коде без разглядывания деталей commit-сообщения. Более того, если вдруг результаты вашей работы в этом коммите окажутся не нужны (такое случается, требования иногда меняются), по сообщению «add some fixes» будет крайне сложно понять, о чем вообще идет речь. Пишите сообщение в present simple времени, максимум одно сухое предложение — что сделано в пределах этого коммита. Пример адекватного гит-сообщения: «FEATURE-123: Add logging to all sign-up attempts», где «FEATURE-123» — это номер задачи в вашем таск-трекере. Если нужно описать больше подробностей — для этого есть комментарии к коммиту, пользуйтесь ими.

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

Часть 2. SOFT-советы

Выясняйте требования и ничего не выдумывайте

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

Задавайте себе вопросы — всё ли я делаю так?

Еще один очень полезный soft-навык — задавать себе вопросы: «а не фигню ли я сейчас делаю?», «зачем я делаю эту задачу?», «какую бизнес-проблему я решаю?», «точно ли я правильно понял требования?», «все ли я учел перед началом разработки?». Если почаще задавать себе такие вопросы, можно избежать проблем на более ранних стадиях работы над задачей, чем когда уже всё закончено и вдруг выясняется, что было сделано вообще не то, что просили. С одной стороны, вопросы звучат странно, но иногда задать их себе — единственный способ понять, что нужно остановиться и спросить совет у кого-то постарше.

Выполняйте работу в срок

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

Завышенные сроки — проблема намного меньшая, чем заниженные. Заказчик, хоть и с болью, но чаще всего может смириться с тем, что ему придется долго ждать выполнения работы. Чаще всего в такой ситуации ему лишь необходим ответ на вопрос «почему так долго?», который он сможет передать уже собственному начальству, спланировать демки и презентации. Если вы выполните работу раньше, у заказчика не будет проблем, хоть он, возможно, и не будет слишком доволен вашей оценкой времени.

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

Итоговые тезисы

  • Code review — на благо проекта.
  • Проектируйте перед имплементацией.
  • Используйте boilerplate.
  • Монолит вместо микросервисов.
  • Применяйте инструменты поддержания качества кода.
    • Однообразное форматирование — меньше разногласий и вопросов.
    • Линтер — твой лучший друг.
    • Развитый typing – помощник в отладке и развитии проекта.
  • Работайте с Git осмысленно.
  • Выясняйте требования и ничего не выдумывайте.
  • Задавайте себе вопросы — все ли я делаю так?
  • Выполняйте работу в срок.
  • Выводы.

Список инструментов

  • Black
  • Flake8/Pylint
  • Mypy
  • git-flow
  • draw.io и Plant UML

Вывод

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