Проблемы понимания MVC в ASP.NET MVC и не только

Случалось ли вам делать рефакторинг "толстых" контроллеров? Приходилось ли создавать многоэтажные модели представлений? Добавлять в представление данные и переписывать при этом код контроллера? Казалось ли вам, что что-то идёт неправильно?


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


Взгляните на это классическое действие "толстого" контроллера:


public ActionResult AddComment(int articleId, string content)
{
    // бизнес-логика
    var article = ArticleRepository.Instance.GetById(articleId);

    if (article == null)
        return View("ArticleNotFound");

    var comment = new Comment
    {
        ArticleId = articleId,
        Content = content
    };

    CommentRepository.Instance.Add(comment);

    //формирование модели представления
    var viewModel = new ArticleViewModel
    {
        Article = article,
        Comments = CommentRepository.Instance.GetByArticleId(articleId)
    };

    return View("Article", viewModel);
}

И на этот шаблон представления:


@Model ArticleViewModel
<header><h1>@Model.Article.Title</h1></header>
<article>@Model.Article.Content</article>
<ul>
    @foreach (var comment in Model.Comments)
    {
        <li>@comment.Content</li>
    }
</ul>

Какие здесь есть проблемы?


  • Конечно, бизнес логика в контроллере. Многие с ней умеют бороться, и выносят её с переменным успехом в сервисы предметной области. Здесь обычно людей останавливает проблема понимания термина Model в MVC.
  • Зависимость кода контроллера от того, что кроме самой статьи мы хотим отобразить на её странице. Представление беспечно: оно полностью уповает на то, что контроллер передаст ему все нужные данные. Это следствие непонимания термина View.

И такие ситуации возникают не только в проектах на ASP.NET MVC, а почти на любых MVC-фреймворках. Чтобы бороться с ними, нужно их понять.


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


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


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


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


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


public interface IArticleService
{
    // Другие методы

    // Об успешности операции мы можем узнавать либо из исключений,
    // которые может выбросить этот метод, либо из возвращаемого им значения.
    void AddComment(string commentContent);
}

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


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


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


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


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


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


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


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


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

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


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


Внедрение зависимостей в ASP.NET MVC


Хорошо. Но для того, чтобы следовать всему этому, нужно внедрить зависимости в контроллеры и представления. Как это сделать в ASP.NET MVC? Широко распространена практика внедрения в контроллер через свойства. Эту возможность предоставляют многие библиотеки вроде Autofac или Ninject, но есть и другие варианты, которые следует знать.


Внедрение зависимостей в контроллер через конструктор


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


  1. Используя Autofac или другой инструмент внедрения зависимостей с поддержкой этой функции.
  2. Написав свою собственную фабрику контроллеров, и использовав внутри неё любой инструмент для разрешения зависимостей.

Внедрение зависимостей во View через публичные свойства


В основной линейке фреймворков ASP.NET MVC нет возможности внедрить зависимости в конечный класс представления, так как этот класс не существует до тех пор, пока оно в первый раз не потребуется. В этот момент на лету будет разобран код шаблона, и создастся наследник класса WebViewPage c перегруженным методом Execute из одного из предков — WebPageExecutingBase, содержащим сложный код генерации ответа по шаблону.
Но есть возможность отнаследовать этот класс не от WebViewPage, а от собственного класса с помощью директивы @inherits в начале кода шаблона:


(новый класс-предок представления, файл можно разместить рядом с шаблоном)


using System.Web.Mvc;

namespace ASP
{
    // здесь я упростил параметр типа ArticleViewModel
    // до int-идентификатора статьи
    public abstract class ArticlePageBase: WebViewPage<int>
    {
        // Autofac не требует дополнительных атрибутов для внедрения,
        // но другие инструменты могут требовать.

        // Источник, из которого представление получит статью
        public IArticleRepository ArticleRepository { get; set; }
        // Источник, из которого представление получит комментарии к ней
        public ICommentRepository CommentRepository { get; set; }
        // Рекомендательный сервис, выдающий список статей,
        // имеющих сходство с текущей
        public IArticleRecomendationService RecomendationService { get; set; }
    }
}

(Razor-шаблон представления)


@inherits ArticlePageBase
@{
    // получение нужных данных из предоставленных сервисов
    var article = ArticleRepository.GetById(Model);
    var comments = CommentRepository.GetByArticleId(Model);
    var recommendedArticles = RecomendationService.GetRecomendations(Model);
}
@*Вывод полученных данных*@

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


Логику получения и подготовки данных для отображения, если она слишком сложна, можно написать, перегрузив метод InitializePage предка представления, и сохранив полученные данные в защищённые поля, которые можно использовать в шаблоне:


public abstract class ArticlePageBase: WebViewPage<int>
{
    public IArticleRepository ArticleRepository { get; set; }

    // Свойство, используемое в шаблоне для отображения данных
    protected Article Article;

    protected override void InitializePage()
    {
        Article = ArticleRepository.GetById(Model);
    }
}

@inherits ArticlePageBase
<h1>@Article.Title</h1>

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


@inherits ArticlePageBase
@{
    // получение нужных данных из предоставленных сервисов
    var article = ArticleRepository.Get(Model);
    var comments = CommentRepository.GetByArticleId(Model);
    var recommendedArticles = RecomendationService.GetRecomendations(Model);
}
<h1>@ArticleService.Get(Model).Name</h1>

<header><h1>@article.Title</h1></header>
<article>@article.Content</article>
<ul>
    @foreach (var comment in comments)
    {
        <li>@comment.Content</li>
    }
</ul>
<ul>
    @foreach (var recommendedArticle in recommendedArticles)
    {
        // Вывод ссылки на рекомендуемую статью
    }
</ul>

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


Внедрение зависимостей во View в ASP.NET MVC Core


Движок Razor в ASP.NET MVC Core позволяет внедрить зависимость с помощью директивы @inject в начале шаблона. На самом деле происходит всё то же создание свойства, но уже не в предке представления, а в самом его классе, генерируемом движком:


@model int
@inject IArticleRepository ArticleRepository
@{
    var article = ArticleRepository.GetById(Model)
}
<h1>@article.Title</h1>

Но для этого необходимо, чтобы этот интерфейс был зарегистрирован в методе ConfigureServices класса Startup:


