Декомпозиция

Controlling complexity is the essence of computer programming.

—Brian Kernighan

Можно выделить два инструмента управления сложностью в программировании:

  • Абстракция

  • Декомпозиция

Абстрагирование — сосредоточение на важных сторонах и отказ от неважных.

Декомпозиция — разделение целого на части.

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

  • Принцип единственной ответственности (The Single Responsibility Principle, SRP). Функция или класс должны решать только одну задачу.

  • По возможности старайтесь разрабатывать чистые функции.

    Чистая функция — это функция, результат работы которой зависит только от входных аргументов.

    Функция не является чистой, если в ней присутствует ввод-вывод или обращение к глобальным переменным.

  • Do not repeat yourself (DRY). Каждая часть знания должна иметь единственное, непротиворечивое и авторитетное представление в рамках системы. В простых случаях нарушение этого принципа проявляется в дублировании кода, использовании неименованных констант (magic numbers).

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

Упражнения

Какие принципы нарушают приведенные ниже функции? Как их исправить?

1:

import math

def calculate_area_and_perimeter(height, width):
    area = height * weight
    perimeter = 2 * height + 2 * width
    return area, perimeter

2:

def calculate_area(height, width):
    area = height * weight
    print(area)

3:

flag = True

def f(n):
    global flag
    flag = not flag
    if flag:
        return n * 2
    return n

def test():
    print(f'f(1) + f(2) = {f(1) + f(2)}')
    print(f'f(2) + f(1) = {f(2) + f(1)}')

Выполните рефакторинг функции:

def weekday(day_number):
    if day_number == 1:
        return 'Monday'
    if day_number == 2:
        return 'Tuesday'
    if day_number == 3:
        return 'Wednesday'
    if day_number == 4:
        return 'Thursday'
    if day_number == 5:
        return 'Friday'
    if day_number == 6:
        return 'Saturday'
    if day_number == 7:
        return 'Sunday'

Что делает этот код? Найдите в нем ошибки. Выполните его рефакторинг.

def main():
    # Subject data = [weight_kg, height_m]
    subject1 = [80, 1.62]
    subject2 = [69, 1.53]
    subject3 = [80, 1.66]
    subject4 = [80, 1.79]
    subject5 = [72, 1.60]

    bmi_subject1 = int(subject1[0] / subject1[1] ** 2)
    print(f"bmi subject1 = {bmi_subject1}")

    bmi_subject2 = int(subject2[0] / subject2[1] ** 2)
    print(f"bmi subject2 = {bmi_subject2}")

    bmi_subject3 = int(subject3[0] / subject3[1] ** 3)
    print(f"bmi subject2 = {bmi_subject3}")

    bmi_subject4 = int(subject4[0] / subject4[1] ** 2)
    print(f"bmi subject4 = {bmi_subject4}")

    bmi_subject5 = int(subject5[0] / subject5[1] ** 2)
    print(f"bmi subject5 = {bmi_subject5}")


if __name__ == '__main__':
    main()

Задание 1

Даны фигуры: окружность, треугольник, прямоугольник. Окружность задана координатами центра и радиусом. Треугольник и прямоугольник заданы координатами вершин. Разработать приложение для вычисления площади фигур.

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

\[S = \sqrt{p(p-a)(p-b)(p-c)}\]

Где p — полупериметр.

\[p = \frac{a + b + c}{2}\]

Расстояние между двумя точками можно вычислить по формуле:

\[d_{ab} = \sqrt{(x_b - x_a)^2 + (y_b - y_a)^2}\]

Задание 2

Разработайте простую модель пиццерии.

В пиццерии готовят несколько разновидностей пиццы по известным рецептам:

recipes = {
    'Пепперони': {'орегано', 'томатная паста', 'базилик', 'пепперони'},
    'Четыре сыра': {'томаты', 'моцарелла', 'фонтин', 'пармезан', 'фета'},
    'Вегетарианская': {'лук', 'сельдерей', 'редис', 'брокколи', 'морковь'},
}

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

Для решения этой задачи ответьте на вопросы:

  1. Какие сущности фигурируют в модели?

  2. Какие они содержат данные?

  3. Какое у них поведение?

Реализуйте необходимые классы и составьте сценарий работы пиццерии. В результате работы программы пользователь должен увидеть текстовый лог происходящих событий. Например:

В пиццерию заходит клиент и заказывает Пепперони.
За работу берется Профессионал.
Пицца готова! В нее выходят томатная паста, орегано, базилик и пепперони.
Клиент оставил отзыв: ***** — Все было очень вкусно!

В пиццерию заходит клиент и заказывает Четыре сыра.
За работу берется Стажер.
Пицца готова! В нее входят сельдерей, морковь, лук, редис и брокколи.
Клиент оставил отзыв: * — Повар перепутал заказ!

Задание 3

Разработайте игру «Сто спичек». Из кучки, состоящей из ста спичек, двое игроков поочередно берут от 1 до 10 спичек. Выигрывает взявший последнюю спичку. Реализуйте режим для двух игроков и игру с компьютером.