Декомпозиция программы на функции
Уроки курсаДекомпозиция программы на функции
Принцип единственной ответственности функции
Когда вы разбиваете программу на функции, возникает соблазн сделать «умную» функцию: пусть она сама спросит у пользователя цену, сама посчитает скидку и сама напечатает результат. Технически это работает. Но это не декомпозиция — это перекладывание монолита в другой контейнер.
Принцип простой: одна функция — одно действие. Не «работа с ценой», а конкретно: либо получить цену, либо применить скидку, либо вывести чек. Если функцию сложно назвать одним глаголом — скорее всего, она делает слишком много.
Посмотрите на такой код:
def process_order():
price = float(input("Введите цену: "))
discounted = price * 0.9
print(f"Итого со скидкой: {discounted:.2f} руб.")
Здесь в одной функции живут три разные обязанности: ввод, вычисление и вывод. Это проблема по трём причинам.
Во-первых, функцию нельзя переиспользовать. Если где-то в программе нужно применить ту же скидку, но к уже известной цене — process_order() не поможет: она обязательно запросит ввод заново.
Во-вторых, функцию трудно проверить. Чтобы убедиться, что скидка считается правильно, придётся каждый раз вводить данные вручную — автоматически это не протестировать.
В-третьих, имя функции лжёт. process_order звучит как что-то большое, но на деле это три несвязанных действия, случайно оказавшихся вместе.
Диагностика простая: если вы описываете, что делает функция, и вынуждены использовать союз «и» — это сигнал, что перед вами кандидат на разделение.
Критерий хорошей функции — она принимает данные через параметры и возвращает результат, не делая ничего лишнего. Например, функция, которая только считает скидку, выглядит так:
def apply_discount(price, rate):
return price * (1 - rate)
Она не знает, откуда пришла цена и что будет с результатом. Она только считает. Именно поэтому её можно вызвать с любым числом, не запуская ввод с клавиатуры.
Точно так же функция ввода должна только читать данные и возвращать их, а функция вывода — только печатать то, что ей передали. Как именно выглядит полный набор таких функций — разберём по шагам в следующем разделе.
