Программа курса← Объектно ориентированное программирование
1История ООП
2Объект и Класс
3Базовые концепции ООП
4Принцип проектирования GRASP
5Принцип проектирования SOLID
6Паттерны GOF

Controller (Контроллер)

TODO: отвалидировать – текст собран автоматически из материалов курса на Google Drive, проверьте формулировки и код.

Controller – это объект, который отвечает за обработку системных событий и при этом не относится к интерфейсу пользователя. Он определяет методы для выполнения системных операций.

Зачем он нужен

Без контроллера логика сценария расползается по обработчикам кнопок и HTTP-эндпоинтам. Поменять способ доставки события – например, добавить к веб-интерфейсу консольный – значит переписать сценарий заново.

Контроллер принимает событие и решает, кому передать работу. Сам он ничего существенного не делает: как только в нём появляется бизнес-логика, он превращается в «божественный объект».

// Контроллер: принимает системное событие и раздаёт работу
public class CheckoutController
{
    private readonly IOrderRepository _orders;
    private readonly IPaymentService _payments;

    public CheckoutController(IOrderRepository orders, IPaymentService payments)
    {
        _orders = orders;
        _payments = payments;
    }

    public void Checkout(int orderId)
    {
        var order = _orders.GetById(orderId);
        _payments.Pay(order.Total);
        order.MarkPaid();
        _orders.Save(order);
    }
}
// Контроллер: принимает системное событие и раздаёт работу
class CheckoutController {
public:
    CheckoutController(IOrderRepository& orders, IPaymentService& payments)
        : orders_(orders), payments_(payments) {}

    void Checkout(int order_id) {
        Order order = orders_.GetById(order_id);
        payments_.Pay(order.Total());
        order.MarkPaid();
        orders_.Save(order);
    }

private:
    IOrderRepository& orders_;
    IPaymentService& payments_;
};
// Контроллер: принимает системное событие и раздаёт работу
type CheckoutController struct {
	orders   OrderRepository
	payments PaymentService
}

func NewCheckoutController(orders OrderRepository, payments PaymentService) *CheckoutController {
	return &CheckoutController{orders: orders, payments: payments}
}

func (c *CheckoutController) Checkout(orderID int) error {
	order, err := c.orders.GetByID(orderID)
	if err != nil {
		return err
	}

	if err := c.payments.Pay(order.Total()); err != nil {
		return err
	}

	order.MarkPaid()

	return c.orders.Save(order)
}
# Контроллер: принимает системное событие и раздаёт работу
class CheckoutController:
    def __init__(self, orders: OrderRepository, payments: PaymentService) -> None:
        self._orders = orders
        self._payments = payments

    def checkout(self, order_id: int) -> None:
        order = self._orders.get_by_id(order_id)
        self._payments.pay(order.total)
        order.mark_paid()
        self._orders.save(order)
// Контроллер: принимает системное событие и раздаёт работу
class CheckoutController {
    constructor(
        private readonly orders: OrderRepository,
        private readonly payments: PaymentService,
    ) {}

    checkout(orderId: number): void {
        const order = this.orders.getById(orderId);
        this.payments.pay(order.total);
        order.markPaid();
        this.orders.save(order);
    }
}
// Контроллер: принимает системное событие и раздаёт работу
public class CheckoutController {
    private final OrderRepository orders;
    private final PaymentService payments;

    public CheckoutController(OrderRepository orders, PaymentService payments) {
        this.orders = orders;
        this.payments = payments;
    }

    public void checkout(int orderId) {
        Order order = orders.getById(orderId);
        payments.pay(order.getTotal());
        order.markPaid();
        orders.save(order);
    }
}
// Контроллер: принимает системное событие и раздаёт работу
class CheckoutController(
    private val orders: OrderRepository,
    private val payments: PaymentService,
) {
    fun checkout(orderId: Int) {
        val order = orders.getById(orderId)
        payments.pay(order.total)
        order.markPaid()
        orders.save(order)
    }
}

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