Умение писать классы ещё не значит умение строить хорошие программы. Эта тема — мост от ООП к дизайну: мы решаем, что должен делать класс и насколько он должен зависеть от других.

Четыре принципа вкратце

  • Инкапсуляция: состояние скрыто и меняется методами (свойства).
  • Наследование: подкласс берёт поведение родителя (наследование и super).
  • Полиморфизм: один вызов по-разному работает на разных объектах (классы и объекты).
  • Абстракция: показываем, что делает объект, а не как (ABC).
python
from abc import ABC, abstractmethod

class Shape(ABC):                        # abstraction: what, not how
    @abstractmethod
    def area(self): ...

class Square(Shape):                     # inheritance
    def __init__(self, side):
        self._side = side                # encapsulation: hidden state

    def area(self):
        return self._side ** 2

class Circle(Shape):
    def __init__(self, r):
        self._r = r

    def area(self):
        return round(3.14159 * self._r ** 2, 2)

for shape in (Square(3), Circle(1)):     # polymorphism: one call, many behaviours
    print(type(shape).__name__, shape.area())
text
Square 9
Circle 3.14

Эти принципы — инструменты. Дизайн — это выбор, когда и как их применять. Три главных вопроса: для чего этот класс? от кого он зависит? что сломается, если его изменить?

Цель дизайна

Программу пишут один раз, а меняют многократно. Хороший дизайн делает изменение дешёвым. Это показывают две меры: связность (cohesion) — насколько части класса относятся друг к другу (цель: высокая) и зацепление (coupling) — зависимость классов друг от друга (цель: низкое).