В данной статье я бы хотел рассказать, почему использовать шаблон проектирования MVC недостаточно для создания гибких и масштабируемых приложений. А также предложить варианты решения выявленных проблем.
В самом Model View Controller шаблоне нет ничего плохого. Он решает ту проблему, для которой его придумали — это разделение логики обработки запроса пользователя и логики представления информации.
![mvc](https://habrastorage.org/r/w1560/storage2/1d5/209/dc2/1d5209dc207f8b612481c0a576997143.png)
До изобретения этого шаблона, логика обработки запроса пользователя и логика отображения были тесно переплетены в одном файле. Это очень усложняло поддержку и приводило к множеству ошибок в системе.
![Спагетти код](https://habrastorage.org/r/w1560/storage2/022/d89/9ba/022d899ba3bb840d60a1448d2d9ed971.png)
Использование MVC-шаблона хорошо там, где модули относительно независимы друг от друга. Например, они вызываются из главного меню. Пользователь работает с модулем A, потом открывает модуль B и так далее.
![Слабая связанность](https://habrastorage.org/r/w1560/storage2/294/94f/1b0/29494f1b01e78237eba5dcbd1252301b.png)
В этом случае он должен знать, в какой последовательности работать с модулями системы, чтобы произвести необходимые изменения.
Также если поменялся процесс работы с системой (изменилась бизнес или доменная модель), то пользователь может обучиться новому процессу без внесения изменений в пользовательский интерфейс системы.
Всё хорошо до тех пор, пока системой пользуется небольшое количество людей, которых можно обучить работе с ней.
А что если система поставляется множеству пользователей?
Чтобы упростить использование системы, можно сделать так, чтобы она сама знала, в каком порядке с ней работать и предлагала пользователю дальнейшие шаги.
Но здесь кроется коварство использования MVC-шаблона. Как показано на изображении ниже, велик соблазн ссылаться напрямую с представления (View) модуля 'A' на контроллер (Controller) модуля 'B', с модуля 'B' на модуль 'C', с модуля 'C' на модуль 'D'.
![Сильная связанность](https://habrastorage.org/r/w1560/storage2/21e/d87/671/21ed87671a7c4307fcabb2991ab26e74.png)
(Или же из контроллера модуля 'A' на контроллер модуля 'B'. Или, что ещё хуже, из контроллера модуля 'A' на представление модуля 'B'. )
Бизнес процесс будет жёстко прошит в 3х представлениях (Views). Согласитесь, что не очень-то и наглядно. Изменение бизнес процесса будет также затруднено из-за распределения связей по нескольким файлам. А поддержку нескольких вариантов бизнес логики, где будут, например, связаны модули A, С и D, придется реализовывать через if/else в представлениях (Views).
К сожалению, данный подход очень часто используется для построения приложений.
Как же вернуть былую слабую связанность модулей системы, сохранив описание бизнес процессов внутри неё?
![](https://habrastorage.org/r/w1560/storage2/025/447/613/025447613a8bc563b6bcd45cac8e273b.png)
Для этого нужно вынести конфигурацию бизнес процессов из модулей и поместить её отдельно.
Сделать так, чтобы пользователи и все модули общались через один основной контроллер.
При этом контроллер будет руководствоваться конфигурацией, какие модули, в какой последовательности предоставлять пользователю для работы.
Для конфигурации состояний модулей и переходов между ними очень удобно использовать реализации, основанные на конечных автоматах (Finite State Machine).
Примерами таких реализаций в Java мире могут послужить:
• Spring Web Flow — надстройка над Spring MVC.
• ADF Task Flows от Oracle — реализация очень похожа на Spring Web Flow.
• Lexaden Web Flow — реализация для компонентной модели Vaadin.
Какие вы ещё знаете реализации данного подхода в Java?
Может, есть похожие фреймворки для других языков программирования?
P.P.S. Детали реализации описанного решения для Lexaden Web Flow и Vaadin, подробно описаны в статье: Навигация: вариант реализации для корпоративного приложения
В самом Model View Controller шаблоне нет ничего плохого. Он решает ту проблему, для которой его придумали — это разделение логики обработки запроса пользователя и логики представления информации.
![mvc](https://habrastorage.org/storage2/1d5/209/dc2/1d5209dc207f8b612481c0a576997143.png)
До изобретения этого шаблона, логика обработки запроса пользователя и логика отображения были тесно переплетены в одном файле. Это очень усложняло поддержку и приводило к множеству ошибок в системе.
![Спагетти код](https://habrastorage.org/storage2/022/d89/9ba/022d899ba3bb840d60a1448d2d9ed971.png)
Использование MVC-шаблона хорошо там, где модули относительно независимы друг от друга. Например, они вызываются из главного меню. Пользователь работает с модулем A, потом открывает модуль B и так далее.
![Слабая связанность](https://habrastorage.org/storage2/294/94f/1b0/29494f1b01e78237eba5dcbd1252301b.png)
В этом случае он должен знать, в какой последовательности работать с модулями системы, чтобы произвести необходимые изменения.
Также если поменялся процесс работы с системой (изменилась бизнес или доменная модель), то пользователь может обучиться новому процессу без внесения изменений в пользовательский интерфейс системы.
Всё хорошо до тех пор, пока системой пользуется небольшое количество людей, которых можно обучить работе с ней.
А что если система поставляется множеству пользователей?
Чтобы упростить использование системы, можно сделать так, чтобы она сама знала, в каком порядке с ней работать и предлагала пользователю дальнейшие шаги.
Но здесь кроется коварство использования MVC-шаблона. Как показано на изображении ниже, велик соблазн ссылаться напрямую с представления (View) модуля 'A' на контроллер (Controller) модуля 'B', с модуля 'B' на модуль 'C', с модуля 'C' на модуль 'D'.
![Сильная связанность](https://habrastorage.org/storage2/21e/d87/671/21ed87671a7c4307fcabb2991ab26e74.png)
(Или же из контроллера модуля 'A' на контроллер модуля 'B'. Или, что ещё хуже, из контроллера модуля 'A' на представление модуля 'B'. )
Бизнес процесс будет жёстко прошит в 3х представлениях (Views). Согласитесь, что не очень-то и наглядно. Изменение бизнес процесса будет также затруднено из-за распределения связей по нескольким файлам. А поддержку нескольких вариантов бизнес логики, где будут, например, связаны модули A, С и D, придется реализовывать через if/else в представлениях (Views).
К сожалению, данный подход очень часто используется для построения приложений.
Как же вернуть былую слабую связанность модулей системы, сохранив описание бизнес процессов внутри неё?
![](https://habrastorage.org/storage2/025/447/613/025447613a8bc563b6bcd45cac8e273b.png)
Для этого нужно вынести конфигурацию бизнес процессов из модулей и поместить её отдельно.
Сделать так, чтобы пользователи и все модули общались через один основной контроллер.
При этом контроллер будет руководствоваться конфигурацией, какие модули, в какой последовательности предоставлять пользователю для работы.
Для конфигурации состояний модулей и переходов между ними очень удобно использовать реализации, основанные на конечных автоматах (Finite State Machine).
Примерами таких реализаций в Java мире могут послужить:
• Spring Web Flow — надстройка над Spring MVC.
• ADF Task Flows от Oracle — реализация очень похожа на Spring Web Flow.
• Lexaden Web Flow — реализация для компонентной модели Vaadin.
Какие вы ещё знаете реализации данного подхода в Java?
Может, есть похожие фреймворки для других языков программирования?
P.P.S. Детали реализации описанного решения для Lexaden Web Flow и Vaadin, подробно описаны в статье: Навигация: вариант реализации для корпоративного приложения