Python — один из наиболее элегантных и чистых языков программирования. Но красивый и чистый синтаксис не означает чистый код. И не избавляет разработчиков от необходимости изучать наилучшие приемы и шаблоны проектирования.
Процитируем Бьерна Страуструпа, создателя языка C++. Он дал очень четкое определение того, что можно считать чистым кодом.
«Я хочу, чтобы мой код был красивым и эффективным. Логика должна быть понятной — так багам будет сложнее спрятаться. Зависимостей должно быть как можно меньше — это облегчает поддержку. Обработка ошибок должна выполняться согласно определенной стратегии. А производительность должна быть приближена к оптимальной — чтобы не соблазнять людей заняться непринципиальными оптимизациями, которые могли бы запутать код. Чистый код делает что-то одно, и делает это хорошо».
Из этой цитаты мы можем выбрать несколько отличительных признаков чистого кода:
Конечно, разработчики вольны писать код так, как им нравится. Нет такого закона, который обязывал бы их писать исключительно чистый код. Но когда код написан плохо, это способствует накоплению технического долга и может повлечь за собой негативные последствия для компании. А это солидная причина писать код как можно лучше.
В этой статье мы рассмотрим несколько советов, как писать чистый код на Python.
Соглашения об именах — один из самых полезных и важных залогов написания чистого кода. Обдумывая, как назвать переменные, функции, классы и т. д., выбирайте осмысленные имена, раскрывающие ваши намерения. Это предполагает, что следует отдавать предпочтение длинным и описательным именам.
Несколько примеров:
Используйте длинные описательные имена, которые будет легко читать. Это избавит вас от необходимости писать лишние комментарии.
# Не рекомендуется # Переменная au - это число активных пользователей au = 105 # Рекомендуется total_active_users = 105
Имена должны раскрывать ваши намерения. Читая ваш код, другой разработчик должен по имени переменной понимать, что в ней хранится.
# Не рекомендуется c = [“UK”, “USA”, “UAE”] for x in c: print(x) # Рекомендуется cities = [“UK”, “USA”, “UAE”] for city in cities: print(city)
Избегайте непонятных сокращений. Лучше пусть имя будет длинным, но понятным, чем коротким и при этом неоднозначным.
# Не рекомендуется fn = 'John' Ln = ‘Doe’ cre_tmstp = 1621535852 # Рекомендуется first_name = ‘JOhn’ Las_name = ‘Doe’ creation_timestamp = 1621535852
Используйте один и тот же набор слов. Непоследовательность будет путать читателя. Это касается не только имен переменных, файлов, функций, но даже и структуры директорий.
# Не рекомендуется client_first_name = ‘John’ customer_last_name = ‘Doe; # Рекомендуется client_first_name = ‘John’ client_last_name = ‘Doe’ # Также обратите внимание на следующий пример: # Не рекомендуется def fetch_clients(response, variable): # do something pass def fetch_posts(res, var): # do something pass # Рекомендуется def fetch_clients(response, variable): # do something pass def fetch_posts(response, variable): # do something pass
Начните отслеживать проблемы (issues) в кодовой базе в своем редакторе.
Для содержания кодовой базы в чистоте очень важно сделать так, чтобы другим разработчикам было легко видеть и отслеживать проблемы в коде. Когда вы можете это делать прямо в своем редакторе, вы:
Конечно, вы можете использовать различные инструменты для отслеживания технического долга, но лучше начать пользоваться соответствующими расширениями для редактора кода. Самые популярные из них также интегрируются с Jira, Linear, Asana и другими инструментами для управления проектами.
Не используйте магические числа. Это жестко прописанные числа, которые встречаются в коде без всяких объяснений. Обычно они появляются в виде литералов, причем неоднократно.
import random # Не рекомендуется def roll_dice(): return random.randint(0, 4) # what is 4 supposed to represent? # Рекомендуется DICE_SIDES = 4 def roll_dice(): return random.randint(0, DICE_SIDES)
При именовании функций строго придерживайтесь соглашения об именах. Использование разных подходов будет путать читателя.
# Не рекомендуется def get_users(): # do something Pass def fetch_user(id): # do something Pass def get_posts(): # do something Pass def fetch_post(id): # do something pass # Рекомендуется def fetch_users(): # do something Pass def fetch_user(id): # do something Pass def fetch_posts(): # do something Pass def fetch_post(id): # do something pass
Каждая функция должна выполнять какое-то одно действие и делать это хорошо. Пишите короткие и простые функции, выполняющие одну задачу. Полезный прием: если в имени вашей функции появляется союз «и», лучше разделить такую функцию на две разных.
# Не рекомендуется def fetch_and_display_users(): users = [] # result from some api call for user in users: print(user) # Рекомендуется def fetch_usersl(): users = [] # result from some api call return users def display_users(users): for user in users: print(user)
Не используйте Boolean flags. Это переменные, содержащие булевы значения — True или False. Они передаются в функцию для определения ее поведения.
text = "Python is a simple and elegant programming language." # Не рекомендуется def transform_text(text, uppercase): if uppercase: return text.upper() else: return text.lower() uppercase_text = transform_text(text, True) lowercase_text = transform_text(text, False) # Рекомендуется def transform_to_uppercase(text): return text.upper() def transform_to_lowercase(text): return text.lower() uppercase_text = transform_to_uppercase(text) lowercase_text = transform_to_lowercase(text)
Не добавляйте лишний контекст. Например, не следует добавлять ненужные слова к именам переменных.
# Не рекомендуется class Person: def __init__(self, person_username, person_email, person_phone, person_address): self.person_username = person_username self.person_email = person_email self.person_phone = person_phone self.person_address = person_address # Рекомендуется class Person: def __init__(self, username, email, phone, address): self.username = username self.email = email self.phone = phone self.address = address
В этом примере мы находимся внутри класса Person, поэтому нет нужды добавлять префикс person_
к каждой переменной класса.
Чтобы ваш код оставался организованным и поддерживаемым, распределяйте логику по разным файлам или классам — т. н. модулям. В Python модуль — это просто файл, имеющий расширение .py. Каждый модуль должен фокусироваться на какой-то одной задаче.
От редакции Pythonist. О модулях можно почитать в статье «Как импортировать в Python?».
Вы можете придерживаться принципов объектно-ориентированного программирования, таких как инкапсуляция, абстракция, наследование и полиморфизм.
Чистый код дает много преимуществ. Здесь и улучшение качества ПО, и легкая поддержка, и уменьшение технического долга.
В этой статье мы рассмотрели само понятие чистого кода и несколько советов о том, как писать чистый код на Python. Учтите, что это переходные знания: они вам пригодятся и при работе с любым другим языком программирования.
Перевод статьи «10 must-know patterns for writing clean code with Python».
Python предлагает набор библиотек, удовлетворяющих различные потребности в визуализации, будь то академические исследования, бизнес-аналитика или…
В Python для представления данных в двоичной форме можно использовать байты. Из этой статьи вы…
В этой статье рассказывается о том, что такое Werkzeug и как Flask использует его для…
При работе с датами часто возникает необходимость прибавлять к дате или вычитать из нее различные…
В этом руководстве мы рассмотрим, как добавить социальную аутентификацию с помощью GitHub и Google в…
В этой статье мы рассмотрим, что такое подсказки типов и чем они могут быть полезны.…