MVC против ООП

265

Перевод статьи Егора Бугаенко, который выступил с критикой ещё одного всем известного паттерна, который нарушает принципы ООП.

MVC-фреймворки под угрозой!
Model-view-controller (MVC) – хорошо знакомый нам паттерн программирования. Он, по сути, является стандартом для большинства пользовательских интерфейсов и веб-фреймворков. Он удобен и лёгок в применении, прост и эффективен. Отличная концепция… для процедурного программирования. Если ваше программное обеспечение –объектно-ориентированное, вы должны недолюбливать её не меньше меня. И вот почему.
Вот так выглядит архитектура MVC:Model, view and controller
Контроллер руководит всеми процессами, манипулируя данными, полученными из Модели, и перенося их в Представление – именно в этом и заключается проблема. Данные выходят за пределы Модели и становятся «голыми» — а это, как мы знаем, большая неприятность. Всё ООП построено на инкапсуляции – скрытии данных.
Архитектура MVC работает с точностью до наоборот, раскрывая данные и скрывая поведение. Контроллер обращается к данным напрямую, принимая решения об их назначении и свойствах, в то время, как объекты, которые, по идее, должны иметь полное представление об информации и прятать её, остаются пассивными. Как раз на этом и строятся принципы любой процедурной архитектуры: код управляет информацией. Взять, к примеру, этот код на C++:

void print_speed() { // controller
  int s = load_from_engine(); // model
  printf("The speed is %d mph", s); // view
}

Функция «print_speed()» является контроллером. Она получает информацию «s» из модели «load_from_engine()» и воспроизводит её представлением «printf()». Только контроллер знает, что информация представлена в милях в час. Двигатель выдаёт скорость «load_from_engine()» в int безо всяких параметров. Контроллер просто предполагает, что данные представлены в милях в час. Если мы захотим создать похожий контроллер где-то ещё, нам придётся снова и снова делать это предположение. Вот в чём состоит проблема «голой информации», которая ведёт к серьёзным проблемам с обслуживанием ПО.
Вот объектно-ориентированная альтернатива для вышеуказанного кода (псевдо С++):

printf(
  new PrintedSpeed( // view
    new FormattedSpeed( // controller
      new SpeedFromEngine() // model
    )
  )
);

В этом случае «SpeedFromEngine.speed()» возвращает скорость в милях в час в виде целочисленного числа; «FormattedSpeed.speed()» возвращает «%d mph«; и, наконец, «PrintedSpeed.to_str()» возвращает полный текст сообщения. Можно называть их «моделью, представлением и контроллером», но на деле это просто объекты, декорирующие друг друга. Это одна и та же сущность – скорость, но она становится более сложной и осмысленной с помощью этого декорирования.
Мы не делим понятие скорости на части. Скорость есть скорость – независимо от того, кто работает с ней и где она представляется. Она просто получает новое поведение от декораторов. Она наращивается, но не распадается на части.
Подводя итог, можно сказать, что Контроллер – это полностью процедурный компонент из троицы MVC, который превращает Модель в пассивное хранилище данных, а Представление – в пассивный визуализатор. Можно ли на самом деле называть такую архитектуру объектно-ориентированной?

  • XXXIV XII

    Всему свое место. У системных администраторов есть известная поговорка: работает — не трогай.