Статьи

Является ли MVC Pattern тупиком для разработки приложений?

В этой статье я хотел бы показать вам, почему использование шаблона MVC недостаточно для создания гибких и масштабируемых приложений. Я также предложу возможные решения выявленных проблем.

В шаблоне Model View Controller нет ничего плохого. Это решает проблему, для которой она была изобретена — отделить логику обработки пользовательских запросов от логики представления.

До изобретения этого шаблона логика обработки пользовательских запросов и логика представления были тесно связаны в одном файле. Это значительно усложнило обслуживание и привело к появлению множества ошибок в системе.

Шаблон MVC является хорошим выбором, когда прикладные модули более или менее независимы друг от друга. Например, они вызываются из главного меню. Давайте представим, что для завершения бизнес-процесса нам необходимо пройти пошаговые модули: A. B, C, D. Объект, созданный в модуле A, становится доступным в модуле B. Объект, созданный в модуле B, а также объект, созданный в модуле A стать доступным в модуле C и т. д.

В этом случае пользователь должен знать порядок работы с системными модулями, чтобы иметь возможность вносить необходимые изменения. Также, если процесс работы с системой изменился (изменилась бизнес-модель или модель домена), пользователь может адаптироваться к новому процессу без изменений в пользовательском интерфейсе.

Все в порядке, пока система не используется небольшим количеством людей, когда нет проблем научить их пользоваться ею. Как насчет системы доставки для большого числа пользователей?

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

Но здесь кроется хитрое использование паттерна MVC. Как видно из рисунка ниже, заманчиво сослаться из представления модуля «А» (Вид) непосредственно к контроллеру (контроллеру) модуля «В», из модуля «В» в модуль «С», из модуля «С» в ». D ‘и т. Д.  

(Или от контроллера модуля «А» к контроллеру модуля «В». Или, что еще хуже, от контроллера модуля «А» до представления (вида) модуля «В»)

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

И вам необходимо жестко кодировать бизнес-логику в операторах if / else, чтобы иметь возможность поддерживать различные варианты A, B, C, D. К сожалению, такой подход довольно часто используется для создания приложений.

Как вернуть прежнюю слабую связь с системными модулями, но сохранить описанные бизнес-процессы внутри.

Для этого вам нужно перенести конфигурацию бизнес-процессов из модулей и разместить их отдельно. Для обеспечения взаимодействия пользователей и всех модулей через один Root или Front Controller. В этом случае контроллер будет извлекать из конфигурации, какие модули в каком порядке предоставить пользователю. Модули будут связываться через корневой контроллер посредством событий, чтобы обеспечить подход слабой связи. 

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

<?xml version="1.0"?>
<application initial="A">
    <module id="A">
        <on event="next" to="B"/>
    </module>
<module id="B" >
<on event="previous" to="A"/> <on event="next" to="C"/> </module>
<module id="C">
<on event="previous" to="B"/> <on event="next" to="D"/> </module>
<module id="D">
<on event="previous" to="C"/> <on event="finish" to="finish"/> </module>
<on event="cancel" to="cancel"/> <final id="finish" /> <final id="cancel" /> </application>

В этом случае довольно просто изменить поведение системы, просто удалив некоторые шаги из конфигурации:

<?xml version="1.0"?>
<application initial="A">
    <module id="A">
<on event="next" to="D"/> </module>
<module id="D">
<on event="previous" to="A"/> <on event="finish" to="finish"/> </module>
<on event="cancel" to="cancel"/> <final id="finish" /> <final id="cancel" /> </application>

Для настройки состояний модуля и переходов между ними очень удобно использовать конечные автоматы (Finite State Machine). После введения наследования и полиморфизма в конфигурацию он становится очень мощным инструментом для описания бизнес-процессов. Для хорошей наглядности мы использовали XML-формат файлов конфигурации, но это также может быть некоторая реализация Domain Specific Language, чтобы иметь возможность проверять конфигурацию во время компиляции.

Примерами таких конечных автоматов в мире Java могут служить:

· Spring Web Flow  —  расширение Spring MVC, и поэтому неплохо использовать с моделью HTTP Request / Response.   

·   Lexaden Web Flow   — создан специально для быстрой разработки гибких корпоративных приложений AJAX Vaadin.

Основное отличие заключается в том, что  Spring Web Flow   в основном создается для сред, тесно связанных с моделью HTTP-запросов / ответов, и поэтому может быть неудобно использовать его с компонентными инфраструктурами AJAX, такими как Vaadin . Страница будет постоянно обновляться, а преимущества AJAX будут игнорироваться.

Вместо   этого Lexaden Web Flow предоставляет всю мощь описанного подхода на уровне запросов AJAX. Используя все лучшее из компонентной модели Vaadin, она позволяет создавать гибкие, масштабируемые и очень надежные корпоративные приложения.

PS статья «  Создание расширенной навигации для корпоративных приложений»  подробно описывает решение, основанное на Lexaden Web Flow.