public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    // Некоторые действия
    services.AddTransient<IArticleRepository, ArticleRepository>();
    // Некоторые действия
}

После всего этого


Используя эти техники, можно упростить код действия контроллера до следующего:


public ActionResult AddComment(int articleId, string content)
{
    // Вместо исключений можно анализировать
    // возвращаемое сервисом значение. Это не принципиально.
    try
    {
        ArticleService.AddComment(articleId, content);
    }
    catch (ArticleNotFoundException e)
    {
        return View("ArticleNotFound");
    }
    return View("Article", articleId);
}

Теперь он действительно тонкий. На него можно даже написать лаконичные модульные тесты. Вся бизнес-логика находится в модели, а все, что относится к показу — в представлении.


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


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


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


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

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


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


Ссылки


MVC на Википедии


Принцип единственной ответственности (SRP) на Википедии


Внедрение зависимости в контроллер через конструктор с помощью Autofac


Внедрение зависимости в контроллер через конструктор с помощью Castle Windsor


Создание собственной фабрики контроллеров


Внедрение зависимости в представление через свойства с помощью Autofac


Внедрение зависимости в представление в ASP.NET MVC Core


Paul M. Jones об ADR


Статья про ADR на Хабрахабре


ADR на Википедии

Поделиться публикацией
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама
Комментарии 248
  • +3
    Причина в том, что многие MVC-фреймворки не вполне следуют шаблону MVC

    Давайте начнем прямо вот с простого вопроса: какое именно определение шаблона MVC вы используете, и почему вы думаете, что asp.net MVC ему соответствует?

    • –1
      почему вы думаете, что asp.net MVC ему соответствует?
      Да вроде-бы автор такого нигде не заявлял. Наоборот — советы о том как это несоотвествие не усугублять собственным кривым кодом.
      • +2

        Чтобы говорить о "несоответствии", надо сначала найти "соответствие". Иными словами, чтобы говорить, что "там-то модель неправильная", нужно сначала найти определение правильной, и объяснить, почему это определение применимо.

  • 0
    А как таким способом вызывать асинхронные методы сервисов из представления?
    • 0

      В ASP.NET MVC — никак. В ASP.NET Core — с помощью ключевого слова await.

      • 0
        Да, увы, в ASP.NET MVC не получится, все методы синхронные. Сначала и действия контроллеров были синхронными. Нужно ждать асинхронных представлений или искать другие лазейки.
        • –3
          Строго говоря асинхронный метод это когда сервер получает запрос и какой нибудь колбеск а потом по своей инициативе вызывает клиента чтобы отдать ему данные.
          В данном случае клиент все равно ждет ответа а await это просто реализация паралелизма. На самом деле это проблема архитектуры IIS — сделать его многопоточным и никакого await не понадобится.
          Вот на WebSocket уже можно реализовывать асинхронные запросы. Причем они будут асинхронными даже если сервер будет однопоточным и выполнять запросы по очереди.

          • +3

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


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

            Нет, к сетевому уровню асинхронность отношения не имеет. Один и тот же запрос клиент может считать синхронным, а сервер асинхронным — на уровне сети синхронность и асинхронность пропадают.

            • –1
              на уровне сети синхронность и асинхронность пропадают.

              Тогда почему AJAX называбт асинхронным (хотя на самом деле никакой асинхронности там нет — это просто фоновый то есть паралельный запрос)?
              На самом деле понятие синхронности относится к взаимодействию двух компонентов (условно называемых клиентом и сервером). Среда передачи сообщения или запроса сути дела не меняет.

              • +2
                Тогда почему AJAX называбт асинхронным (хотя на самом деле никакой асинхронности там нет — это просто фоновый то есть паралельный запрос)?

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

              • –3
                многопоточный и таковым быть не перестает.

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

                Перекладывание контекста с одного потока в другой — тоже нехило затратная операция. И это никак не решает ни проблему многопоточности ни время ожидания клиентом ответа. Это просто разгружает основной поток выполнения
                для ответа на более быстрые запросы. То есть на самом деле await async это
                костыль для исправления недостатков архитектуры IIS.
                Вот в яве — каждый сервлет выполняется в отдельном треде и никаких костылей не надо.

                • +1
                  зависит от настройки пула. Обычно там один поток.

                  Конечно же, нет.


                  processorThreadMax
                  Specifies the maximum number of worker threads per processor that ASP can create.
                  The default value is 25.

                  (документация)


                  Перекладывание контекста с одного потока в другой — тоже нехило затратная операция.

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

                  • +2
                    Вот в яве — каждый сервлет выполняется в отдельном треде и никаких костылей не надо.

                    Напомните, сколько запросов в секунду тянет сервер на обычных сервлетах?

                    • –3
                      сколько надо столько и потянет. Зависит от ресурсов. Но особенность нынешней ситуации в том что железо сейчас гораздо дешевле труда програмиста.
                      Посему добавить проца или памяти проще и соответственно дешевле чем заниматься хитроумной оптимизацией. Посмотрите на размеры дистибутивов и требования к памяти и количеству ядер для современных приложений. Счет идет на гигабайты.
                      Не говоря уже об облаках и прочих виртуализациях где ресурсы динамически распределяются в зависимости от нагрузки — по сути гиганский
                      await async о котором разработчику не надо парится.

                      • +2

                        Если бы это было так как вы пишите — то не появилась бы в мире Java такая вещь как Netty.

                        • –3
                          в мире JAva как и в прочих мирах каждый день появляется что то новое. Это поиск серебряной пули которому никогда не будет конца.
                        • +1
                          Не говоря уже об облаках и прочих виртуализациях где ресурсы динамически распределяются в зависимости от нагрузки — по сути гиганский
                          await async о котором разработчику не надо парится.

                          … это пока разработчик не платит из своего кармана за эти динамически выделенные ресурсы.

                          • –1
                            Платит владелец приложения но это гораздо дешевле чем платить разработчику за оптимизацию а тем более за переписывание приложения на новомодную асинхронку.
                            • +1

                              Ну вот некоторым владельцам уже оказалось дешевле платить разработчикам за оптимизацию.

                              • –2
                                когда я пишу что невыгодно оптимизировать я имею ввиду ДОПОЛНИТЕЛЬНЫЕ усилия по оптимизации в целом грамотно написанного кода. Особенно всякого рода экономии на спичках или переписывании (а значит и тестировании и отладке) работающего приложения на новый фреймворк только чтобы применить await.

                                конечно если некий умелец написал цикл в цикле а в внутри цикла sql запрос то конешно другого варианта как переписать нет
                                • 0

                                  Ну а если вместо переписывания на новый фреймворк с самого начала писать на новом фреймворке?

                                  • –1
                                    даже если так. Вы надеюсь понимаете что недостаточно поставить перед какой угодно функцией await чтобы она стала асинхронной?
                                    И не факт что асинхронность даст существенный прирост производительности с учетом такой дорогостоящей операции
                                    как перекладывание контекста из потока в поток.
                                    Ведь железо становится не только дешевым а и более быстродействующим. Может на обычном диске и есть смысл делать await для чтения небольшого файла но в SSD вряд ли.

                                    Если речь не о фейсбуке то файл будет прочитан и оддан (и соответственно освобожден поток) быстрее чем придет следующий запрос пользака.

                                    • +1

                                      Зависимость обратная: если операция асинхронная, то перед ней нужно писать await. Соответственно, если в каком-то контексте нельзя писать await — значит, любые асинхронные операции запрещены.

                                      • +1
                                        речь о том что для await функция должны быть соответственно заимплементировна. То есть дополнительная работа а не просто ключевое слово.
                                        • +1

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

                                          • –1
                                            если все ее зависимости имеют асинхронные версии.

                                            если. Но не всегда можно обойтихсь готовыми библиотеками.
                                            • +1

                                              Как минимум, у TcpServer, TcpClient, UdpClient и NetworkStream есть все необходимые асинхронные операции. А значит, реализовать любой сетевой запрос асинхронным образом — не проблема. Да и у FileStream асинхронные операции тоже присутствуют.


                                              Все плохо только с асинхронным открытием файла и асинхронными DNS-запросами.

                                              • +1

                                                … еще HttpClient, все основные операции поверх SqlClient, и генерящиеся прокси в WCF-ных клиентах. Так что реально покрыто почти все рутинное.

                                      • +2
                                        Если речь не о фейсбуке то файл будет прочитан и оддан (и соответственно освобожден поток) быстрее чем придет следующий запрос пользака.

                                        Это пока у вас один пользователь. А когда у вас запросы реально идут в параллель, а под асинхронией у вас лежат не локальные файлы, а сетевые запросы — тут-то профит и начинает чувствоваться.

                                    • +2
                                      когда я пишу что невыгодно оптимизировать я имею ввиду ДОПОЛНИТЕЛЬНЫЕ усилия по оптимизации в целом грамотно написанного кода.

                                      Это тоже бывает выгодно. А еще у людей разное понимание "грамотно написанного кода", и часто сначала выпускают неоптимальную, но работающую версию, а потом ее оптимизируют.


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

                                      • –1
                                        весь нынешний .net туда уверенно ползет.

                                        Ну в разработке каждый день возникает новый модный тренд куда все ползут независимо от здравого смысла. Стадное чувство.
                                        Яркий пример — нынешнее яваскриптовое безумие.

                                        А в случае с .NET так и вариантов нет больше. Решили в майкрософте что надо влепить паттерн MVC в ASP.NET и все — других то вариантов нет. Тоже с асинхронкой. Вместо решить вопросы с оптимизацией потоков переложили эту проблему на разработчика.
                                        То есть разраб кроме писать собственно веб приложение должен еще и заботится о его распарралеливании.

                                        • +1
                                          Ну в разработке каждый день возникает новый модный тренд куда все ползут независимо от здравого смысла.

                                          Вот только не это "модный тренд", а осознанное решение MS, которые имеют для этого вполне описанные основания.


                                          А в случае с .NET так и вариантов нет больше.

                                          Ну да, и именно поэтому надо уметь писать и работать с асинхронным кодом.


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

                                          А напомните, какие именно вопросы с оптимизацией потоков должен был решить MS?


                                          То есть разраб кроме писать собственно веб приложение должен еще и заботится о его распарралеливании.

                                          Да нет, в общем-то. Вы можете запариться и писать без асинков, asp.net приложение все равно будет работать параллельно. Как и работало с самой первой версии.

                                          • –2
                                            а осознанное решение MS, которые имеют для этого вполне описанные основания.

                                            типа как выкупить у нокии мобильный бизнес и спустить его в унитаз. Или заниматься бесконеным перекладыванием иконок меню в скайпе вместо заставить его нормально работать.
                                            Ну да, и именно поэтому надо уметь писать и работать с асинхронным кодом.

                                            вот и я об этом. Не потому что это разумное решение а потому что вариантов нет.
                                            А напомните, какие именно вопросы с оптимизацией потоков должен был решить MS?

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

                                            тогда нафига await. Сделайте чтобы внутри все работало и не пудрите людям мозги пусть занимаются решением прикладных задач.
                                            • +1
                                              Веб разработчик вообще не должен заморачиватся что там у них за проблемы.

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


                                              Но вы говорите, что есть проблемы, которые надо было решить. Какие?


                                              тогда нафига await.

                                              Чтобы решить проблему нехватки потоков.


                                              Сделайте чтобы внутри все работало

                                              Сделали. Работает. Но вот беда, людям недостаточно получившейся производительности. Да, тем самым, которые прикладные задачи решают.

                                          • 0

                                            Вот только ключевая проблема оптимизации потоков — в самом их наличии...

                  • 0

                    К сожалению, в ASP.NET MVC рендер представления синхронный, что ограничивает в возможности запроса дополнительных данных непосредственно из шаблона. Говорят, в ASP.NET Core все немного по-лучше.


                    Но я бы не стал даже в ASP.NET Core запрашивать из шаблона основные данные, как вы сделали с var article = ArticleRepository.GetById(Model). Хотя бы потому что в некоторых случаях следует отображать данные которые еще никуда не сохранены и существуют лишь в памяти. Например, при попытке отправки невалидно заполненной формы без AJAX.

                    • 0
                      Согласен с вами. Да, этот пример просто показывает возможность, он не диктует, как вам поступать. Можно передать в представление сущность статьи. Это нормально (выше было сказано, что ViewModel часто может стать просто сущностью). Но список комментариев к ней, рекомендации и другая подобная информация должна получаться самим представлением.
                    • –2
                      Несоответствие именно в том, что конкретно для ASP.NET MVC нет специального места для размещения логики представления, но его можно получить указанными в статье способами. Они снимают с контроллера и модели зависимость от представления.
                      На счет модели — тут нельзя сказать, как она должна быть организована. Для каждой задачи она своя. Важно лишь то, что в нее должен быть включен и функционал предметной области, не только доступ к данным, и именно к нему и должен обращаться контроллер.
                      • 0

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

                        • 0
                          Да, извините. Я руководствуюсь такой схемой:
                          М — полнофункциональная модель предметной области. Не имеет связи ни с контроллером, ни с представлением.
                          V — средство отображения, кроме шаблонов обладающее собственной логикой (порой и сами шаблоны не нужны, если вывод происходит в других форматах). Имеет связь с моделью, но обычно только на извлечение данных. И имеет связь с контроллерами (конкретно здесь не напрямую, а через запрос и его маршрутизацию).
                          C — набор действий — конечных точек маршрутизации. Имеет связь с моделью: переводит действие пользователя на её язык, и связь с представлением: выбирает, какое нужно отобразить.
                          • +1

                            А почему вы считаете, что это определение применимо к asp.net MVC, хотя документация и литература (ну вот например Эспозитовский Programming Microsoft ASP.NET MVC) говорят об обратном? Вот одна цитата:


                            In general, there are at least two distinct models—the domain model and the view model. The former describes the data you work with in the middle tier and is expected to provide a faithful representation of the domain entities. [...] The view model just describes the data being worked on in the presentation. [...] two distinct models logically exist, and coexist, in a typical layered web solution. You might decide that for your own purposes the two models nearly coincide, but you should always recognize the existence of two distinct models that operate in two distinct layers.

                            Если опираться на это описание, то предлагаемое вами решение для структурирования всех трех компонентов становится полностью неприемлемым.


                            Я не говорю, заметьте, что это решение неприемлемо вообще. Я говорю всего лишь, что asp.net MVC построен на другой модели, и пытаться навязать ему вашу будет болезненно.

                            • 0
                              Согласен с вами. Не совсем применимо. Да, примерно здесь как раз и находится основная несостыковка этого шаблона и их реализации. Тем не менее приблизиться к шаблону можно, и я показываю, как. Приходится писать класс-предок представления или использовать Helper-классы из слоя View. Будет хорошо, если в следующих версиях фреймворка это будет проще. Но достигаемое разделение ответственности между слоями сыграет хорошую службу, повысит тестируемость и гибкость приложения.
                              • +1
                                Да, примерно здесь как раз и находится основная несостыковка этого шаблона и их реализации.

                                Ээээ… нет. Вы почему-то считаете, что в asp.net MVC реализован тот шаблон, который вы описали выше, просто "неправильно". А на самом деле там просто реализован шаблон Model2, и вот он как раз реализован правильно и логично.


                                Тем не менее приблизиться к шаблону можно, и я показываю, как.

                                А зачем? Почему просто не использовать Model2?


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

                                А если ничего не вызывать из View, внезапно, тестируемость становится еще лучше (а разделение как было, так и осталось, потому что весь Model2 — это один слой, presentation, а границей в domain является контроллер).

                                • 0
                                  Хм, да, вы правы. Используется Model 2. Но разве вам не кажется, что у него есть изъяны?
                                  По поводу тестирования — зависимости, которые внедряются в эти слои, обычно тестируются отдельно, а View тестируется через связку виртуального браузера и Page Object Pattern
                                  • 0
                                    Но разве вам не кажется, что у него есть изъяны?

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


                                    View тестируется через связку виртуального браузера и Page Object Pattern

                                    Вот именно этого я и хочу избежать. View тестировать тяжело, поэтому чем меньше в нем будет кода, который надо тестировать, тем лучше. Из этого вытекают view-specific models, а дальше, собственно, мы и приходим к классическому Model2.

                                    • 0
                                      А как бы вы отнеслись к простому модульному тестированию класса-предка представления, если не делать его абстрактным, и всю логику поместить в него? Ведь Razor по большому счету просто добавляет метод рендеринга шаблона.
                                      • 0
                                        А как бы вы отнеслись к простому модульному тестированию класса-предка представления, если не делать его абстрактным, и всю логику поместить в него?

                                        … и что будет публичным тестируемым интерфейсом этого класса? Покажите пример.


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

                                        • 0
                                          Например, свойства, в которые будут помещаться «подготовленные» для отображения данные после исполнения метода InitializePage.
                                          • +1

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

                                            • 0
                                              Нет, потому что контроллер не занимается его наполнением
                                              • 0

                                                А пока не важно, кто этим занимается. Важно, что по смыслу это view model — данные, подготовленные для отображения.

                                      • 0

                                        Зачем отдельно тестировать тривиальную композицию работающих и протестированных сервисов?

                                        • 0
                                          Это уже другой вопрос, но она может быть и не такой тривиальной.
                              • +2
                                М — полнофункциональная модель предметной области. Не имеет связи ни с контроллером, ни с представлением.

                                Не очень понятно, что такое «полнофункциональная», но да, она не должна иметь ничего общего с другими компонентами
                                V — средство отображения, кроме шаблонов обладающее собственной логикой
                                View может обладать своей логикой, но реализовывать ее. Строго говоря, в нем и логики нет, ее реализует средство управления отображением.
                                C — набор действий — конечных точек маршрутизации.
                                Нет! базовый класс Controller в ASP.NET MVC — таковым является, потому как определяем какие данные принять и какой view вернуть. Но Контроллер в MVC не является средством маршрутизации.

                                Вообще, в статье, на мой взгляд, поднято несколько проблем, заслуживающих внимания и пояснения. Но вот пояснения в некоторых случаях только больше путают.
                                На Хабре было две замечательные статьи по мотивам публикаций Реенскауга, где рассказывается, что именно «прородитель MVC» имел в виду код каждым компонентом системы.
                                Один
                                Два
                                • 0
                                  Полнофункциональная модель — это когда в ней есть функционал для всех возможных действий над ней. Есть счет — должен быть какой-то класс-менеджер, или что-то иное, с помощью которого можно этот счет открыть, закрыть, пополнить, получить какие-то связанные с ним данные и т.п.

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

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

                                  Да, я понимаю. Я разбирал этот шаблон (и других его родственников) достаточно глубоко, и не только в вебе. Конкретно — в десктопных приложениях и в игровой архитектуре. Но это тема для отдельной статьи.
                          • 0
                            • Нет необходимости внедрять все зависимости, необходимые для целой группы действий, достаточно лишь тех, которые нужны для конкретного действия.
                            • Нет дилеммы, как сгруппировать действия в контроллеры: по иерархии страниц или по смыслу, так как действия — отдельные классы. Можно организовать произвольное дерево папок с такими классами.

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

                            • –1
                              Очень хорошее замечание, спасибо! Но согласитесь, даже в этом случае не всегда каждое действие такого контроллера будет использовать все зависимости, внедренные в него.
                              Кстати, есть возможность внедрять «ленивые» зависимости, инициализирующиеся при первом обращении, это тоже снижает нагрузку. Тем не менее с точки зрения принципов SOLID нет никакой необходимости группировать действия. Напротив, индивидуальные чействия чище.
                              • 0
                                Зато такая необходимость есть с точки зрения организации кода. Вы же тут в посте уже объяснили что идеальное действие — в 9 строчках. Что, на каждые 9 строчек кода создавать отдельный файл?

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

                                  В Asp net core можно зависимости в action методы внедрять, ага

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

                                альтернативный шаблон — ADR

                                ADR конечно ближе к здравому смыслу но непонятно зачем что то изобретать да еще и вводить новую терминологию а потом объяснять чем домейн отличается от модели.
                                На самом деле наиболее разумный подход компонентный. Раз мы уж говорим о .NET то это старый добрый WebForms. Все что майкам надо было сделать — выкинуть визуальный редактор чтобы не мешал верстке (ведь в ASP.NET MVC его все равно нет)
                                и осталась бы логичная компонентная событийная модель, персистентностью состояния страницы, и с взаимодействием разработчика с компонентами (элементами страницы) через их свойства не заморачиваясь как оно там передается через HTTP.
                                Остается ждать или попробовать самим реализовать ADR-фреймворк на .NET.

                                Ну вот я себе компонентный реализовал и вполне доволен.

                                • 0
                                  Проблема понимания MVC в том что этот паттерн абсолютно неестественнен для веба.

                                  "Классический" — да. Model2, который в asp.net MVC и JSP — совершенно естественнен.

                                  • –1
                                    Если оно такое естественное то откуда все это бесконечные дискуссии (включая эту) о том как должны взаимодействовать компоненты, должен контроллер передавать данные от модели представлению или не должен и т.д. и т.п. Как то далековато от «естественного». Паттерн по определению должен быть однозначен — иначе это вообще не паттерн хоть модель два хоть модель стопицот.
                                    • 0
                                      Если оно такое естественное то откуда все это бесконечные дискуссии (включая эту) о том как должны взаимодействовать компоненты

                                      Во многом — из непонимания, какой же именно паттерн используется. Еще — из-за эволюции паттерна со временем. Дело, однако в том, что эти дискуссии возникают не только для серверной имплементации паттерна (т.е., того, что вы назваете "вебом"), но и для клиентской, а это как раз изначальное его (паттерна) место.


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

                                      • +1

                                        у MVC нет проблем, проблема часто в понимании того что MVC это паттерн для уровня пердставления, а не для всего приложения.

                                        • 0
                                          Да, кстати, именно по этому строение модели всегда поверхностно освещается при обсуждении MVC. Нет каких-то законов, говорящих, какой ей быть, кроме предоставления API
                                          • 0
                                            И не надо никаких законов. Модель — место где живут бизнес данные и бизнес логика. Посему какой ей быть зависит от реализации. Может быть бекенд в виде сервера приложений а может быть просто БД с хранимками.
                                            Но в вебье приходится применять некую искуствено созданную структуру в виде класса по имени Model. При чем этих «моделей» десятки хотя по сути у приложения одна единственная модель.

                                            • 0

                                              presentation layer
                                              вот здесь находится mvc
                                              domain layer
                                              а здесь находится бизнес логика
                                              data soure layer
                                              а вот тут уже данные и т.д.
                                              Из вашего комментария получается что M из MVC размазано по всему приложению...

                                              • 0

                                                Ну если быть совсем занудным, то M из классического MVC находится на границе presentation-domain. То есть для V/C M — это и есть domain layer, точнее, его фасад, за которым спрятано все остальное. Но, повторюсь, это для классического MVC, не для Model2.

                                                • 0

                                                  да, полностью согласен, я скорее хотел сказать, что если мы обсуждаем mvc, ну или в нашем случае model2, то паттерны достаточно понятны, а споры скорее происходят из-за того что часто их пытаются наложить на все приложение, хотя они решают конкретные задачи.

                                                • 0
                                                  это просто ваш вариант видения. Именно в этом и проблема паттерна — каждый обясняет его как хочет терминами какими хочет.
                                                  Из вашего комментария получается что M из MVC размазано по всему приложению..

                                                  Оно никуда не размазано — оно находится в ОДНОМ месте ОДНИМ куском.
                                            • 0
                                              ну да лично у паттерна проблем нет. Лишь нет понимания для чего он предназначен и всего делов.
                                            • 0

                                              а model2, это грубо говоря адаптация mvc для веб приложений

                                              • 0
                                                То есть бесконечные обсуждения пробоем применения паттерна только в том что люди не подозревают о существовании некоей сакральной Model2 которая не вызывает вопросов и все ставит на свои места?
                                                • 0

                                                  Это говорит о том, что для веб приложений придумали более подходящий паттерн взамен mvc(но в чем то похожий), но почему-то постоянно говорят про mvc и как раз возникает много споров.

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

                                                    • 0
                                                      Но если даже переименовать, проблем это не особо убавит потому как архитектурно эти решения все равно неудачны для веба

                                                      … а вот это совершенно не очевидно.


                                                      Почему то нет дискусий что такое паттерн например singleton.

                                                      Зато есть дискуссии, стоит его применять, или нет. И их не сильно меньше, чем дискуссий про MVC.


                                                      И не потому что он проще а потому что там все четко и понятно.

                                                      Дадада, особенно в условиях конкурентного доступа и ленивой инициализации.

                                                      • 0
                                                        Зато есть дискуссии, стоит его применять, или нет.

                                                        вполне логично. Как и дискусия какой применять язык програмирования или технологию. В случае с паттерном MVC монополия. Особенно это касается нового поколения разработчиков которые не представляют что веб и MVC это не то же самое.
                                                        • 0
                                                          В случае с паттерном MVC монополия.

                                                          Эээ… что? Где монополия? У меня вот веб-фреймворк безо всякого MVC (и Model2).

                                                          • 0
                                                            Особенно это касается нового поколения разработчиков которые не представляют что веб и MVC это не то же самое.

                                                            Ну почему же? https://en.wikipedia.org/wiki/Architectural_pattern
                                                            новое покаление разработчиков могут как минимум перейти по этой ссылке и начать изучение паттернов.
                                                            А опытное покаление разработчиков в это время будет проектировать приложения.
                                                            Обычно так оно и происходит.
                                                            Я как не очень опытный разработчик, читаю комментарии более опытных… так что не какой монополии.

                                                            • 0
                                                              новое поколение разработчиков могут как минимум перейти по этой ссылке и начать изучение паттернов.

                                                              никто никуда не будет переходить. Все будут смотреть на типовые готовые решения которые все на MVC. Даже там где есть варианты как в PHP все равно большинство фреймворков на MVC. Просто потому что так сделал Zend которому пофиг как оно на практике.

                                                              • 0

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


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


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


                                                                У меня вот веб-фреймворк безо всякого MVC (и Model2).
                                                                • 0
                                                                  Если вы про ZendFramework, то особого его влияния на другие фреймворки незаметно. А создатель Symfony явно заявляет, что Symfony не MVC фреймворк. В Symfony Framework есть, по сути, только контроллеры, которым передаётся запрос и ожидается от них ответ. Модель, представление — опционально и реализуются как угодно.
                                                          • +2
                                                            Одна из причин в том, что Singleton — порождающий шаблон ООП, а MVC — архитектурный шаблон
                                                • –1
                                                  Да, MVC не очень хорош для веба. По большому счету тут могут быть полезны разные подходы. Можно ведь делать и одностраничное приложение с логикой представления полностью вынесенной в браузер, оставив на сервере только REST-API. Но чаще хорошо подходят гибридные решения.
                                                  • 0
                                                    Можно ведь делать и одностраничное приложение с логикой представления полностью вынесенной в браузер

                                                    Такие решения более трудоемкие. Это просто попытка изобразить на клиенте некое подобие десктопного приложения. Но как ни крути для веба все таки проще классический подход — сформировать страницу на сервере и выплюнуть готовую в браузер чем реализовывать сотни API для которых кстати, все равно нужен бекенд — ведь сайт обычно — это просто витрина к серверным данным. Особенно странно нагружать клиента (особенно мобильного) тоннами тяжелого яваскрипта в эпоху дешевых облачных вычислений.
                                                    SPA решения оправданы для не небольшого класса задач — каких нибудь браузерных игр или обмена сообщениями в реалтайме типа как в соцсетях… Но подавляющее большинсво сайтов не требуют подобной интерактивности.
                                                    • 0

                                                      В какой то мере я согласен. Да, часто для сайтов SPA не подходит, особенно возникают проблемы с поисковиками.


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

                                                      • 0

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

                                                        • 0
                                                          в соответствии с нынешней модой вытаскивать логику на клиента, там все делается аяксом. Поэтому вместо возвращения одним запросом простой html страницы делается стопицот аякс запросов к API которые загрузят сервер намного больше.
                                                          • 0
                                                            стопицот аякс запросов к API которые загрузят сервер намного больше.

                                                            … почему?

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

                                                                Зато они могут оперировать существенно меньшими данными. И/или вообще не строить HTML (который тоже жрет ресурсы).


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

                                                                • –1
                                                                  Зато они могут оперировать существенно меньшими данными

                                                                  если надо отдать энное количество данных то их по любому надо отдать. Да еще и в json заворачивать.

                                                                  И/или вообще не строить HTML

                                                                  HTML по любому надо отдать. и сколько там того HTML.
                                                                  страницы субъективно быстрее

                                                                  а еще они дергаются и прыгают за каждым движением мыши как судорожные.
                                                                  клиент быстрее теми же серверными ресурсами

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

                                                                  • 0
                                                                    если надо отдать энное количество данных то их по любому надо отдать.

                                                                    Иногда отдача кучи маленьких кусков данных дешевле, чем одного большого.


                                                                    HTML по любому надо отдать. и сколько там того HTML.

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


                                                                    не теми же а БОльшими.

                                                                    Не доказано.


                                                                    при нынешних скоростях трафика и стоимости железа — остальное экономия на спичках.

                                                                    Это вам так кажется. Иногда ускорение (клиентское, click-to-last-byte) может быть на порядок.


                                                                    Особенно если страница сложная и данных не ней разные и зависящиее друг от друга.

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

                                                                • 0

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


                                                                  мой комментарий к строчкам с которыми я согласен


                                                                  Но чаще хорошо подходят гибридные решения.

                                                                  которые я как понимаю Вы упустили.

                                                          • +1
                                                            SPA решения оправданы, как ни странно, для веб-приложений, а не для сайтов.
                                                            • 0
                                                              можете назвать принципиальную разницу? Ну кроме «веб-приложение» круче звучит
                                                              • +1

                                                                Эталонный сайт:


                                                                1. построен вокруг контента;
                                                                2. рассчитан на то что пользователь уйдет с него как только закончит потреблять контент;
                                                                3. имеет большую долю входящих переходов по прямой ссылке.

                                                                Эталонное приложение:


                                                                1. построено вокруг взаимодействия с пользователем и решения его задач;
                                                                2. рассчитано на то что пользователь будет долгое время оставаться в нем или даже на "вечную" работу в фоновой вкладке;
                                                                3. для большинства пользователей начинается со стартового экрана.
                                                                • –1
                                                                  как я и говорил — по сути разницы никакой. Чисто словоблудие.

                                                                  То что вы перечислили — это то же самое только в одном месте называется «решать задачи пользователя» в другом — «потреблять контент».

                                                                  Неудивительно что мы в очередной раз мусолим темы типа что такое MVC
                                                                  • +1
                                                                    Ключевое слово — взаимодействие. У эталонных сайтов его нет.
                                                                    • –2

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

                                                                      • 0

                                                                        Можете считать веб-сайт простейшим веб-приложением типа "Hello world". Вы же не будете устанавливать MVC-фреймворк (настоящий :) ), если всё, что вам нужно — это вывести "Hello world" в консоль?

                                                                        • –1

                                                                          а вот тут я тоже не соглашусь…
                                                                          для меня веб сайт это когда apache отдает файлы по заданному адрессу, а веб приложение это все что имеет логику и построение ответа на запрос пользователя. И если что то формирует ответ в зависимости от запроса пользователя это уже приложение, а не просто отдает html файл. А имя веб-приложение дано так как оно определяем контекст. Но можно сказать и без контекста, приложение.

                                                                          • 0

                                                                            Apache тоже формирует ответ в зависимости от запроса пользователя. То же кэширование взять: 304 отдать или 200 с контентом — чем не логика?

                                                                            • 0

                                                                              Да, если мы берем статусы ответов.
                                                                              Но на формирования контента он не как не влияет, для этого нужны другие инструменты.


                                                                              А почему бы мне не использовть MVC фрейморк для приложения аля "Hello world"?

                                                                              • 0
                                                                                Но на формирования контента он не как не влияет, для этого нужны другие инструменты.

                                                                                Вообще-то, влияет. Если сработало кэширование, сервер отдает пустое тело, если не сработало — актуальное содержимое.

                                                                                • 0

                                                                                  Хм… не точно написал…
                                                                                  Для меня сайт это статические html файлы, тоесть его можно и локально смотреть, не каких других вещей он не требует.


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

                                                                                  • 0

                                                                                    … а выше вы же писали "нет понятия веб приложения и веб сайтов, это по факту взаимозаменяемые слова".


                                                                                    А дальше мы упремся в определение "минимальной логики".

                                                                                    • 0

                                                                                      потому что я не согласен что веб-сайт от веб-приложения отличается....


                                                                                      1. построен вокруг контента
                                                                                      2. построено вокруг взаимодействия с пользователем и решения его задач;

                                                                                      Это всего лишь цели приложения.
                                                                                      А если все же делить, то для меня сайт это статические html, css…
                                                                                      делать классификацию "сайт", "Приложение" по целям или по сложности логики или объему… на мой взгляд не верно.

                                                                                      • 0

                                                                                        Не приложения, а программно-аппаратной системы :) Одних целей оптимально достигнуть с помощью создания сайта, других — приложения. Причём в одной системе могут быть и то, и другое, например, сайт для пользователя, а приложение для администраторов. Часто такую систему называют CMS — приложение для создани ясайтов, по сути.

                                                                                        • 0

                                                                                          да, в самом простом случае.
                                                                                          Но часто выводится не только постоянный контент.
                                                                                          А есть сортировки, фильтрация, формы, система комментариев, поиск…
                                                                                          И это уже по сути приложение, как и со стороны пользователя, так и со стороны администратора сайта.


                                                                                          Не надо забывать что CMS добавляют поболее возможностей окромя того что бы просто накидать страницы, ну если она конечно не написна студентом Васей 2 курса.

                                                                                          • 0

                                                                                            И интересно… почему вы делите CMS на приложение и сайт.


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

                                                                                            • 0
                                                                                              И интересно… почему вы делите CMS на приложение и сайт.

                                                                                              Потому что ничего не мешает сделать CMS, которая генерит полностью статический контент. Собственно, я такие неоднократно делал.

                                                                                              • 0

                                                                                                Ну и значит я пока не замечаю противоречий в своем личном мнении, а все ваши комментарии доказывают это...

                                                                                                • 0

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


                                                                                                  Поэтому классифицировать системы по наблюдаемому поведению несколько оправданнее.

                                                                                                  • 0

                                                                                                    Что тоже не противоричит вроде моему мнению. Так как даже переход по ссылке это запрос пользователя и поведение приложения.

                                                                                                    • +1

                                                                                                      Тогда даже статический сайт, веб-сервер которого маппит 1:1 файлы из докрута, является веб-приложением, а сайтов нет вообще.


                                                                                                      А маппить урлы на файловую систему 1:1 или собирать по ним ответы из шаблонов и баз данных по сложным алгоритма роутинга и т. п. — разницы нет с точки зрения классификации веб-ресурсов.

                                                                                                      • 0

                                                                                                        Ну вот об этом многие и пишут, а весь сыр бор вроде начался с вашего комментария


                                                                                                        SPA решения оправданы, как ни странно, для веб-приложений, а не для сайтов.
                                                                                                        • 0

                                                                                                          Большинство людей "в теме" всё же разделяют сайты и веб-приложения. Критерии разделения не чёткие, но основываются прежде всего на способе взаимодействия пользователя с ресурсом. Условно говоря, они на грани межде вебом и вебом 2.0 :)

                                                                                                          • 0

                                                                                                            википедия относится к веб 2.0
                                                                                                            можете на основе википедии объяснить в чем различие?

                                                                                                      • 0
                                                                                                        Что тоже не противоричит вроде моему мнению

                                                                                                        Которому? Вот этому:


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


                                                                                                        или вот этому:


                                                                                                        "нет понятия веб приложения и веб сайтов, это по факту взаимозаменяемые слова"

                                                                                                        • 0

                                                                                                          вот этому


                                                                                                          потому что я не согласен что веб-сайт от веб-приложения отличается…
                                                                                                          А если все же делить, то для меня сайт это статические html, css…

                                                                                                          ("то для меня сайт" ключевые слова)

                                                                                                • 0

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

                                                                                                  • 0

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

                                                                                      • 0

                                                                                        Apache может формировать динамический контент без дополнительных инструментов из коробки, типа <!--#echo var="DATE_LOCAL" -->


                                                                                        Overengineering в общем случае, даже если минимальное использование ресурсов не было заявлено

                                                                                        • 0

                                                                                          я писал про статические html, css изображения...., что в свою очередь назвал веб-сайтом.


                                                                                          то что там умеет apache или другой сервер к этим файлам не относится, а относится к настройке веб-сервера.


                                                                                          по поводу Overengineering вопрос спорный и скорее должен рассматривать для конкретных случаев.
                                                                                          Сегодня клиенту нужна просто одна главная страница, а через пару релизов уже новости, статьи. Потом он затих на 3 месяца, а после того как проснулся ему нужна интеграция с CRM и т.д… в какой то мере выбирая сразу фреймворк я беру решения на вырост и не обязан использовать сразу его на 100%, но с другой стороны я не попадаю в ситуацию когда через какое то время мне надо будет писать реализацию с нуля всего и вся.

                                                                                      • 0

                                                                                        это не логика взаимодействия именно с пользователем. Это взаимодействие браузера с веб-сервером.


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

                                                                • 0

                                                                  Полагаю, что такой уровень абстракции, как MVC использовать можно как душе угодно. Споры тут неуместны. Готовлю статью как раз на эту тему. Я разобрался как можно точно, без условностей определить как называть контроллер, какие там будут действия, в т.ч. какие нужны зависимости. Каждый для себя определяет такую логику. Кто-то интуитивно, кто-то строит аргументированный вариант использования. В общем случае, усложнять не стоит. Не стоит, например, внедрять во View сервисы доступа к данным, тогда что должен делать контроллер!? Мухи и котлеты — не логично.

                                                                  • 0
                                                                    Как раз, если представление сможет само позаботиться о себе, контроллер перестанет делать эту работу за него. И у него останется вполне себе понятная задача: изменить состояние модели (если это нужно) и выбрать представление для показа.
                                                                    На счет споров — да, отходить от шаблона можно, ничего такого в этом нет, это может быть нужно по разным причинам. Я здесь не для споров, а для того, чтобы помочь кому-то посмотреть глубже в эту абстракцию, увидеть ее суть.
                                                                    • 0

                                                                      Как раз, если представление заботиться само о себе — это уже не MVC, насколько я могу судить… С Вашей логикой, лучше было бы заюзать Pipeline… Я и заюзал бы сам, но придется много кода писать, потому предлагаю четко определить, что такое патерн, шаблон, модель, вьюшка, контроллер и экшн. Когда такие определения появятся, как опора для становления логики использования, можно и писать приложение. Для меня все началось с Castle MonoRail. Весь путь, который был проделан с этой точки, я смог испробовать со всех сторон, и точно могу сказать, что вариантов миллион, но нужна, повторюсь, четкая опора для рассуждений. К сожалению, такой теоритической опоры Вы не предоставили в полной мере. В любом случае, спасибо за статью! Успехов Вам!

                                                                    • 0
                                                                      Я разобрался как можно точно,

                                                                      Приветствую ваш оптимизм но нет. В этом вопросе вообще невозможно разобраться. Уж как нибудь бы уже разобрались за последние лет 15.
                                                                      Не стоит, например, внедрять во View сервисы доступа к данным, тогда что должен делать контроллер!

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

                                                                      • 0
                                                                        Контроллер должен указать предствлению что именно оно должно отрендерить а представление уже само знает какие данные ему для этого надо и где их брать.

                                                                        … и как же выглядит "что именно отрендерить"?


                                                                        (впрочем, этот разговор имеет смысл только в рамках конкретного паттерна. Вы сейчас о MVC или Model2?)

                                                                        • 0
                                                                          и как же выглядит «что именно отрендерить

                                                                          Отрендери профиль пользователя с id=2

                                                                          А представление уже знает как искать пользователя какие поля выбрать откуда подтянуть аватар там и все такое.

                                                                          • 0
                                                                            Отрендери профиль пользователя с id=2

                                                                            И в чем тогда функция контроллера? Который уже, благодаря роутингу и модел-биндингу, получил ровно эту команду.

                                                                            • 0
                                                                              Если запрос был именно таким, то это частный случай, когда контроллеру только и остается, как передать управление представлению. Нормальная ситуация.
                                                                              Если же запрос был каким-то другим, например, «сохранить профиль пользователя», то контроллер сначала повоздействует на модель, и по успеху операции решит, «Отрендерить профиль пользователя с id=2» или показать сообщение об ошибке.
                                                                              • +1
                                                                                Если же запрос был каким-то другим, например, «сохранить профиль пользователя», то контроллер сначала повоздействует на модель,

                                                                                Input model binding + вызов сервиса. Однострочник.


                                                                                и по успеху операции решит, «Отрендерить профиль пользователя с id=2» или показать сообщение об ошибке.

                                                                                Угу. Отрендерить профиль, учитывая PRG, это тот же экшн, что и выше. А (генеричное) сообщение об ошибке обрабатывается стандартным хэндлером.


                                                                                Суммарно три строчки кода на контроллер.

                                                                            • +1
                                                                              В таком случае, имхо, контроллер должен передать представлению как параметр метода render или анлогичного этого пользователя, а уж всё остальное (например, права текущего пользователя для активации кнопки «забанить») представление должно вытаскивать само из инжектированных сервисов.
                                                                              • –1
                                                                                а если нет метода рендер и инжекции? Одна из причин непонимания сути — углубление в, не имеющие к отношения к делу, частности.
                                                                                Еще раз — контроллер предает представлению команду с указанием какой пользователь должен быть показан а не лазит в Бд и другие ресурсы за собственно данными.
                                                                                А еще в некоторых случаях модель сама может сообщать представлению что данные поменялись и надо обновится.
                                                                                • 0
                                                                                  Именно, команду с указанием пользователя. Не идентификатора, а самого пользователя (в рамках бизнес-модели)
                                                                          • 0

                                                                            Знаете, Вы натолкнули меня на мысль: Не слишком ли много в данном патерне MVC неопределенностей? Может быть, тогда это плохой патерн? Если рассматривать вопрос с позиции однозначности применения...

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

                                                                                Про мух я выше писал. А не могли бы Вы подробнее (белее или менее) раскрыть суть ООП, применительно к шаблону проектирования MVC.