Python для новичковФункцииДекомпозиция программы на функции

Декомпозиция программы на функции

Уроки курсаДекомпозиция программы на функции

Принцип единственной ответственности функции

Когда вы разбиваете программу на функции, возникает соблазн сделать «умную» функцию: пусть она сама спросит у пользователя цену, сама посчитает скидку и сама напечатает результат. Технически это работает. Но это не декомпозиция — это перекладывание монолита в другой контейнер.

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

Посмотрите на такой код:

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)

Она не знает, откуда пришла цена и что будет с результатом. Она только считает. Именно поэтому её можно вызвать с любым числом, не запуская ввод с клавиатуры.

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