Asp.net mvc на реальном примере. теория и вступление

Введение

В наше время сложно найти разработчика, который не слышал бы о паттерне под названием Model-View-Controller или сокращенно MVC, что вообщем не удивительно, с задачей отделения данных от их представления сталкиваешься практически на каждом проекте. Однако, как ни странно, столь же сложно найти разработчика, который действительно четко себе представляет, что такое на самом деле паттерн MVC и как его можно реализовать в конкретной ситуации. Подобное неведение явилось следствием того, что по историческим причинам данной аббревиатурой принято называть не один единственный паттерн, а целое семейство паттернов, призванное отделять представление от модели. Произошло это в силу разных обстоятельств. Отчасти из-за того что MVC не просто паттерн, а довольно объемное архитектурное решение, в котором каждый новый разработчик видел что-то свое и ставя во главу угла особенности своего проекта, реализовывал его по своему. Отчасти же из-за возраста данного паттерна, во времена его изобретения и сами приложения, и графические интерфейсы были существенно беднее чем в наше время, с тех пор они сильно эволюционировали и вместе с ними изменялся и сам паттерн. Данная статья посвящена также одному из паттернов входящих в это семейство, причинам его появления, особенностям применения, преимуществам и недостаткам, а так же описанию сопутствующих паттернов.

