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


Причина в том, что многие 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 на Википедии

Комментарии (225)


  1. lair
    20.11.2017 11:51
    +1

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

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


    1. Anarions
      20.11.2017 11:56
      -1

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


      1. lair
        20.11.2017 11:58
        +1

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



  1. adeptuss
    20.11.2017 12:10

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


    1. mayorovp
      20.11.2017 12:14

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


      1. polly5315 Автор
        20.11.2017 12:52

        Да, увы, в ASP.NET MVC не получится, все методы синхронные. Сначала и действия контроллеров были синхронными. Нужно ждать асинхронных представлений или искать другие лазейки.


      1. caballero
        20.11.2017 13:20

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


        1. mayorovp
          20.11.2017 13:32
          +2

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


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

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


          1. caballero
            20.11.2017 13:46

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

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


            1. lair
              20.11.2017 13:50

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

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


          1. caballero
            20.11.2017 14:04

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

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

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


            1. lair
              20.11.2017 14:16

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

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


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

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


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

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


            1. mayorovp
              20.11.2017 14:37

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

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


              1. caballero
                20.11.2017 15:12
                -1

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


                1. mayorovp
                  20.11.2017 15:17
                  +1

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


                  1. caballero
                    20.11.2017 15:40
                    -2

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


                1. lair
                  20.11.2017 15:19

                  Не говоря уже об облаках и прочих виртуализациях где ресурсы динамически распределяются в зависимости от нагрузки — по сути гиганский
                  await async о котором разработчику не надо парится.

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


                  1. caballero
                    20.11.2017 15:39

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


                    1. lair
                      20.11.2017 15:40

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


                      1. caballero
                        20.11.2017 15:57
                        -1

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

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


                        1. mayorovp
                          20.11.2017 16:01

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


                          1. caballero
                            20.11.2017 16:13

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

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


                            1. mayorovp
                              20.11.2017 16:25

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


                              1. caballero
                                20.11.2017 16:48

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


                                1. mayorovp
                                  20.11.2017 16:53

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


                                  1. caballero
                                    20.11.2017 17:02

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

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


                                    1. mayorovp
                                      20.11.2017 17:26

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


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


                                      1. lair
                                        20.11.2017 17:32

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


                            1. lair
                              20.11.2017 16:30
                              +1

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

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


                        1. lair
                          20.11.2017 16:29
                          +1

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

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


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


                          1. caballero
                            20.11.2017 17:17
                            -1

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

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

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


                            1. lair
                              20.11.2017 17:31
                              +1

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

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


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

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


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

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


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

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


                              1. caballero
                                20.11.2017 17:48
                                -1

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

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

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

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

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


                                1. lair
                                  20.11.2017 17:58

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

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


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


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

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


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

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


                            1. mayorovp
                              20.11.2017 17:37

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


  1. mayorovp
    20.11.2017 12:13

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


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


    1. polly5315 Автор
      20.11.2017 12:24

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


  1. polly5315 Автор
    20.11.2017 12:18

    Несоответствие именно в том, что конкретно для ASP.NET MVC нет специального места для размещения логики представления, но его можно получить указанными в статье способами. Они снимают с контроллера и модели зависимость от представления.
    На счет модели — тут нельзя сказать, как она должна быть организована. Для каждой задачи она своя. Важно лишь то, что в нее должен быть включен и функционал предметной области, не только доступ к данным, и именно к нему и должен обращаться контроллер.


    1. lair
      20.11.2017 13:48

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


      1. polly5315 Автор
        20.11.2017 14:03

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


        1. lair
          20.11.2017 14:12

          А почему вы считаете, что это определение применимо к 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 построен на другой модели, и пытаться навязать ему вашу будет болезненно.


          1. polly5315 Автор
            20.11.2017 14:23

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


            1. lair
              20.11.2017 14:28

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

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


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

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


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

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


              1. polly5315 Автор
                20.11.2017 14:50

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


                1. lair
                  20.11.2017 14:53

                  Но разве вам не кажется, что у него есть изъяны?

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


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

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


                  1. polly5315 Автор
                    20.11.2017 15:57

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


                    1. lair
                      20.11.2017 16:31

                      А как бы вы отнеслись к простому модульному тестированию класса-предка представления, если не делать его абстрактным, и всю логику поместить в него?

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


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


                      1. polly5315 Автор
                        20.11.2017 16:41

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


                        1. lair
                          20.11.2017 16:46
                          +1

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


                          1. polly5315 Автор
                            20.11.2017 16:48

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


                            1. lair
                              20.11.2017 16:49

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


                  1. mayorovp
                    20.11.2017 16:05

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


                    1. polly5315 Автор
                      20.11.2017 16:11

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


        1. alexeystarchikov
          20.11.2017 14:51

          М — полнофункциональная модель предметной области. Не имеет связи ни с контроллером, ни с представлением.

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

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


          1. polly5315 Автор
            20.11.2017 15:06

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

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

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

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


  1. mayorovp
    20.11.2017 12:21

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

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


    1. polly5315 Автор
      20.11.2017 12:33

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


      1. mayorovp
        20.11.2017 12:44

        Зато такая необходимость есть с точки зрения организации кода. Вы же тут в посте уже объяснили что идеальное действие — в 9 строчках. Что, на каждые 9 строчек кода создавать отдельный файл?

        Нет, можно конечно несколько классов в один файл запихнуть, но тут тоже кто-нибудь возмутится…


        1. polly5315 Автор
          20.11.2017 12:58

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


      1. HackerDelphi
        22.11.2017 08:15

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


  1. caballero
    20.11.2017 13:40
    -2

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

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

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

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


    1. lair
      20.11.2017 13:51

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

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


      1. caballero
        20.11.2017 14:11

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


        1. lair
          20.11.2017 14:20

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

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


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


        1. mdErrDX5341
          20.11.2017 15:07

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


          1. polly5315 Автор
            20.11.2017 15:10

            Да, кстати, именно по этому строение модели всегда поверхностно освещается при обсуждении MVC. Нет каких-то законов, говорящих, какой ей быть, кроме предоставления API


            1. caballero
              20.11.2017 15:29

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


              1. mdErrDX5341
                20.11.2017 15:38

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


                1. lair
                  20.11.2017 15:42

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


                  1. mdErrDX5341
                    20.11.2017 15:49

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


                1. caballero
                  20.11.2017 15:43

                  это просто ваш вариант видения. Именно в этом и проблема паттерна — каждый обясняет его как хочет терминами какими хочет.

                  Из вашего комментария получается что M из MVC размазано по всему приложению..

                  Оно никуда не размазано — оно находится в ОДНОМ месте ОДНИМ куском.


          1. caballero
            20.11.2017 15:16

            ну да лично у паттерна проблем нет. Лишь нет понимания для чего он предназначен и всего делов.


        1. mdErrDX5341
          20.11.2017 15:13

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


          1. caballero
            20.11.2017 15:21

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


            1. mdErrDX5341
              20.11.2017 16:15

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


              1. caballero
                20.11.2017 16:28

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


                1. lair
                  20.11.2017 16:33

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

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


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

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


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

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


                  1. caballero
                    20.11.2017 16:55

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

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


                    1. lair
                      20.11.2017 16:56

                      В случае с паттерном MVC монополия.

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


                    1. mdErrDX5341
                      20.11.2017 17:13

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

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


                      1. caballero
                        20.11.2017 17:28

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

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


                        1. mdErrDX5341
                          20.11.2017 17:55

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


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


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


                          У меня вот веб-фреймворк безо всякого MVC (и Model2).


                        1. VolCh
                          21.11.2017 08:39

                          Если вы про ZendFramework, то особого его влияния на другие фреймворки незаметно. А создатель Symfony явно заявляет, что Symfony не MVC фреймворк. В Symfony Framework есть, по сути, только контроллеры, которым передаётся запрос и ожидается от них ответ. Модель, представление — опционально и реализуются как угодно.


                1. polly5315 Автор
                  20.11.2017 16:45
                  +1

                  Одна из причин в том, что Singleton — порождающий шаблон ООП, а MVC — архитектурный шаблон


    1. polly5315 Автор
      20.11.2017 13:53

      Да, MVC не очень хорош для веба. По большому счету тут могут быть полезны разные подходы. Можно ведь делать и одностраничное приложение с логикой представления полностью вынесенной в браузер, оставив на сервере только REST-API. Но чаще хорошо подходят гибридные решения.


      1. caballero
        20.11.2017 14:20

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

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


        1. mdErrDX5341
          20.11.2017 18:55

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


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


        1. mdErrDX5341
          20.11.2017 21:44

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


          1. caballero
            20.11.2017 23:01

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


            1. lair
              20.11.2017 23:05

              стопицот аякс запросов к API которые загрузят сервер намного больше.

              … почему?


              1. caballero
                20.11.2017 23:12

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


                1. lair
                  20.11.2017 23:17

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

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


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


                  1. caballero
                    20.11.2017 23:59

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

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

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

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

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

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


                    1. lair
                      21.11.2017 00:06

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

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


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

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


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

                      Не доказано.


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

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


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

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


                1. mdErrDX5341
                  20.11.2017 23:20

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


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


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

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


        1. VolCh
          21.11.2017 08:41

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


          1. caballero
            21.11.2017 10:14

            можете назвать принципиальную разницу? Ну кроме «веб-приложение» круче звучит


            1. mayorovp
              21.11.2017 10:44

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


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

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


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


              1. caballero
                21.11.2017 12:04

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

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

                Неудивительно что мы в очередной раз мусолим темы типа что такое MVC


                1. VolCh
                  22.11.2017 00:02
                  +1

                  Ключевое слово — взаимодействие. У эталонных сайтов его нет.


                  1. mdErrDX5341
                    22.11.2017 00:10
                    -1

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


                    1. VolCh
                      22.11.2017 22:30

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


                      1. mdErrDX5341
                        23.11.2017 23:05

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


                        1. VolCh
                          24.11.2017 18:59

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


  1. Magic_B
    20.11.2017 15:12

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


    1. polly5315 Автор
      20.11.2017 15:19

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


      1. Magic_B
        20.11.2017 15:29

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


    1. caballero
      20.11.2017 23:08

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

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

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


      1. lair
        20.11.2017 23:18

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

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


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


        1. caballero
          21.11.2017 00:01

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

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

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


          1. lair
            21.11.2017 00:06

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

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


            1. polly5315 Автор
              21.11.2017 00:21

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


              1. lair
                21.11.2017 00:25

                Если же запрос был каким-то другим, например, «сохранить профиль пользователя», то контроллер сначала повоздействует на модель,

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


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

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


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


          1. VolCh
            21.11.2017 09:26

            В таком случае, имхо, контроллер должен передать представлению как параметр метода render или анлогичного этого пользователя, а уж всё остальное (например, права текущего пользователя для активации кнопки «забанить») представление должно вытаскивать само из инжектированных сервисов.


            1. caballero
              21.11.2017 10:11

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


              1. VolCh
                22.11.2017 00:05

                Именно, команду с указанием пользователя. Не идентификатора, а самого пользователя (в рамках бизнес-модели)


      1. Magic_B
        21.11.2017 10:15

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


        1. caballero
          21.11.2017 11:58

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


          1. Magic_B
            21.11.2017 12:03

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


            1. caballero
              21.11.2017 12:18

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


          1. lair
            21.11.2017 12:04

            Простыми словами MVC можно описать так — мухи отдельно, котлеты отдельно.

            … это вы описали separated presentation. MVC, конечно, частный случай оного, но надо же тогда и частности описывать.


            1. caballero
              21.11.2017 12:22

              я и описал

              модель (данные), место где эти данные предьявляются пользователю (представление) и та часть приложения которая непосредственно принимает команды управления от пользователя (контроллер)

              подробнее — это уже конкретная имплементация.


        1. lair
          21.11.2017 12:04

          Архитектурным паттернам вообще свойственно быть размытыми. Иначе бы разработка архитектуры ПО уже давно была простой и понятной дисциплиной.


  1. Leg3nd
    20.11.2017 15:24

    Есть мнение, что контроллер — не какае-та мифическая штука, где каждый наделяет его той отвественностью какая придет ему в голову (или еще хуже каждый раз изобретая новые «шаблоны» — MVP и т. д.), а это вполне себе графический компонент, такой же как и View.


    1. polly5315 Автор
      20.11.2017 15:50

      Хороший экскурс в историю


  1. Ordos
    20.11.2017 21:33

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

    <h1>@ArticleService.Get(Model).Name</h1>

    Мы отрендерили h1, вызвали ArticleService.Get, получили exception. Клиенту ушёл битый html.


    1. mayorovp
      20.11.2017 21:36

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


    1. mdErrDX5341
      20.11.2017 22:21
      -1

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


      1. mdErrDX5341
        20.11.2017 22:42

        обращение к тем кто поставил минус)))
        давайте решения данной проблемы, на архитектурном уровне)))


      1. lair
        20.11.2017 22:57

        весь MVC живет в одном слое приложения.


        1. mdErrDX5341
          20.11.2017 23:15

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


          1. lair
            20.11.2017 23:19

            по этому в нем легко менять поведение при сбоях

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


            1. mdErrDX5341
              20.11.2017 23:27

              Вот вот, именно про это я и писал, а так же использую слова view и presentation, так что бы указать разницу паттерна и слоя приложения. Увы на русском языке эти понятия смешиваются.


              я писал


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

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


              1. lair
                20.11.2017 23:34

                … и что? На отображение ошибок это все не влияет.


                1. mdErrDX5341
                  20.11.2017 23:45

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


                  1. lair
                    21.11.2017 00:02

                    … проще по сравнению с чем? Это всегда важный вопрос.


                    1. mdErrDX5341
                      21.11.2017 00:07

                      По сравнению с тем когда бизнес логика лежит монолитном в M из MVC


                      1. lair
                        21.11.2017 00:08

                        Извините, но вы сравниваете M из MVC с M из MVC. Что-то не так.


                        1. mdErrDX5341
                          21.11.2017 00:46

                          я вообще не сравниваю, я говорю о разных сущностях… об m из mvc из уровня представления и о бизнес логике. Фасад для бизнес логики в виде m для mvc проще создать и тестировать чем тянуть целый уровень бизнес логики. я к этому клоню.


                          1. lair
                            21.11.2017 00:49

                            Фасад для бизнес логики в виде m для mvc проще создать и тестировать чем тянуть целый уровень бизнес логики.

                            Это совершенно бессмысленное противопоставление. Чтобы сделать фасад, вам нужно иметь, что за него положить. Будет это "целый уровень" или полтора метода, зависит от сложности домена, а не от чего-то еще.


                            1. mdErrDX5341
                              21.11.2017 01:05

                              Хороший ответ))) соглашусь))) но с другой стороны разрабатывая 1 програмную единицу мне не нужно думать о всем приложении и всех ее зависимостях, что мне позволяет создавать ее не зависимо от всех составляющих огромного приложения


                              1. lair
                                21.11.2017 01:08

                                Разрабатывая "одну программную единицу" вам нужно думать о ее зависимостях. Один конкретный контроллер зависит от его конкретных прикладных (и инфраструктурных) сервисов, вот о них и придется думать. "model как фасад" вам тут никак не помогает (эти сервисы — и есть model в этом понимании), помогает только хорошая инкапсуляция этих сервисов.


                                1. mdErrDX5341
                                  21.11.2017 01:23

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


                                  1. lair
                                    21.11.2017 01:30

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


                                    1. mdErrDX5341
                                      21.11.2017 01:40

                                      Можно немного точнее? я вроде как утверждал что писал о view в mvc и presentation как слое приложения, тоесть я разделял эти два понятия… теперь мне интересно где я ошибаюсь при таком разделении обязаностей кода...


                                      1. lair
                                        21.11.2017 01:46

                                        Я говорю про вашу путаницу с model и "слоем бизнес-логики".


                                        1. mdErrDX5341
                                          21.11.2017 01:56

                                          может я криво пишу… что не исключено, но я пишу о том что M в mvc не является "слоем бизнес логики", и что программная единица построенная на базе паттерна mvc это отдельная единица программного кода. Но в тоже время она использует в любом случае "слой бизнес логики". Но в любом случае это только элемент интерфейса, который в свою очередь не обязан и не должен зависить от "бизнес логики".


                                          1. lair
                                            21.11.2017 02:01

                                            но я пишу о том что M в mvc не является "слоем бизнес логики",

                                            Это ошибка — если мы говорим о "классическом" MVC, конечно.


                                            программная единица построенная на базе паттерна mvc это отдельная единица программного кода.

                                            Нет. "Отдельные" — это view и controller. А model как раз совместно используется доменным слоем и слоем представления.


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

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


                                            Идея MVC, как и других separated presentation-шаблонов в том, чтобы бизнес не зависел от интерфейса. Если вы разорвете еще и обратную зависимость, приложение перестанет выполнять свою функцию.


                                            1. mdErrDX5341
                                              21.11.2017 02:22

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


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


                                              1. lair
                                                21.11.2017 12:07

                                                Если вы под "элементами интерфейса" понимаете элементы управления, то да, они не зависят от бизнес-логики. Но! они заодно и не зависят от MVC (в них почти никогда нет полной триады, а в большей части случаев они вообще живут только во view). И это не говоря о том, что элементы управления есть не только в MVC, и даже не только в separated presentation.


                                            1. mdErrDX5341
                                              21.11.2017 02:43

                                              Я кстати замечу что именно в вебе появилось такое понятие как style guide


                                              1. mdErrDX5341
                                                21.11.2017 02:49

                                                вернее распространилось...


                                              1. lair
                                                21.11.2017 12:07

                                                Можно подтверждающую цитату?


                                                1. mdErrDX5341
                                                  21.11.2017 21:39

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


                                                  Получается что в вебе мы скорее уходим от таких вот подобных элементов?


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


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


                                                  Но если мы будем пытаться смотреть на сайт как на отдельные страницы, то есть воспринимать их как view, то конечно смысли MVC пропадает… Но в данном случае появляется монолит.


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


                                                  1. lair
                                                    21.11.2017 21:46

                                                    При чем здесь цитата.

                                                    При том, что я хочу видеть основания для вашего громкого утверждения.


                                                    допустим нам нужен список новостей и статей, как правило этот список не чем не отличается

                                                    Не отличается между чем и чем?


                                                    по этому для view это почти одинаковые объекты

                                                    Какие объекты одинаковые?


                                                    Получается что в вебе мы скорее уходим от таких вот подобных элементов?

                                                    Не понимаю вопроса.


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

                                                    "Кроссплатформенных" — "интерфейс похожий для самой платформы". Это как вообще?


                                                    В вебе когда туда пришли маркетологи и поняли что сайт не кого не зацепит, решили творить вместе с дизайнерами огого разные интерфейсы для каждого сайта, от сюда и появился styleGuide для интерфейса каждого отдельного сайта…

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


                                                    так что я пытаюсь понять где я ошибаюсь

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


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

                                                    … а это, заметим, почти то же самое, что предлагается в статье.


                                                    1. mdErrDX5341
                                                      21.11.2017 21:56

                                                      … а это, заметим, почти то же самое, что предлагается в статье.

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


                                                      1. lair
                                                        21.11.2017 21:57

                                                        Если это то, что вы пытаетесь сказать, то вам это очень плохо удается.


                                          1. VolCh
                                            21.11.2017 09:36

                                            M в MVC является интерфейсом (программным) к бизнес-логике, от которого зависит, как минимум, C. Будет это абстракция, имплементации которой легко подменять для, например, целей юнит-тестирования интерфейса (клиентского) или конкретные классы бизнес-логике — ваше решение.


                                            1. mdErrDX5341
                                              21.11.2017 21:22

                                              в статье и так имплементации.


                                              1. lair
                                                21.11.2017 21:34

                                                В статье не MVC, уж если быть въедливым.


                                                1. mdErrDX5341
                                                  21.11.2017 21:45

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


                                                  1. lair
                                                    21.11.2017 21:48

                                                    Согласен, так как MVC не возможно создать на стыке веб-браузера и сервера

                                                    Вообще-то, прекрасно возможно — если вы пишете JS-приложение в браузере.


                                                    1. mdErrDX5341
                                                      21.11.2017 22:02

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


                                                      1. lair
                                                        21.11.2017 22:08

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


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


                                                        1. mdErrDX5341
                                                          21.11.2017 22:24
                                                          -1

                                                          ну своеобразный костыль, если брать запрос-ответ, по этому и model2 достаточно отличается от mvc.


                                                          А что бы разбавить это безумие, то добавляются AppConroll..., PageControll..., BundleControll..., RestAPI, Ajax со всеми вытекающими… Я же больше говорю о формировании страницы и многих ее UI элементов, а не пробрасывание на сервере модель во вью, скорее о том что все эти технологии, паттерны надо использовать, так как среда приложений веб-браузер <-> сервер пока так скажем слаба, от сюда и другой архетиктурный паттерн как микросервисы...


                                                          1. lair
                                                            21.11.2017 22:27

                                                            ну своеобразный костыль, если брать запрос-ответ, по этому и model2 достаточно отличается от mvc.

                                                            Это не костыль, это способ получить серверные события на клиенте. Работающий.


                                                            А что бы разбавить это безумие то добавляются AppConroll, PageControll, BundleControll, RestAPI, Ajax со всеми вытекающими…

                                                            А это вообще никак не связано.


                                                            скорее о том что все эти технологии, паттерны надо использовать

                                                            Какие "эти"?


                                                            от сюда и другой архетектурный паттерн как микросервисы...

                                                            Нет, микросервисная архитектура не имеет никакого отношения к веб-браузерам и их общению с сервером.


                                                            1. mdErrDX5341
                                                              21.11.2017 22:32
                                                              -1

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


                                                              1. lair
                                                                21.11.2017 22:34

                                                                чем вам не нравится браузер как архетиктурная точка микросервиса или тонкого клиента?

                                                                Я не знаю, что такое "архитектурная точка".


                                                                1. mdErrDX5341
                                                                  21.11.2017 22:38
                                                                  -1

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


                                                            1. mdErrDX5341
                                                              21.11.2017 22:44
                                                              -1

                                                              нет, но есть паттерн, но правда пока у вас есть возможность реализовать клиент-сервер-умерло соединение… то увы придется смериться с реальностью, от сюда всякие ajax и веб сокеты)))


                                                              1. lair
                                                                21.11.2017 22:48

                                                                AJAX и веб-сокеты появились не в ответ на умирающие соединения. А те, в свою очередь, начали умирать тогда же, когда появились клиент-серверные приложения поверх БД (то есть задолго до MVC), и продолжают умирать до сих пор, и будут умирать дальше, причем, по мере разрастания распределенных систем, все больше и больше. На существующие паттерны это влияет мало, надо просто понимать зону их применимости.


                                                                1. mdErrDX5341
                                                                  21.11.2017 22:56
                                                                  -1

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


                                                                  1. lair
                                                                    21.11.2017 22:59

                                                                    такие вещи как ajaх и веб сокеты появились тогда когда веб браузер перестал быть приложением для гиков…

                                                                    Ничего, что они появились в сильно разное время?


                                                                    а паттерн такой как MVC и наблюдатель пришелся к месту…

                                                                    MVC тут только ни при чем, а так все хорошо.


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

                                                                    Observer — не архитектурный паттерн. А MVC к стандартам бизнеса (не знаю, откуда вы их взяли) имеет мало отношения.


                                                                    И да, при чем тут умирающие соединения?


                                                                    1. mdErrDX5341
                                                                      21.11.2017 23:07
                                                                      -1

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


                                                                      1. lair
                                                                        21.11.2017 23:09

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

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


                                                                        Вот от сюда и растут ноги быстро шагающего JS и CSS.

                                                                        Ни JS, ни CSS никак не могут повлиять на соединение с сервером.


                                                                        И постоянные запросы к серверу именно не устраивают бизнес, а не программистов

                                                                        Бизнесу на эти запросы искренне положить.


                                                                1. mdErrDX5341
                                                                  21.11.2017 23:01
                                                                  -1

                                                                  от сюда и такое развите JS и CSS, так как бизнесу нужен результат… а результат это быстрые деньги.


                                                        1. mdErrDX5341
                                                          21.11.2017 22:50
                                                          -1

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


                                                          1. lair
                                                            21.11.2017 22:52

                                                            А давайте еще вспомним что не клиент запрашивает данные, а его оповещают...

                                                            Это верно не во всякой архитектуре.


                                                            1. mdErrDX5341
                                                              21.11.2017 23:16
                                                              -1

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


                                                              1. lair
                                                                21.11.2017 23:27

                                                                Клиент не будет ждать когда его браузер запросит актуальную информацию,

                                                                Да ладно. Сейчас прекрасно ждет.


                                                                интефейс должен отвечать удобностью и актуальностью информацией

                                                                Актуальность информации — штука очень относительная в любой распределенной системе.


                                                                1. mdErrDX5341
                                                                  21.11.2017 23:31
                                                                  -1

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


                                                                  1. lair
                                                                    21.11.2017 23:34

                                                                    Это не отменяет того, что эта самая "актуальность как возможность" — штука относительная. Особенно относительной она становится, когда ты приносишь бизнесу табличку: задежка доставки информации 5с — x k$, задежка доставки информации 1с — 20x k$. Часто говорят "а мы и минуту подождем".


                                                                    1. mdErrDX5341
                                                                      21.11.2017 23:38
                                                                      -1

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


                                                                      1. lair
                                                                        21.11.2017 23:43

                                                                        пусть ждут, от сюда и технологии такие как аякс и веб сокет

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


                                                                        1. mdErrDX5341
                                                                          21.11.2017 23:52
                                                                          -1

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


                                                                          1. lair
                                                                            21.11.2017 23:55

                                                                            а не об этом я писал?

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


                                                                            я так вспоминаю вы мне даже в личку начали писать,

                                                                            В хранящейся у меня истории диалогов я никогда не писал вам в личку.


                                                                            1. mdErrDX5341
                                                                              22.11.2017 00:05
                                                                              -1

                                                                              Сергей Роговцев lair 10 апреля в 01:56

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


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

                                                                              так как бизнес требует...


                                                                              1. lair
                                                                                22.11.2017 00:10

                                                                                Сергей Роговцев lair 10 апреля в 01:56

                                                                                Очень любопытно. У меня этого сообщения нет, есть только ваше от 10 апреля в 02:23. Впрочем, я специально сказал "в хранящейся у меня истории", я не претендую на идеальную память.


                                                                                так как бизнес требует

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


                                                                                1. mdErrDX5341
                                                                                  22.11.2017 00:18
                                                                                  -1

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


                                                                                1. mdErrDX5341
                                                                                  22.11.2017 00:37
                                                                                  -1

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


                                                                                  1. lair
                                                                                    22.11.2017 00:39

                                                                                    как в таком положено у вам нет аддекватных ответов

                                                                                    Я однажды уже писал вам, и еще раз повторю: вы практически не задаете осмысленных вопросов.


                                                                                    1. mdErrDX5341
                                                                                      22.11.2017 00:46
                                                                                      -1

                                                                                      скорее вы не читаете комментариев и по этому просто цитируете фразы, вместо того что бы прочитать и понять, а после этого вы не осознаете сами комментрии…
                                                                                      вы даже не могли понять когда Вас просили остановится, скорее всего Вы были увлечены своим величием)))


                                                                                    1. mdErrDX5341
                                                                                      22.11.2017 00:58
                                                                                      -1

                                                                                      Давай девочка еще минус)))


                                                                                    1. mdErrDX5341
                                                                                      22.11.2017 01:21
                                                                                      -1

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


                                                                                      1. lair
                                                                                        22.11.2017 01:31

                                                                                        Самое интерестное что Вы повторили мои многие слова или выводы, из комметариев которым сами поставили минус

                                                                                        Вам кажется.


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

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


                                                                                        1. mdErrDX5341
                                                                                          22.11.2017 01:44
                                                                                          -1

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

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


                                                                                          чтоооооо? вы хоть сами понимаете что пишете, я не задавал вопросов, а спрашивал о правильности своих утверждениях)))
                                                                                          Вы вчитаете или печаете на автомате, считая себя...


                                                                                          1. lair
                                                                                            22.11.2017 01:49

                                                                                            я не задавал вопросов, а спрашивал

                                                                                            Уже прекрасно.


                                                                                            о правильности своих утверждениях

                                                                                            Ну вот вам и рассказали, что они некорректны.


                                                                                            1. mdErrDX5341
                                                                                              22.11.2017 01:57
                                                                                              -1

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


                                                                                              1. lair
                                                                                                22.11.2017 02:05

                                                                                                а утверждал что уровень представления на мой взгляд нужно отделять от уровня вью в моделе mvc,

                                                                                                Это единственное, что вы утверждали?


                                                                                                (да, нет такой вещи как «уровень вью»)


                                                                                                мои многие примеры с элементами интерфейса.

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


                                                                                                1. mdErrDX5341
                                                                                                  22.11.2017 02:40

                                                                                                  отвечу....


                                                                                                  Я столько видел over-engineered code, хотя в большинстве случаев просто нужно было взять данные из БД, удобно и быстро показать их пользователю. Все.

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


                                                                                                  как мне кажется нужно просто в скрипт php вернуть ответ из базы и после этого его в цикле вывести.


                                                                                                  1. lair
                                                                                                    22.11.2017 11:41

                                                                                                    отвечу....

                                                                                                    Вы не тому человеку отвечаете.


                                                                                                1. mdErrDX5341
                                                                                                  22.11.2017 02:45

                                                                                                  Это единственное, что вы утверждали?

                                                                                                  Да Вы проницательны)))


                                                                                                  Никто не спорит, что надо отделять термины одной системы (слои) от терминов другой системы (компоненты), ну так они и разделены в оригинале.

                                                                                                  Но только не в MVC)))


                                                                                                  1. lair
                                                                                                    22.11.2017 11:43

                                                                                                    Но только не в MVC

                                                                                                    … и в MVC тоже. Пока вы находитесь внутри MVC, у вас вообще есть только одна терминологическая система, ее собственная (плюс тактические паттерны, которые с ней не пересекаются), и в этой системе нет термина presentation. Когда вы смотрите на MVC снаружи, оценивая его положение в приложении, у вас, наоборот, есть (должна быть) только другая терминологическая система, стратегическая, в которой есть presentation, но не имеет смысла говорить о view.


                                                                                                    Bounded contexts, как обычно.


    1. polly5315 Автор
      20.11.2017 22:38

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


      protected override void OnException(ExceptionContext filterContext)
      {
          // Логирование ошибки
          filterContext.ExceptionHandled = true;
          filterContext.Result = RedirectToAction("OperationFailed");
      }


      1. mdErrDX5341
        20.11.2017 22:47

        я далек от C# и ASP.NET MVC, вы имеете в виду view или уровень presentation?


        1. lair
          20.11.2017 22:58

          View — это и есть уровень presentation.


          1. mdErrDX5341
            20.11.2017 23:04

            В данном случае я пытась отделить view в mvc от presentation слоя, так как перевод неоднозначен


            1. mdErrDX5341
              21.11.2017 09:25

              вот опять мне не понятен минус.
              view как и presentation переводится в данном случае как представление, от сюда и может возникнуть путаница о чем идет речь…
              и почему минус хз, хз, хз....


      1. mdErrDX5341
        20.11.2017 22:55

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


      1. lair
        20.11.2017 22:58

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

        Это слишком много логики в представлении. Ее всю нужно тестировать.


        1. polly5315 Автор
          20.11.2017 23:54

          Если бы она была в контроллере или где-либо еще, ее все равно пришлось бы тестировать.


          1. lair
            21.11.2017 00:07

            Но контроллер тестировать проще, чем представление.


            1. polly5315 Автор
              21.11.2017 00:14

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


              1. lair
                21.11.2017 00:20

                Не факт.

                Факт. Контроллер всегда легче тестировать, чем представление, просто в силу контракта.


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

                Нет в Model2 никакого оповещения модели о действии пользователя.


                возможно, предварительная валидация входных данных.

                И что?


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

                Ээээ… нет? Что такое "логика отображения", на конкретном примере?


                1. polly5315 Автор
                  21.11.2017 00:31

                  Нет в Model2 никакого оповещения модели о действии пользователя.

                  Вы ведь манипулируете моделью прежде, чем отобразить представление?


                  Что такое "логика отображения"

                  Мы с вами это уже обсуждали в другой ветке. Это сбор представлением всех недостающих данных и их подготовка к вставлению в шаблон.


                  1. lair
                    21.11.2017 00:34

                    Вы ведь манипулируете моделью прежде, чем отобразить представление?

                    Нет. Если пользователь производит действие, то оно выражено в input model, на основании которой производится действие на домене, результат которого мапится во view model. Это в asp.net MVC, как частном случае Model2.


                    Мы с вами это уже обсуждали в другой ветке. Это сбор представлением всех недостающих данных и их подготовка к вставлению в шаблон.

                    А как так вышло, что у вас одни и те же данные для одного и того же представления могут приходить из разных контроллеров? Можно, опять-таки, на конкретном примере?


                    1. polly5315 Автор
                      21.11.2017 01:17

                      Самый простой пример — сообщение об ошибке или любое другое сервисное представление, которое показывается через return View("%ViewName%");. Некоторые из них тоже нуждаются в каких-то данных.
                      А так же частичные представления, которые вызываются из остальных, и показываются на многих страницах.


                      1. lair
                        21.11.2017 01:29

                        Самый простой пример — сообщение об ошибке

                        Для сообщения об ошибке данными является сама ошибка (либо Exception, либо выделенный Error Model поверх Exception), нет там никакой дополнительной логики ее сбора.


                        любое другое сервисное представление, которое показывается через return View("%ViewName%");. Некоторые из них тоже нуждаются в каких-то данных.

                        … например? В моей практике они либо берут данные из данных мастер-пейджа (а за этот трюк я набрал овердофига плюсов на SO), либо их можно завернуть в presentation service и делать так (в экшне):


                            return _standardViews.Alpha();

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


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

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


                        (в некий момент сложность всего этого цирка зашкаливает, и приходилось переходить на Html Helpers, которые хоть тестировать немножко проще, чем представления)


                        В asp.net Core, кстати, если я ничего не путаю, эту дырку заткнули view components, у которого разделение компонентов такое же, как у обычной триады.


                      1. lair
                        21.11.2017 01:37

                        … в той же документации на asp.net Core, кстати, явно написано (несмотря на наличие dependency injection во view):


                        You should try to maintain separation of concerns between your controllers and views. Most of the data your views display should be passed in from the controller.


                        1. HackerDelphi
                          22.11.2017 08:47

                          Согласен — очень правильно.
                          Читал много, но подытожу ответы здесь, если Вы не против:


                          1. Данные готовит контроллер, но через "толстую" модель или пару доменная модель -> модель вью, а затем передает их в модель.
                          2. Партиалки и/или вью компоненты (а также — таг хелперы) используются либо для отображения какой-либо части вью модели (отдельное комплексное свойство модели) либо же для отображения обобщённых моделй (базовый класс или интерфейс). В целом, подход такой, чтобы партиады (как их не называй) получали "конкретную" модель для отображения, а не были просто кусочком большого представления.
                          3. При необходимости можно из контроллеров отдавать данные для клиентского рендеринга, либо, иногда, куски HTML, которые вставляются в финальный код.


                          1. lair
                            22.11.2017 11:49

                            Для начала, важно отметить, что это все может быть верно только в контексте asp.net MVC, который базируется на Model2. Про другие "MVC" и MVC-фреймворки я говорить не буду.


                            Данные готовит контроллер, но через "толстую" модель или пару доменная модель -> модель вью, а затем передает их в модель.

                            Это уже избыточное обобщение. С уверенностью можно сказать, что контроллер передает в представление готовые к представлению (простите) данные. Подготовил ли он их сам, или он только скоординировал репозиторий с маппером — вопрос сильно вторичный.


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

                            Вот как раз для view components это неверно. Можно вызвать view component "сегодняшняя погода", и он сам получит для себя данные; именно благодаря тому, что у него собственнная триада, это не нарушает паттерна в целом.


                            При необходимости можно из контроллеров отдавать данные для клиентского рендеринга

                            … это уже не совсем Model2.


                            либо, иногда, куски HTML

                            А это неверно, потому что контроллер должен отдавать некий result, который уже рендерится конвеером. Если мы хотим отдать HTML — значит это view result с данными внутри (или без данных, если он от данных не зависит).


  1. lair
    21.11.2017 01:45

    У этого шаблона [ADR] есть преимущества перед MVC:

    Вообще, то ли я криво читаю, то ли все описанное прекрасно можно было сделать на старом asp.net WebAPI + пакет для razor views. D Core, который объединил MVC и WebAPI вообще проблем быть не должно — там уже есть view responses и formatted responses из MVC-контроллеров.


  1. Westernstorm
    21.11.2017 14:18

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

    Тонкий контроллер убыстряет разработку? вряд ли
    Увеличивает скорость приложения? нет

    Я столько видел over-engineered code, хотя в большинстве случаев просто нужно было взять данные из БД, удобно и быстро показать их пользователю. Все.


    1. DrPass
      22.11.2017 01:23

      У меня возникло такое же впечатление. Многие архитекторы следуют паттернам ради самих паттернов, хотя это на самом деле не самоцель. Есть один, причем не слишком четкий, критерий качества кода — код должен быть читабельным, понятным и легко сопровождаемым. А паттерны — это лишь инструменты достижения этого критерия. И если следование всем канонам паттерна усложняет код, то этого делать не надо. Более того, надо себя вовремя одергивать, когда в голову приходит любимая мантра архитектора: «Если нагрузка/функционал/что-то ещё будет расти, то вот тут надо сразу заложить масштабирование, балансировку, что-то ещё, чтобы потом не переделывать». Во-первых, надо чётко понимать, когда ожидается наступление этого самого «если», и произойдет ли оно вообще, а во-вторых, все равно зачастую окажется проще потом переделать, чем сейчас навернуть.