4 простых способа рефакторинга кода



Книга 4 простых способа рефакторинга кода

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


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


Рассмотрим пять простых способов рефакторинга кода для начинающих в Python с пояснениями преимуществ и демонстрацией кода до и после.


Определение функций для повторяющихся задач


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


Функции предоставляют множество преимуществ, но с точки зрения рефакторинга сокращается объём кода, улучшается читаемость. Кроме того, если нужно обновить задачу, делать это понадобится только на одном участке — в определении функции.


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


До


while True:
length = int(input("Enter the length: "))
if length > 0:
break

while True:
width = int(input("Enter the width: "))
if length > 0:
break

print("The area is", length * width)

Заметьте, что два блока почти идентичны. А что, если понадобится вычислить объём куба? Скорее всего мы скопируем цикл while, изменив имя переменной и приглашение к вводу.


После


def input_positive_integer(prompt):
while True:
input_value = int(input(prompt))
if input_value > 0:
return input_value

length = input_positive_integer("Enter the length: ")
width = input_positive_integer("Enter the width: ")
print("The area is", length * width)

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


Конструктор списков вместо цикла for


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


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


Давайте рассмотрим два примера, один простой и второй немного посложнее.


В первом примере выберем нечётные числа из списка целых чисел.


До


my_numbers = [1,2,3,4,5]
odd_numbers = []
for item in my_numbers:
if item % 2 == 1:
odd_numbers.append(item)

print(odd_numbers) # [1, 3, 5]

В этом примере запустим цикл в my_numbers и используем оператор вычисления остатка, чтобы определить, нужно ли вставлять элемент в odd_numbers.


После рефакторинга


my_numbers = [1,2,3,4,5]
odd_numbers = [item for item in my_numbers if item % 2 == 1]

Подведём итог в этом примере: конструктор списков — это передача элементов в odd_numbers, перебор my_numbers, выполнение return (первый item) и применение оператора if для фильтрации.


Можно создавать более сложные конструкторы списков, что даёт большие преимущества. Во втором примере предположим, что у нас есть двумерная матрица целых чисел и каждое значение мы хотим возвести в квадрат.


До


matrix = [[1,2,3],[4,5,6],[7,8,9]]
squared_matrix = []

for row in matrix:
line = []
for item in row:
line.append(item ** 2)
squared_matrix.append(line)

print(squared_matrix)
# [[1, 4, 9], [16, 25, 36], [49, 64, 81]]

Мы должны использовать вложенный цикл for вместе с временной переменной для хранения каждой строки перед вставкой в окончательную переменную.


После рефакторинга


matrix = [[1,2,3],[4,5,6],[7,8,9]]
squared_matrix = [
[
item ** 2
for item in row
]
for row in matrix
]

print(squared_matrix)
# [[1, 4, 9], [16, 25, 36], [49, 64, 81]]

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


Логический оператор OR вместо условного оператора


Присвоение одного из двух значений может быть обработано с помощью простого оператора if:


if args['website']:
website = args['website']
else:
website = "https://nuancesprog.ru"

Эти типы присвоений “или-или” традиционно могут выполняться с помощью условного оператора, объединяющего присвоения в один.


До


website = args['website'] if args['website'] else "https://nuancesprog.ru"

Структура условного оператора такова:


value if true | expression | value if false

Когда выражение должно оценить, приводит ли “value-if-true” к булеву значению True, логический оператор OR может упростить трудно читаемый условный оператор.


После


website = args['website'] or "https://nuancesprog.ru"

Логический оператор OR пытается присвоить первое значение. Если первое значение приводит к False—None, пустая переменная и т.д.—используется второе значение.


Этот код значительно проще читать, он позволяет эффективно устанавливать значение по умолчанию при присвоении переменной.


Функция enumerate() вместо range()


Цикл for в Python может сбивать с толку, особенно, если вы привыкли работать с другими языками программирования. Вашим первым порывом будет создать индексную переменную и использовать её для перебора списка. 


В результате часто используется функция range(). Этот приём не “в стиле” Python, в отличие от руководства по стилю и проверенных приёмов. Подробнее вы можете прочесть в моей статье “Перестаньте использовать range() в цикле for в Python”.


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


До


races = ["Terran", "Protoss", "Zerg"]
for i in range(len(races)):
print(i+1, races[i])

# 1 Terran
# 2 Protoss
# 3 Zerg

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


После рефакторинга


races = ["Terran", "Protoss", "Zerg"]
for i, race in enumerate(races, 1):
print(i, race)

# 1 Terran
# 2 Protoss
# 3 Zerg

Функция enumerate() принимает два аргумента: итерируемое и начальное значение счёта, а возвращает текущее порядковое значение и элемент в итерируемом. Примечание: временная переменная счёта идёт первой в цикле for, а начальное значение счёта идёт вторым в вызове функции. Это распространённая ошибка. 


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




553   0  

Comments

    Ничего не найдено.