Логика MVC: для просмотра требуется больше данных

#model-view-controller

#модель-представление-контроллер

Вопрос:

Я новичок в MVC и, вероятно, еще не до конца понимаю его логику, и именно поэтому у меня всегда возникают проблемы.

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

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

Итак, теперь предположим, что у меня есть веб-сайт. В нем есть индексная страница (/) и несколько неиндексных страниц (/vacancy /, /about /, /articles/bytag / fun / 5 / и т.д.). Вверху каждой страницы есть логотип. Проблема в том, что я хочу, чтобы логотип был гиперссылкой на страницу индекса на каждой странице моего сайта, кроме самой страницы индекса (потому что я не хочу, чтобы мои страницы содержали гиперссылки на самих себя). Поэтому я хочу «<img src=’logo.png’>» на странице индекса и «<a href=»/»><img src=’logo.png’></a>» на других страницах.

Конечно, я не хочу повторяться и создавать несколько шаблонов (header_index и header_nonindex) с одним и тем же изображением логотипа. Итак, что мне нужно сделать, это проверить, нахожусь ли я на странице индекса в каком-либо месте моего шаблона (то есть внутри части просмотра) и в зависимости от результата добавить или не добавлять тег link.

И здесь я сталкиваюсь с логической проблемой. Я не могу получить адрес в представлении (потому что логически эта часть не имеет ничего общего с запросом пользователя, она преобразует данные, полученные от контроллера). Поэтому мне нужен мой контроллер для отправки определенных данных (например. адрес страницы или логическое значение типа «isIndex») для представления. Но представление не может «требовать» данные от контроллера, представление — это просто способ преобразования данных. Поэтому, если какая-либо конкретная переменная необходима для самого преобразования, добавление ее в контроллер сделало бы представление зависимым от конкретного контроллера, а контроллер — связанным с конкретным представлением, что нарушило бы всю идею абстракции и разделения. Таким образом, нет способа сделать то, что мне нужно, не нарушая логику MVC.

Какую часть этого я понимаю неправильно?

Комментарии:

1. является ли этот C # и ASP.NET MVC 3 и Razor или чистая теория изучения?

2. Скажем, чистая теория изучения.

Ответ №1:

Классическая головоломка, но не особенно изолированная от MVC. В ООП вы хотите повысить согласованность внутри класса и уменьшить связь между классами. MVC поднимает этот же принцип на архитектурный уровень, каждый компонент отвечает за свою активность, но отделен от действий двух других. Это идеальная ситуация, но, как и в ООП, идеал не подразумевает абсолютного разделения. Они используют некоторые модели объектов доступа к контроллерам данных, создают модели представлений и интерпретируют входные данные (обычно как модели в веб-MVC). Представления используют модели представлений и в Интернете являются источником входных данных. Модель, пожалуй, самая изолированная.

Реальность такова, что разделение — это не абсолют, а континуум. У вас больше или меньше разделения по сравнению с другими архитектурными шаблонами. MVC, как правило, находится на «более» разделительном конце архитектурных шаблонов, но не все реализации MVC или даже экземпляры приложений в этих рамках созданы равными в этом отношении. Как говорится, «вы можете написать Fortran на любом языке», что означает, что вы можете, если захотите, нарушать шаблон проектирования в любой степени, которую вы хотите, даже до такой степени, чтобы преобразовать его в другой шаблон.

Это не всегда плохо. Вы должны относиться к этому прагматично. Цель, в конце концов, не в том, чтобы достичь чистой архитектурной реализации. Цель состоит в том, чтобы выполнить бизнес приложения. В вашем случае у вас есть некоторые цели пользовательского интерфейса, которые требуют, чтобы представление имело доступ к некоторым сведениям о том, какой контроллер его отображает. ASP.NET MVC предоставляет это через свойство viewContext, которое, в свою очередь, предоставляет ссылку на контроллер, RouteData и HttpContext.

Вы могли бы использовать их для достижения своих бизнес-целей за счет некоторого искажения архитектурного шаблона, то есть представление теперь обрабатывает некоторый «ввод» и принимает некоторые решения непосредственно на основе этих значений. В качестве альтернативы вы также можете сделать разделение более четким, увеличив сложность ваших моделей представления, либо используя базовую модель, которая содержит некоторые служебные свойства, либо, в MVC, используя ViewBag как расширение каждой модели для тех же целей. Это увеличивает связь с контроллером, поскольку теперь ему необходимо знать, что представлению необходимы эти служебные свойства для корректного отображения. Опять же, это континуум — вы увеличиваете связь, а не создаете связь там, где ее не было.

Я отказался от идеи создания чистого MVC. Да, я хочу оставаться как можно ближе к парадигмам MVC framework. С фреймворком работать проще, чем против него. Однако, когда у меня есть цель, которая заставляет меня нарушать разделение задач (после тщательного изучения, чтобы убедиться, что мне действительно это нужно), я больше заинтересован в том, чтобы сделать это устойчивым и ремонтопригодным способом, чем прыгать через архитектурные обручи, чтобы сделать что-то, для чего фреймворк не подходит или что лучше всего сделать способом, которого фреймворк не предусматривает.

Ответ №2:

Вы правы в том, что 3 компонента MVC необходимо разделить, и их цель — сохранить код чистым и раздельным.

Но это не означает, что они независимы. Это не означает, что вы можете взять любое представление, объединить его с любым контроллером и ожидать, что оно будет работать.

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

Поэтому, когда вы находитесь в контроллере индексной страницы, сообщите этой статической переменной, что вы находитесь на индексной странице, а для всех других контроллеров установите ее по умолчанию (default = вы не находитесь на индексной странице). И тогда вы можете использовать эту статическую переменную в любом представлении, независимо от контроллера.

Комментарии:

1. Идея View (на мой взгляд) заключается в преобразовании входных данных, имеющих определенный предустановленный формат. Таким образом, представление может быть объединено с любым контроллером, который способен отправлять ему данные в этом конкретном формате (и vv). Очень похоже на функции. Допустим, «факториал (int)» принимает целое число и возвращает его факториал (что практически также является преобразованием данных). Я считаю, что он должен работать корректно, пока он получает свое целое число в качестве входных данных, и это единственное условие. Я думаю, что это означает разделение. Если функция требует определенных глобальных переменных, то это не так.

2. Глобальные переменные — плохая идея. Внедрение зависимостей — это правильный путь-