Что почитать

  1. Wikipedia: Model-View-Controller (http://en.wikipedia.org/wiki/Model_view_controller)
  2. Twisting The Triad (http://www.object-arts.com/Papers/TwistingTheTriad.PDF) by Andy Bower, Blair McGlashan
  3. GUI Architectures (http://www.martinfowler.com/eaaDev/uiArchs.html) by Martin Fowler
  4. Microsoft Journal: Model-View-Presenter (http://msdn.microsoft.com/msdnmag/issues/06/08/DesignPatterns/default.aspx) by Jean-Paul Boodhoo
  5. Supervising Controller (http://www.martinfowler.com/eaaDev/SupervisingPresenter.html) by Martin Fowler
  6. Passive View (http://www.martinfowler.com/eaaDev/PassiveScreen.html) by Martin Fowler
  7. Presentation Model (http://www.martinfowler.com/eaaDev/PresentationModel.html) by Martin Fowler


Эта статья опубликована в журнале
RSDN Magazine

#2-2006. Информацию о журнале можно найти здесь

Wrapping up

MVC is a framework for thinking about programming, and for organizing your program’s files. To signify the idea that your code should be organized by its function, developers will create folders for each part of MVC. (The idea that apps should be divided based on the function of each part of the code is sometimes referred to as separation of concerns.) If you’ve looked at Codecademy’s Ruby on Rails course, you might have noticed that there is a folder for each part of MVC within every Rails app it introduces.

MVC gives you a starting place to translate your ideas into code, and it also makes coming back to your code easier, since you will be able to identify which code does what. In addition, the organizational standard MVC promotes makes it easy for other developers to understand your code.

RV¶

См.также

  • Pyramid wikipedia

В защиту своего дизайна авторы Pyramid написали довольно большой документ,
который призван развеять мифы о фреймворке. Например, на критику модели MVC в
Pyramid следует подробное объяснение, что MVC «притянут за уши» к
веб-приложениям. Следующая цитата хорошо характеризует подход к терминологии в
Pyramid:

Паттерн RV (Resources-View)

Веб ограничен URL, который и представляет из себя дерево ресурсов или
структуру сайта.

Также протокол HTTP не позволяет хранить состояние и
отправлять/принимать оповещения клиенту от сервера, что ограничивает
возможность отслеживания действий клиента для последующего уведомления модели
на изменение состояния.

Поэтому данные часто используются на «frontend»-е
(например в связке React/Redux), а на стороне сервера формируются только один
раз во время ответа, либо загружаются отдельным запросом при помощи AJAX, или
даже с помощью других протоколов, например WebSocket.

RV фреймворки:

Соглашения в MVC

В проекте MVC применяются два вида соглашений. Соглашения первого вида — это просто предположения о том, как может выглядеть структура проекта.

Например, общепринято размещать файлы JavaScript в папке Scripts. Здесь их рассчитывают обнаружить другие разработчики, использующие MVC, и сюда будут устанавливаться пакеты NuGet. Однако вы вольны переименовать папку Scripts или вообще удалить ее — разместив файлы сценариев где-то в другом месте. Это не помешает инфраструктуре MVC Framework запустить ваше приложение при условии, что элементы <script> внутри представлений ссылаются на местоположение, в котором находятся файлы сценариев.

Соглашения второго вида произрастают из принципа соглашения по конфигурации (convention over configuration) или соглашения над конфигурацией, если делать акцент на преимуществе соглашения перед конфигурацией, который был одним из главных аспектов, обеспечивших популярность платформе Ruby on Rails. Соглашение по конфигурации означает, что вы не должны явно конфигурировать, к примеру, ассоциации между контроллерами и их представлениями. Нужно просто следовать определенному соглашению об именовании для файлов — и все будет работать. При соглашении такого рода снижается гибкость в изменении структуры проекта. В последующих разделах объясняются соглашения, которые используются вместо конфигурации.

Следование соглашениям для классов контроллеров

Классы контроллеров должны иметь имена, заканчивающиеся на Controller, например, ProductController, ShopController. При ссылке на контроллер где-либо в проекте, скажем, при вызове вспомогательного метода HTML, указывается первая часть имени (такая как Product), а инфраструктура MVC Framework автоматически добавляет к этому имени слово Controller и начинает поиск класса контроллера.

Это поведение можно изменить, создав собственную реализацию интерфейса IControllerFactory.

Следование соглашениям для представлений

Представления и частичные представления располагаются в папке:

/Views/ИмяКонтроллера

Например, представление, ассоциированное с классом ProductController, находится в папке /Views/Product

Обратите внимание, что часть Controller имени класса в имени папки внутри Views не указывается, т.е. используется папка /Views/Product, а не /Views/ProductController

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

Инфраструктура MVC Framework ожидает, что стандартное представление для метода действия должно иметь имя этого метода. Например, представление, ассоциированное с методом действия List(), должно называться List.cshtml. Таким образом, ожидается, что для метода действия List() в классе ProductController стандартным представлением будет /Views/Product/List.cshtml.

Стандартное представление используется при возвращении результата вызова метода View() в методе действия, примерно так:

Можно указать имя другого представления:

Обратите внимание, что мы не включаем в представление расширение имени файла или путь. При поиске представления MVC Framework просматривает папку, имеющую имя контроллера, и затем папку /Views/Shared

Это значит, что представления, применяемые более чем одним контроллером, можно поместить в папку /Views/Shared и инфраструктура найдет их самостоятельно.

Следование соглашениям для компоновок

Соглашение об именовании для компоновок предусматривает добавление к имени файла символа подчеркивания _, а сами файлы компоновки помещаются в папку /Views/Shared. Среда Visual Studio создает компоновку по имени Layout.cshtml для всех шаблонов проектов кроме Empty. Эта компоновка по умолчанию применяется ко всем стандартным представлениям через файл /Views/_ViewStart.cshtml. Если вы не хотите, чтобы стандартная компоновка применялась к представлениям, можете изменить настройки в _ViewStart.cshtml (либо вообще удалить этот файл), указав другую компоновку в представлении, например:

Или же можно отключить компоновку для заданного представления:

The Advantages of the MVC Architecture

A common problem faced by application developers these days is the support for different type of devices. The MVC architecture solves this problem as developers can create different interfaces for different devices, and based on from which device the request is made, the controller will select an appropriate view. The model sends the same data irrespective of the device being used, which ensures a complete consistency across all devices.The MVC separation beautifully isolates the view from the business logic. It also reduces complexities in designing large application by keeping the code and workflow structured. This makes the overall code much easier to maintain, test, debug, and reuse.

Особенности архитектурного шаблона MVC

Если оперировать высокоуровневыми понятиями, то архитектурный шаблон MVC означает, что приложение MVC будет разделено, по крайней мере, на три части, которые описаны ниже:

  • Модели, содержащие или представляющие данные, с которыми работают пользователи. Они могут быть простыми моделями представлений, которые только представляют данные, передаваемые между представлениями и контроллерами, или же они могут быть моделями предметной области, которые содержат бизнес-данные, а также операции, преобразования и правила для манипулирования этими данными.

  • Представления, применяемые для визуализации некоторой части модели в виде пользовательского интерфейса.

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

Модели — это определение «вселенной», в которой функционирует ваше приложение. Например, в банковском приложении модель представляет все аспекты банковской деятельности, поддерживаемые приложением, такие как расчетные счета, главная бухгалтерская книга и кредитные лимиты для клиентов, равно как и операции, которые могут использоваться для манипулирования данными в модели, такие как внесение денежных средств и списание со счетов. Модель отвечает также за сохранение общего состояния и целостности данных — например, удостоверяясь, что все транзакции внесены в главную книгу, а клиент не снимает со счета больше денежных средств, чем имеет на то право, или больше, чем имеется в распоряжении самого банка.

Модели определяются также и тем, за что они не отвечают: модели не имеют дела с визуализацией пользовательских интерфейсов или обработкой запросов, т.к. это ответственность представлений и контроллеров.

Представления содержат логику, необходимую для отображения элементов модели пользователю — и ничего более. Они не имеют никаких прямых сведений о модели и не обмениваются данными непосредственно с ней. Контроллеры являются шлюзом между представлениями и моделью — запросы поступают от клиента и обслуживаются контроллером, который выбирает подходящее представление для отображения пользователю и, если требуется, соответствующую операцию, которая должна быть выполнена над моделью.

Каждая часть архитектуры MVC является четко определенной и самодостаточной — это то, что называется разделением ответственности. Логика, которая манипулирует данными в модели, содержится только в модели, логика, отображающая данные — только в представлении, а код, который обрабатывает запросы и ввод пользователей — только в контроллере. При четком разграничении всех частей приложение будет легче сопровождать и расширять в течение его срока существования, независимо от того, насколько большим оно станет.

Модель предметной области

Наиболее важной частью приложения MVC является модель предметной области. Эта модель создается за счет определения реальных объектов, операций и правил, существующих в данной отрасли или роде деятельности, которые должно поддерживать приложение; такая совокупность и называется предметной областью

После этого создается программное представление предметной области — модель предметной области. Для целей ASP.NET MVC Framework модель предметной области — это набор типов C# (классов, структур и т.д.), которые все вместе называются типами предметной области. Операции из предметной области представляются методами, определенными в типах предметной области, а правила предметной области выражаются логикой, заключенной внутри этих методов или путем применения атрибутов C#.

Создавая экземпляр типа предметной области для представления конкретной порции данных, мы тем самым создаем объект предметной области. Обычно модели предметной области устойчивы и долговечны. Существует множество различных способов достижения этого, но наиболее распространенным вариантом остаются реляционные базы данных.

Короче говоря, модель предметной области — это единственное официальное определение бизнес-данных и процессов внутри приложения. Устойчивая модель предметной области является также официальным определением состояния представления предметной области. Подход с применением модели предметной области решает многие проблемы, возникающие при сопровождении приложения. Если необходимо манипулировать данными в модели либо добавить новый процесс или правило, то модель предметной области будет единственной частью приложения, которую придется изменить.

Распространенный способ отделения модели предметной области от остальных частей приложения ASP.NET MVC предусматривает помещение модели в отдельную сборку C#. Такой подход позволяет создавать ссылки на модель предметной области из других частей приложения, но не будет гарантировать отсутствие каких-либо ссылок в обратном направлении. Это особенно полезно в крупномасштабных проектах.

MVC¶

См.также

  • Статья о фреймворке Ruby on Rails
  • Концепция MVC для чайников

MVC (Model-View-Controller: модель-вид-контроллер) — шаблон архитектуры ПО,
который подразумевает разделение программы на 3 слабосвязанных компонента,
каждый из которых отвечает за свою сферу деятельности.

Бешеная популярность данной структуры в Веб-приложениях сложилась благодаря её
включению в две среды разработки, которые стали очень востребованными: Struts и Ruby on Rails. Эти среды разработки наметили пути
развития для сотен рабочих сред, созданных позже.

Паттерн MVC (Model-View-Controller)

  • Model — модель, предоставляющая доступ к данным. Позволяет извлекать данные и менять их
    состояние;
  • View — представление, отображающее данные клиенту. В веб-программировании
    существует в виде конечных данных (HTML, JSON, …), которые получает
    клиент. Может формироваться при помощи генераторов по заданному шаблону,
    например Jinja2, Mako; или систем для построения интерфейсов по разметке,
    таких, как Windows Presentation Foundation (WPF), либо Qt Widgets; или
    описываться декларативно, как это делается в QML и ReactJs.
  • Controller — контроллер, отслеживающий различные события (действия пользователя) и по
    заданной логике оповещающий модель о необходимости изменить состояние системы.

Классические MVC фреймворки:

Альтернатива MVC — ADR

Сам шаблон MVC в контексте веб-разработки тоже имеет некоторые недостатки. Обработчики запросов объединяются в виде методов-действий внутри одного класса-контроллера. Это ведёт к тому, что для того, чтобы совершить одно действие, нужно проинициализировать весь контроллер, внедрив в него зависимости, необходимые для всех его действий. Это тоже нарушение SRP. Так же часто возникает проблема правильной группировки действий по контроллерам.

Пол М. Джонс предложил альтернативный шаблон — ADR (реализованный на PHP), некое подобие которого можно встретить в других библиотеках. У этого шаблона есть преимущества перед MVC:

  • Замена классов-контроллеров с методами-действиями на отдельные классы-действия. Это дает несколько плюсов:
    • Нет необходимости внедрять все зависимости, необходимые для целой группы действий, достаточно лишь тех, которые нужны для конкретного действия.
    • Нет дилеммы, как сгруппировать действия в контроллеры: по иерархии страниц или по смыслу, так как действия — отдельные классы. Можно организовать произвольное дерево папок с такими классами.
    • Нет необходимости использовать Reflection-механизмы для поиска нужного метода и подстановки параметров. Все данные можно передавать через конструктор наряду с зависимостями. Таким образом у действия остается только один метод — «Исполнить», что приводит все действия в соответствие одному интерфейсу.
  • Responder более гибок, чем View в широко известных фреймворках: в зависимости от ситуации он может выбирать, какой шаблон использовать, или вообще ответить в виде XML или JSON или любом другом формате.

Остается ждать или попробовать самим реализовать ADR-фреймворк на .NET.

Всем хорошего кода и тонких контроллеров!

Коротко о паттерне MVC

Как следует из названия, паттерн MVC включает в себя 3 компонента: Модель, Представление и Контроллер. Каждый из компонентов выполняет свою роль и является взаимозаменяемым. Это значит, что компоненты связаны друг с другом лишь некими четкими интерфейсами, за которыми может лежать любая реализация. Такой подход позволяет подменять и комбинировать различные компоненты, обеспечивая необходимую логику работы или внешний вид приложения. Разберемся с теми функциями, которые выполняет каждый компонент.

Модель

Отвечает за внутреннюю логику работы программы. Здесь мы можем скрыть способы хранения данных, а также правила и алгоритмы обработки информации.

Например, для одного приложения мы можем создать несколько моделей. Одна будет отладочной, а другая рабочей. Первая может хранить свои данные в памяти или в файле, а вторая уже задействует базу данных. По сути это просто паттерн Стратегия.

Представление

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

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

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

Контроллер

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

Фактически на каждое действие, которое может сделать пользователь в Представлении, должен быть определен обработчик в Контроллере. Этот обработчик выполнит соответствующие манипуляции над моделью и в случае необходимости сообщит Представлению о наличии изменений.

UML-диаграммы игры Сапер

Прежде чем перейти к написанию кода неплохо было бы заранее продумать архитектуру приложения. Она не должна зависеть от языка реализации, поэтому для наших целей лучше всего подойдет UML.

Диаграмма Состояний игровой клетки

Любая клетка на игровом поле может находиться в одном из 4 состояний:

  1. Клетка закрыта;
  2. Клетка открыта;
  3. Клетка помечена флажком;
  4. Клетка помечена вопросительным знаком.

Здесь мы определили лишь состояния, значимые для Представления. Поскольку мины в процессе игры не отображаются, то и в базовом наборе соответствующего состояния не предусмотрено. Определим возможные переходы из одного состояния клетки в другое с помощью UML Диаграммы Состояний:

Диаграмма Классов игры Сапер

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

Организация архитектуры довольно проста. Здесь мы просто распределили задачи по каждому классу в соответствии с принципами паттерна MVC:

  1. В самом низу иерархии расположен класс игровой клетки . Он хранит позицию клетки, определяемую рядом и столбцом игрового поля; одно из состояний , которые мы описали в предыдущем подразделе; информацию о наличии мины в клетке () и счетчик мин в соседних клетках . Кроме того, у него есть два метода: для циклического перехода по состояниям, связанным с пометками, появляющимися в результате щелчка правой кнопкой мыши, а также , который обрабатывает событие, связанное с щелчком левой кнопкой мыши;
  2. Чуть выше расположен класс Модели . Он является контейнером для игровых клеток . Его первый метод подготавливает игровое поле для начала игры. Метод делает проверку игрового поля на состояние выигрыша и возвращает истину, если игрок победил, иначе возвращается ложь. Для проверки проигрыша предназначен аналогичный метод . Методы и всего лишь делегируют действия соответствующим клеткам на игровом поле, а метод возвращает запрашиваемую игровую клетку;
  3. Класс Представления включает следующие методы: — обеспечивает перерисовку Представления для отображения актуального состояния игрового поля в Модели; — возвращает настройки игры, заданные пользователем; — создает игровое поле на основе данных Модели; и соответственно отображают сообщения о победе и проигрыше;
  4. И наконец класс Контроллера . В нем определено всего три метода на каждое возможное действие игрока: отвечает за нажатие на кнопке «Новая игра» в интерфейсе Представления; и обрабатывают щелчки по игровым клеткам левой и правой кнопками мыши соответственно.

The View (V)

When users interacts with your app, they are interacting with the view layer. It should not contain any business logic. In code terms, you’ll normally see:

  • subclasses: These range from a basic to complex custom UI controls.
  • Classes that are part of UIKit/AppKit.
  • Core Animation.
  • Core Graphics.

Typical code smells found in this layer manifest in different ways but boil down to include anything unrelated to UI in your view layer. This can include network calls, business logic, manipulating models and so on.

Use the following as a checklist when inspecting your view layer:

  • Does it interact with the model layer?
  • Does it contain any business logic?
  • Does it try to do anything not related to UI?

If you answer “yes” to any of these questions, you have an opportunity to clean up and refactor.

Of course, these rules aren’t written in stone and sometimes you’ll need to bend them. Nonetheless, it’s important to keep them in mind.

Well-written view components are often reusable, but don’t focus on that from the start. It’s easy to get caught up in the thought of taking a cool button you built and making it compatible for a dozen different scenarios that your app may never need.

Consider making components reusable only when you actually need to. When you have multiple use cases, that’s the time to make a component more generic.

From a testing perspective, UI testing in iOS allows you to test things like transitions, UI elements having specific attributes or UI interactions working as intended.

Паттерн Publish-Subscribe (Издатель-Подписчик)

Если один или несколько объектов в Вашем проекте должны отслеживать изменения другого объекта — гибким решением будет применение шаблона проектирования Publish-Subscribe.

При изменении своего состояния, издатель оповещает всех своих подписчиков, путем вызова у них какой-либо функции, инициализирующей обновление подписчика. При этом, издатель должен предоставлять функции для добавления и удаления подписчиков. Выделение таких функций в виде интерфейсов (базовых классов подписчика и издателя) позволяет ослабить зависимости в соответствии с принципом инверсии зависимостей (Dependency Inversion Principle) — Издатель будет зависеть лишь от интерфейса подписчика, но не от его конкретного типа .

В качестве примера, рассмотрим табличные процессоры (MS Excel и аналоги), позволяющие строить разные виды графиков и диаграмм по данным таблицы. При изменении данных в таблице, графики в таких системах могут автоматически перестраиваться. Для этого таблица рассылает уведомление об изменении данных всем, кто на нее подпишется.


Шаблон Publish-Subscribe. Пример использования

На диаграмме показаны основные элементы шаблона:

  • AbstractSubscriber, задает интерфейс подписчиков;
  • EyeChart, один из реальных подписчиков (легко могут быть добавлены другие виды диаграмм). Хранит ссылку на издателя, при помощи которой получает его обновленное состояние после получения сигнала об обновлении данных;
  • AbstractPublisher, задает интерфейс издателей. Может реализовывать этот интерфейс (не являться абстрактным), т.к. все издатели должны одинаково добавлять/удалять подписчика и уведомлять их об обновлении;
  • SpreadSheet, таблица с данными, уведомляющая подписчиков об изменении своих данных.

В результате применения шаблона:

  • ослабляется зависимость издателя от подписчика. Остается зависимость лишь от абстрактного класса, что позволяет без модификации кода издателя добавлять новые типы подписчиков;
  • появляется возможность добавлять и удалять подписчиков во время выполнения программы. Издатель не располагает информацией не только о конкретных типах Подписчиков, но и об их количестве. Так, например, во многих играх наряду с картой, отображающей состояние игрового мира присутствует мини-карта. Обе карты являются подписчиками, а игровой мир — издателем, при этом для отключения мини-карты достаточно удалить соответствующий объект и снять его с подписки.

MVC

Модель MVC изначально была основана на серверной веб-разработке и постепенно стала пригодной для клиентской веб-разработки, отвечая ее сложности и разнообразию.

MVC — это аббревиатура от Model-View-Controller, которая делит приложение на три части:

  • Модель(Используется для обработки данных, связанных с бизнес-логикой приложения, и для чтения данных)

  • Посмотреть(Отображаемая страница)

  • Контроллер(Соединитель между M и V используется для управления потоком приложения и бизнес-логикой страницы)

Возможности MVC:

Модель MVC характеризуется разделением задач, то есть модель данных в приложении отделена от бизнес-логики и логики представления. В клиентской веб-разработке разделение кода и слабая связь между моделью (M-данные, операционные данные) и представлением (HTML-элемент данных V-display) упрощают разработку, поддержку и тестирование. Клиентское приложение. Все коммуникации односторонние.

  1. View отправляет команды контроллеру;

  2. После того, как Контроллер завершит бизнес-логику, он требует, чтобы Модель изменила состояние;

  3. Модель отправляет новые данные в представление, и пользователь получает обратную связь.

Процесс MVC:

Есть два типа процессов MVC, которые используются в повседневной разработке.

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

Другой — получить инструкции через контроллер и передать их контроллеру:

Преимущества MVC:

  • Низкое сцеплениеУровень представления отделен от бизнес-уровня, что позволяет изменять код уровня представления без перекомпиляции кода модели и контроллера.
  • Возможность многократного использования
  • Низкая стоимость жизненного цикла
  • MVC снижает техническое содержание разработки и поддержки пользовательских интерфейсов.
  • Высокая ремонтопригодность, Разделение уровня представления и уровня бизнес-логики также упрощает обслуживание и изменение веб-приложений.
  • Быстрое развертывание

Недостатки MVC:

  • Не подходит для малых и средних приложений, Потратив много времени на применение MVC к не очень большим приложениям, обычно перевешивает выгода.

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

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

Приложение MVC:

В начале популярности веб-приложений MVC использовался в серверных приложениях java (struts2) и C # (ASP.NET), а позже в клиентских приложениях появился AngularJS на основе шаблона MVC.

What is MVC

With the project handy, it’s time to start learning about the Model, the View and the Controller. But first, what exactly is MVC?

Note: If you already know the concept of MVC, feel free to skip ahead to the next section, where you’ll start getting into best practices.

MVC is a software development pattern made up of three main objects:

  • The Model is where your data resides. Things like persistence, model objects, parsers, managers, and networking code live there.
  • The View layer is the face of your app. Its classes are often reusable as they don’t contain any domain-specific logic. For example, a is a view that presents text on the screen, and it’s reusable and extensible.
  • The Controller mediates between the view and the model via the delegation pattern. In an ideal scenario, the controller entity won’t know the concrete view it’s dealing with. Instead, it will communicate with an abstraction via a protocol. A classic example is the way a communicates with its data source via the protocol.

When you put everything together, it looks like this:

Each one of these objects is meant to be separate from the other, and each fulfills a specific role. When building an app that uses a specific pattern, in this case MVC, the goal is to adhere to the pattern when building all layers of your app.

Apple’s MVC documentation explains these layers in detail and can give you a good theoretical understanding. From a practical perspective, though, it falls a little short.

In this tutorial, you’ll learn to treat MVC as a pattern and not as a strict rule that you must never break. As is the case with many things in software development, nothing is perfect and neither is MVC. There are gray areas that you’ll run into, but no decision you make is the wrong decision. As long as you don’t have files that are too big, or code that is difficult to expand upon, then you’re likely doing a good job. Use MVC — and other patterns for that matter — as architectural guidelines and foundations for your app.

Having said that, it’s time to look at each layer in more detail.

Проблемы понимания MVC

Model — не схема БД, не сущность и не ORM, а модель предметной области

Очень часто моделью называют классы, отображающиеся на сущности схемы БД. Однако в рамках MVC этот термин имеет другой смысл. Model — это модель предметной области, содержащая всю бизнес-логику приложения. В том числе сущности, различные сервисы, репозитории, фабрики и многое другое. Модель хранит состояние и может его изменять в зависимости от действий над ней.

Часть функционала модели (или весь) может быть даже реализована с помощью внешних сервисов, но с точки зрения контроллера и представления это не важно: модель предоставляет им API: классы данных и сервисы, имеющие методы для каждого действия, которое мы можем совершить с моделью. Модель может существовать в отрыве от нашего веб-приложения, и поэтому её обычно стоит реализовывать в виде одного или нескольких отдельных проектов

В контексте нашего примера стоит создать класс, предоставляющий возможность управления статьями (в частности, добавление комментария) и, желательно, соответствующий интерфейс:

View — не анемичный шаблон, а активный инструмент представления

В веб-разработке часто под View понимается шаблон со специальной разметкой, куда должны быть подставлены данные, предоставленные ему контроллером. При этом он сам не обращается к модели предметной области и не получает оттуда данные. Это приводит к тому, что контроллер должен подготовить для него данные в специальном виде (это вынуждает его нарушать принцип единственной ответственности). А если нужно добавить какую-то информацию в шаблон, приходится менять свойства модели представления и код контроллера или провайдера модели представления (если таковой используется).

Модель представления при этом является обособленным классом, и наполняется не связанными по смыслу свойствами, совокупности которых нельзя даже дать связного названия, кроме как (ещё один плохой признак).

Но в описании MVC говорится, что представление имеет связь с моделью, и может запрашивать у неё данные, а некоторых случаях даже менять состояние модели! (Но от последнего, по моему мнению, по возможности лучше отказаться.)

Если следовать этому правилу, для передачи данных в представление не понадобится модель представления с большим количеством свойств. Скорее всего её вообще не будет, или это будет идентификатор необходимой сущности или сама сущность в крайнем случае. Остальные данные, связанные с ней, представление должно получить само через предоставленные через внедрение зависимости сервисы, принадлежащие Model.

Если многим представлениям приходится схожим образом обрабатывать данные перед показом, могут быть созданы другие классы, помогающие им в этом. Это могут быть не только «Helper»-классы. И, хоть они и не будут шаблонами разметки, они все равно будут относиться к слою View.

Controller — не место для бизнес-логики и подготовки данных для отображения

Контроллер, а в частности его действие (в веб-разработке) является конечной точкой маршрутизации запроса. Всё, что должно сделать действие, это:

  1. Выполнить валидацию запроса (опционально)
  2. Оповестить модель (если это необходимо), и получить ответ (тоже не всегда обязательно)
  3. Отобразить представление, передав ему только действительно важные данные от модели

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

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Adblock
detector