Javascript модульность, серверный MVC и бизнес-реальность


32

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

Я хотел бы указать, что ответы должны включать эти технологии:

  • C #
  • MVC 3 с бритвой
  • Javascript с JQuery

Все, что выходит за рамки этого (например, Backbone.js , Entity Framework и т. Д.), Приветствуется в качестве предложений, если они помогают ответить на вопрос:

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

В идеале основное внимание должно быть уделено решению, развертываемому в бизнес / корпоративной среде. На этом примечании приведенный выше список технологий не будет изменен, поэтому, пожалуйста, не предлагайте решения с «вы должны использовать xxx вместо yyy, который вы используете сейчас».

Задний план

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

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

1. Структура проекта

Учитывая, что я работаю с ASP.NET MVC (в Visual Studio 2010 ), я хотел бы получить решение для структуры каталогов, которое предлагает некоторую поддержку основного макета этого типа приложения. Полагаю, что- то вроде Brunch , но с более подробным описанием того, что будет содержать каждая папка и как она работает с другими областями приложения.

2. Доступ к данным

Я хотел бы как можно больше модульного доступа к данным, используя структуру типа API. Можно предположить , множество объектов POCO ( User, UserGroup, Customer, OrderHeader, OrderDetailsи т.д.), но также будут несколько сложных отчетами , которые требуют интенсивной обработки данных SQL и осторожный рендеринг UI. EF + LINQ фантастичны для первых, но не так уж и для последних. Я не могу найти то, что кажется подходящим для обоих сценариев, не будучи слишком сложным или слишком простым.

3. Организация клиентского кода и рендеринг пользовательского интерфейса

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

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

$('#doSomethingDangerous').click(function () {
    // maybe confirm something first
    if (confirm('Are you sure you want to do this?')) {   

        // show a spinner?  something global would be preferred so I don't have to repeat this on every page 
        $('#loading').show();  

        // maybe the page should notify the user of what's going on in addition to the dialog?
        $('#results').show().html('<h2>Please wait, this may take a while...</h2>');  

        $.ajax({
            url: 'blah/DoDangerousThing',
            success: function (data) {                     
                // The results will be loaded to the DOM obviously, is there a better way to pull this type of specific code out of the data access calls?
                $('#results').empty();
                $('#results').append('<b>' + data.length + '</b> users were affected by this dangerous activity');
                $('#results').append('<ul>');

                // I've recently started to use jQuery templates for this sort of logic, is that the way to go?
                $(data).each(function (i, user) {
                    $('#results').append('<li>' + user.Username + '</li>');
                });                    
                $('#results').append('</ul>');

                // Need to hide the spinner, again would prefer to have this done elsewhere
                $('#loading').hide();
            }
        });
    }
});

Основные вопросы

  • Клиент MVC против сервера MVC? Мой проект уже является структурой MVC на стороне сервера, так что все еще существует потребность в клиентском MVC, как обеспечивает Backbone.js?
  • Должны ли файлы Javascript создаваться для каждого объекта (например, OrderHeader.js), а затем уменьшаться / объединяться во время сборки? Или просто должен быть Order.jsлогик для чего-то еще OrderHeader, OrderDetails, Reports?
  • Как следует обрабатывать сложные запросы? Прямо сейчас моя ведущая теория /Reports/Orders-By-Date/или что-то в этом роде, и я использую пользовательский запрос SQL, который отображает пользовательский набор данных (или ViewModel) в Razor View. Но как насчет подкачки, сортировки и т. Д.? Это лучше сделать на стороне клиента или сервера? (предположим, больший набор данных - от 2 до 3 секунд SQL-запроса)
  • Я прочитал проект Microsoft Silk . Это хороший путь? Как это сравнить с Backbone.js или другими?
  • Я очень привык к многоуровневой архитектуре, эти концепции несколько выбрасывают это в окно? Кажется, что MVC похож на кучу мини N-ярусных секций внутри того, что раньше было интерфейсом или верхним уровнем.

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


2
Вы вложили много усилий в этот вопрос, но он просто не кажется мне вопросом Stackoverflow. Возможно, программисты stackexchange подойдут лучше.
Заостренный

3
Я не согласен с тем, что это интересная тема, но предполагается, что Stackoverflow посвящен объективным вопросам. Нечто похожее на этот вопрос, в основном, является постером для вопросов, которые «скорее всего потребуют мнения, дебатов, споров, опросов или расширенного обсуждения».
Заостренный

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

1
Я согласен с @Pointy, что это принадлежит стеку программистов. Ваш вопрос очень интересный, и я буду следовать ему, потому что я всегда ищу совет. Но это не объективный вопрос, и он только закончится преференциальными дебатами. Как всегда, делайте то, что лучше всего подходит для вашей ситуации ... никто из нас ничего не знает о структуре вашей сети, количестве клиентов, статистике трафика или процессе сборки ... так что вопрос СЛИШКОМ слишком расплывчатый ... все, что я знаю, это избегать шелка ;)
one.beat.consumer

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

Ответы:


10

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

1. Структура проекта. Я согласен с Eduardo в том, что структура папок в приложении MVC оставляет желать лучшего. У вас есть стандартные папки Controllers, Models и Views. Но затем папка «Виды» разбивается на разные папки для каждого контроллера и общую папку. И каждое Views / ControllerName или Views / Shared можно разбить на EditorTemplates и DisplayTemplates. Но это позволяет вам решить, как организовать вашу папку Models (вы можете обойтись с или без подпапок и дополнительных объявлений пространства имен).

Не дай Бог, вы используете Области, которые дублируют структуру папок Controllers, Models и Views для каждой области.

/Areas
    /Area1Name
        /Controllers
            FirstController.cs
            SecondController.cs
            ThirdController.cs
        /Models
            (can organize all in here or in separate folders / namespaces)
        /Views
            /First
                /DisplayTemplates
                    WidgetAbc.cshtml <-- to be used by views in Views/First
                /EditorTemplates
                    WidgetAbc.cshtml <-- to be used by views in Views/First
                PartialViewAbc.cshtml <-- to be used by FirstController
            /Second
                PartialViewDef.cshtml <-- to be used by SecondController
            /Third
                PartialViewMno.cshtml <-- to be used by ThirdController
            /Shared
                /DisplayTemplates
                    WidgetXyz.cshtml <-- to be used by any view in Area1
                /EditorTemplates
                    WidgetXyz.cshtml <-- to be used by any view in Area1
                PartialViewXyz.cshtml <-- to be used anywhere in Area1
            _ViewStart.cshtml <-- area needs its own _ViewStart.cshtml
            Web.config <-- put custom HTML Helper namespaces in here
        Area1NameRegistration.cs <-- define routes for area1 here
    /Area2Name
        /Controllers
        /Models
        /Views
        Area2NameRegistration.cs <-- define routes for area2 here

/Controllers
    AccountController.cs
    HomeController.cs
/Models
/Views
    /Account
        /DisplayTemplates
            WidgetGhi.cshtml <-- to be used views in Views/Account
        /EditorTemplates
            WidgetGhi.cshtml <-- to be used views in Views/Account
        PartialViewGhi.cshtml <-- to be used by AccountController
    /Home
        (same pattern as Account, views & templates are controller-specific)
    /Shared
        /DisplayTemplates 
            EmailAddress.cshtml <-- to be used by any view in any area
            Time.cshtml <-- to be used by any view in any area
            Url.cshtml <-- to be used by any view in any area
        /EditorTemplates
            EmailAddress.cshtml <-- to be used by any view in any area
            Time.cshtml <-- to be used by any view in any area
            Url.cshtml <-- to be used by any view in any area
        _Layout.cshtml <-- master layout page with sections
        Error.cshtml <-- custom page to show if unhandled exception occurs
    _ViewStart.cshtml <-- won't be used automatically in an area
    Web.config <-- put custom HTML Helper namespaces in here

Это означает, что если вы работаете с чем-то вроде WidgetController, вы должны искать в других папках, чтобы найти связанные WidgetViewModels, WidgetViews, WidgetEditorTemplates, WidgetDisplayTemplates и т. Д. Как бы громоздко это ни было, я придерживаюсь и не отклоняюсь от эти соглашения MVC. Что касается размещения модели, контроллера и представления в одной папке, но с разными пространствами имен, я избегаю этого, потому что я использую ReSharper. Он будет волнообразно подчеркивать пространство имен, которое не соответствует папке, в которой находится класс. Я знаю, что мог бы отключить эту функцию R #, но это помогает в других частях проекта.

Для файлов, не относящихся к классу, MVC предоставляет вам содержимое и сценарии из коробки. Мы пытаемся сохранить все наши статические / не скомпилированные файлы в этих местах, опять же, чтобы следовать соглашению. Каждый раз, когда мы включаем библиотеку js, которая использует темы (изображения и / или css), все файлы тем попадают куда-то в / content. Для сценария мы просто помещаем их все непосредственно в / scripts. Первоначально это было для получения IntelliSense JS от VS, но теперь, когда мы получаем IntelliSense JS от R # независимо от размещения в / scripts, я полагаю, мы могли бы отклониться от этого и разделить сценарии по папкам для лучшей организации. Вы используете ReSharper? Это чистое золото ИМО.

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

// no more magic strings in route definitions
context.MapRoutes(null,
    new[] { string.Empty, "features", "features/{version}" },
    new
    {
        area = MVC.PreviewArea.Name,
        controller = MVC.PreviewArea.Features.Name,
        action = MVC.PreviewArea.Features.ActionNames.ForPreview,
        version = "december-2011-preview-1",
    },
    new { httpMethod = new HttpMethodConstraint("GET") }
);

@* T4MVC renders .min.js script versions when project is targeted for release *@
<link href="@Url.Content(Links.content.Site_css)?r=201112B" rel="stylesheet" />
<script src="@Url.Content(Links.scripts.jquery_1_7_1_js)" type="text/javascript">
</script>

@* render a route URL as if you were calling an action method directly *@
<a href="@Url.Action(MVC.MyAreaName.MyControllerName.MyActionName
    (Model.SomeId))">@Html.DisplayFor(m => m.SomeText)</a>

// call action redirects as if you were executing an action method
return RedirectToAction(MVC.Area.MyController.DoSomething(obj1.Prop, null));

2. Доступ к данным: у меня нет опыта работы с PetaPoco, но я уверен, что стоит проверить. Рассматривали ли вы для своих сложных отчетов службы отчетов SQL Server? Или вы работаете на другой БД? Извините, мне не ясно, о чем именно вы спрашиваете. Мы используем EF + LINQ, но мы также вкладываем определенные знания о том, как генерировать отчеты в классах домена. Таким образом, мы имеем хранилище вызовов службы домена вызова контроллера вместо прямого хранилища вызовов контроллера. Для специальных отчетов мы используем SQL Reporting Services, что опять-таки не идеально, но наши пользователи хотели бы иметь возможность легко переносить данные в Excel, а SSRS облегчает нам задачу.

3. Организация кода на стороне клиента и рендеринг пользовательского интерфейса. Здесь я думаю, что смогу предложить некоторую помощь. Возьмите страницу из книги MVC ненавязчивой проверки и ненавязчивой AJAX. Учти это:

<img id="loading_spinner" src="/path/to/img" style="display:none;" />
<h2 id="loading_results" style="display:none;">
    Please wait, this may take a while...
</h2>
<div id="results">
</div>
<input id="doSomethingDangerous" class="u-std-ajax" 
    type="button" value="I'm feeling lucky" 
    data-myapp-confirm="Are you sure you want to do this?"
    data-myapp-show="loading_spinner,loading_results" 
    data-myapp-href="blah/DoDangerousThing" />

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

$('.u-std-ajax').click(function () {
    // maybe confirm something first
    var clicked = this;
    var confirmMessage = $(clicked).data('myapp-confirm');
    if (confirmMessage && !confirm(confirmMessage )) { return; } 

    // show a spinner?  something global would be preferred so 
    // I dont have to repeat this on every page 
    // maybe the page should notify the user of what's going on 
    // in addition to the dialog?
    var show = $(clicked).data('myapp-show');
    if (show) {
        var i, showIds = show.split(',');
        for (i = 0; i < showIds.length; i++) {
            $('#' + showIds[i]).show();
        }
    }

    var url = $(clicked).data('myapp-href');
    if (url) {
        $.ajax({
            url: url,
            complete: function () {                     
                // Need to hide the spinner, again would prefer to 
                // have this done elsewhere
                if (show) {
                    for (i = 0; i < showIds.length; i++) {
                        $('#' + showIds[i]).hide();
                    }
                }
            }
        });
    }
});

Приведенный выше код будет заботиться о подтверждении, показывая счетчик, показывая сообщение ожидания и скрывая сообщение счетчика / ожидания после завершения вызова ajax. Вы настраиваете поведение, используя атрибуты data- *, такие как ненавязчивые библиотеки.

Основные вопросы

- Клиент MVC против сервера MVC? Я не пытался описать действия, которые вы предприняли в функции успеха, потому что похоже, что ваш контроллер возвращает JSON. Если ваши контроллеры возвращают JSON, вы можете посмотреть на KnockoutJS. Knockout JS версия 2.0 была выпущена сегодня . Он может подключаться прямо к вашему JSON, так что наблюдаемый щелчок может автоматически связывать данные с вашими шаблонами JavaScript. С другой стороны, если вы не возражаете против того, чтобы ваши методы действия ajax возвращали HTML вместо JSON, они могут вернуть уже созданный UL с его дочерними элементами LI, и вы можете добавить это к элементу, используя data-myapp-response = "полученные результаты". Ваша функция успеха будет выглядеть так:

success: function(html) {
    var responseId = $(clicked).data('myapp-response');
    if (responseId) {
        $('#' + responseId).empty().html(html);
    }
}

Подводя итог моему лучшему ответу на это, если вы должны вернуть JSON из ваших методов действий, вы пропускаете View на стороне сервера, так что это действительно не MVC сервера - это просто MC. Если вы возвращаете PartialViewResult с html вызовам ajax, это сервер MVC. Поэтому, если ваше приложение должно возвращать данные JSON для вызовов ajax, используйте клиентский MVVM, такой как KnockoutJS.

В любом случае, мне не нравится тот JS, который вы опубликовали, потому что он смешивает ваш макет (HTML-теги) с поведением (асинхронная загрузка данных). Выбор сервера MVC с частичными представлениями html или клиента MVVM с чистыми данными модели представления JSON решит эту проблему для вас, но ручное построение DOM / HTML в javascript нарушает разделение проблем.

- Создание файла Javascript. Очевидно, функции минимизации появятся в .NET 4.5 . Если вы идете по ненавязчивому пути, ничто не помешает вам загрузить все ваши файлы JS в 1 скриптовом файле. Я буду осторожен с созданием разных файлов JS для каждого типа сущности, в результате вы получите взрыв файла JS. Помните, что после загрузки файла скрипта браузер должен его кешировать для будущих запросов.

- Сложные запросы, которые я не считаю такими сложными, как разбиение на страницы, сортировка и т. Д. Я предпочитаю обрабатывать это с помощью URL-адреса и серверной логики, чтобы сделать запросы к базе данных настолько ограниченными, насколько это необходимо. Однако мы развернуты в Azure, поэтому для нас важна оптимизация запросов. Например: /widgets/show-{pageSize}-per-page/page-{pageNumber}/sort-by-{sortColumn}-{sortDirection}/{keyword}. EF и LINQ to Entities могут обрабатывать разбиение на страницы и сортировку с помощью таких методов, как .Take (), .Skip (), .OrderBy () и .OrderByDescending (), так что вы получите то, что вам нужно во время поездки по БД. Я еще не нашел необходимость в клиентской жизни, поэтому, честно говоря, я мало что о них знаю. Посмотрите другие ответы для получения дополнительных советов по этому вопросу.

- Проект шелка Никогда не слышал об этом, придется проверить это. Я большой поклонник Стива Сандерсона, его книг, его BeginCollectionItem HtmlHelper и его блога. Тем не менее, у меня нет никакого опыта работы с KnockoutJS в производстве . Я проверил его учебники, но я стараюсь не совершать что-либо, пока не выйдет хотя бы версия 2.0. Как я уже говорил, KnockoutJS 2.0 был только что выпущен.

- N-уровень Если под уровнем вы подразумеваете другую физическую машину, то нет, я не думаю, что что-либо выходит за рамки. Обычно 3-х уровневый означает, что у вас есть 3 машины. Таким образом, у вас может быть толстый клиент в качестве уровня представления, который работает на компьютере пользователя. Толстый клиент может получить доступ к уровню обслуживания, который выполняется на сервере приложений и возвращает толстый клиент XML или что-то еще. А сервисный уровень может получать свои данные с SQL-сервера на 3-м компьютере.

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

Обновление после комментария pres / bus / data

Итак, вы используете слой и слой взаимозаменяемо. Я обычно использую термин «слой» для логических / проектных / сборочных подразделений и уровень для физического разделения сети. Извините за путаницу.

В лагере MVC вы найдете довольно много людей, которые скажут, что вы не должны использовать «Модели» в MVC для вашей модели данных сущности, а также не должны использовать свои Контроллеры для бизнес-логики. В идеале ваши модели должны быть ViewModels для конкретного вида. Используя что-то вроде Automapper, вы берете свои сущности из модели вашего домена и помещаете их в ViewModels, специально разработанные для использования представлением.

Любые бизнес-правила также должны быть частью вашего домена, и вы можете реализовать их, используя доменные службы / шаблон фабрики / все, что подходит на вашем доменном уровне, а не на уровне представления MVC. Контроллеры должны быть глупыми, хотя и не такими глупыми, как модели, и должны нести ответственность перед доменом за все, что требует бизнес-знаний. Контроллеры управляют потоком HTTP-запросов и ответов, но все, что имеет реальную ценность для бизнеса, должно быть выше уровня оплаты контроллера.

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


Я полностью согласен с этим ответом! В частности: • Resharper - гений MVC ... от проверки ошибок до навигации IDE, его полезность поражает меня! • MVC на стороне сервера - почти всегда лучший подход • MVC - это не 3 отдельных уровня, это один уровень представления - я никогда не думал об этом, но это абсолютно правильно.
Скотт Риппи

Очень хороший ответ, определенно то, что я искал ценой моих 300 повторений. Напитки на меня, если вы находитесь в районе Торонто :)

Кстати, я всегда рассматривал N-уровень как Pres / Bus / Data независимо от того, где они физически сидели. Вот почему я сказал, что MVC почти удаляет эту архитектуру, потому что она в основном объединяет 3, что, как вы сказали, несколько согласуется с этим, но также дает другую точку зрения на это.

Я хотел бы предостеречь против ViewModel, модель для просмотра, подход. Недавно я столкнулся с ситуацией, когда позже захотелось, чтобы у меня не было этой абстракции от DTO до ViewModel. См .: stackoverflow.com/q/7181980/109456

Как правило, мне не нравится видеть jQuery, и вместо этого я пишу объекты с интерфейсами, которые любой серверный разработчик сможет понять довольно быстро с помощью JQ или DOM API, занимающегося бизнесом внутри. Мне также очень нравится концепция Django URLConfig, и я считаю ее полезной для настройки объектов для реализации на страницах. Понятия не имею что такое МВ? библиотеки должны делать для меня, хотя. Они не идеально подходят для этой проблемы, IMO и делегирование событий DOM + - это все, что мне нужно для обработки страниц без чрезмерной привязки к конкретной структуре.
Эрик Реппен

6

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

Мои советы:

1. Структура проекта
Я обнаружил, что структура MVC по умолчанию мне не подходит. Я обычно работаю в контроллере, представлениях и модели одного и того же объекта (думаю, продукт, заказ, клиент) одновременно. Итак, мне нравится, когда файлы находятся в одной папке, но с разными пространствами имен.

2. Данные
Если вы используете Linq-to-SQL или EF, вы пожалеете позже.
Я использую PetaPoco, который позволяет мне запускать извлечение и обновление записей SQL без проблем с отображением, но без изучения нового способа работы и без ночных кошмаров по производительности.

У меня есть генератор кода для создания исходного класса POCO с атрибутами PetaPoco, а затем изменить класс при добавлении или удалении какого-либо поля.

PetaPoco работает с динамическими и стандартными классами, поэтому у вас нет никаких компромиссов (Massive - все динамические, а Dapper - все стандартные классы)

Я также генерирую основной SQL, используя встроенный SqlBuilder, который содержит все стандартные объединения для сущности, но не содержит WHERE, поэтому я повторно использую тот же SQL для извлечения одной сущности или списка.

3. Jquery. Вы можете стандартизировать некоторые части пользовательского интерфейса, используя общий вызов jQuery (вставляя некоторые данные в элемент HTML).

Например, у меня есть это для удаления.

var deleteLinkObj;
// delete Link
$('.jbtn-borrar').click(function () {
    deleteLinkObj = $(this);  //for future use
    $('#delete-dialog').dialog('open');
    return false; // prevents the default behaviour
});
$('#delete-dialog').dialog({
    autoOpen: false, width: 400, resizable: false, modal: true, //Dialog options
    buttons: {
        "Borrar": function () {
            $.post(deleteLinkObj[0].href, function (data) {  //Post to action
                if (data == 'OK') {
                    deleteLinkObj.closest("tr").hide('fast'); //Hide Row
                }
                else {
                    alert(data);
                }
            });
            $(this).dialog("close");
        },
        "Cancelar": function () {
            $(this).dialog("close");
        }
    }
});

Мне просто нужно добавить класс jbtn-borrarв гиперссылку, и он показывает диалоговое окно, удалить запись и скрытьtr

Но не думай об этом. Ваше приложение будет сиять с небольшими штрихами в каждом представлении.

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

Как следует обрабатывать сложные запросы (давайте назовем это Report).
Я использую класс с параметрами Report в качестве свойств (удобно для использования MVC-автоматического сопоставления) и Generateметод, который выполняет запрос и заполняет список пользовательских классов (если вы этого не делаете. класс не подходит для ViewModel)
Вы можете использовать этот класс в качестве модели представления и заполнить таблицу сгенерированным списком.

Проект Microsoft Silk
Overarchitected. Беги как можно быстрее в противоположном направлении.


Забавно, когда я читал Project Silk, я продолжал испытывать это ноющее чувство и не мог его определить. Возможно, это было

3

1. Структура проекта

У меня есть 2 файла проекта в моем решении

1) Сервис / бизнес-уровень Я помещаю всю свою бизнес-логику, код доступа к БД и POCO в этот отдельный проект. Нет необходимости в уровне доступа к данным, если вы используете ORM, так как ORM уже абстрагирует уровень DB.

2) Слой пользовательского интерфейса содержит все мои виды, контроллеры, модели, скрипты, CSS

Я стараюсь, чтобы мои контроллеры, виды, скрипты и CSS использовали одинаковую структуру папок. Также структурируйте мои файлы так, чтобы они максимально соответствовали пути URL. Чтобы избежать необходимости писать пользовательскую маршрутизацию.

Максимально используйте DisplayTemplates, EditorTemplates, Partial views и Shared folder.

Затем я структурирую все свои сценарии так, чтобы они совпадали с областями, контроллерами моих файлов c #, поэтому у меня был бы файл common.js в корне, файл js на страницу и файл common.js для каждой области.

CSS-файлы У меня обычно 2 + n (где n - количество областей). 1-й файл CSS - это CSS только для целевой страницы, чтобы помочь быстрее загружать страницу (вероятно, это не так важно для бизнеса / корпоративной среды). 2-й файл CSS является common.css, который имеет все стили для всех остальных страниц. Затем еще один файл common.css для каждой области, например файл AdminArea.css, в котором есть CSS для каждой страницы администратора.

2. Доступ к данным

Если я использую Entity Framework, я использую CodeFirst, так как он очень хорошо работает с POCOS, и у вас нет модели для обслуживания. nHibernate намного мощнее, но имеет более крутое обучение. Для подкачки результатов в БД у меня есть многократно используемый класс C # и внутренний вид, который я использую для всех своих представлений.

Для сложных запросов и генерации отчетов я использую хранимые процедуры. Их намного проще писать и поддерживать, и они предоставляют больше возможностей LINQ. Они также могут быть использованы другими службами, такими как SSRS. Я использую automapper, чтобы преобразовать набор данных, возвращаемый обратно, в те же самые POCO, которые использует вся структура POCO.

3. Организация клиентского кода и рендеринг пользовательского интерфейса

У ответа Эдуардо Молтени есть хороший пример кода. Кроме того, я бы определенно рекомендовал использовать knockoutjs, так как он имеет хорошие шаблоны и привязки. Если вы используете JSON для всех ваших вызовов AJAX, которые я часто использую, то автоматическое сопоставление UI с объектами JS значительно экономит время.

Основные вопросы

Сложные запросы должны жить в хранимой процедуре. (см. комментарий emeraldcode.com)

Вы по-прежнему сохраняете свою N-уровневую архитектуру, используя этот MVC.


1

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

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

В сценарии Ochard все, что вы не можете решить с помощью его механизмов конфигурации, вы бы потом обрабатывали либо добавлением бесплатных онлайн-модулей, либо написанием своего собственного модуля (который, конечно, является C #, razor и так далее). Код организации - это сила Orchard.

Что касается доступа к данным, у полнофункционального ORM достаточно плюсов и минусов, и я также считаю, что микро-ORM - лучший выбор. Попробуйте Massive или Dapper . Оба были показаны на Hanselminutes . Я суммирую эти два, сказав это: абстракции от SQL почти всегда ломаются, когда проект масштабируется. В конце концов, лучшее решение для доступа к БД - это абстракция, называемая SQL (немного сарказма, но это правда). Пусть микро ОРМ работает с этим, и у вас есть золото.

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


0

Не уверен, как я пропустил этот вопрос, но я добавлю два своих цента два года спустя.

Клиент MVC против сервера MVC? Мой проект уже является структурой MVC на стороне сервера, так что все еще существует потребность в клиентском MVC, как обеспечивает Backbone.js?

MVC и MV? даже до того, как его подтолкнули к клиентской части, он фактически превратился в маркетинговый термин, который действительно только обещает, что каким-то образом данные будут отделены от других вещей, что в целом является отличной идеей, но на самом деле не так уж сложно для DIY. Независимо от того, какой подход вы используете, прямо перед или прямо во время внесения изменений в HTML, которые влияют на возможности презентации или взаимодействия, это абсолютно ужасное место, чтобы выяснить, что бизнес хочет, чтобы вы делали с данными.

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

Должны ли файлы Javascript создаваться для каждого объекта (например, OrderHeader.js), а затем минимизироваться / объединяться во время сборки? Или просто должен быть файл Order.js, в котором есть логика для OrderHeader, OrderDetails, отчетов и т. Д.?

Это действительно зависит от вас, но я постараюсь уйти от одного дела, одного класса. Я никогда не понимал, почему было полезно, например, найти абстрактный файл и интерфейс, а также файлы, реализующие и т. Д. Категоризировать на более широкие вопросы. Ctrl + F не так уж сложно использовать, если он будет немного длинным.

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

И FFS не возиться с управлением зависимостями с помощью JavaScript в Интернете. Require.js на сайтах со средней и низкой сложностью заставляет меня забивать детские тюлени. Вставьте свои сторонние библиотеки в верхний блок. Ваши собственные библиотеки во втором блоке. И затем ваш код реализации (который никогда не должен быть десятым по сравнению с вашим внутренним библиотечным кодом - то есть очень кратким, ясным и простым для понимания) в этом третьем блоке.

Как следует обрабатывать сложные запросы? Прямо сейчас моя ведущая теория - / Reports / Orders-By-Date / или что-то в этом роде, и я использую собственный SQL-запрос, который отображает пользовательский набор данных (или ViewModel) в Razor View. Но как насчет подкачки, сортировки и т. Д.? Это лучше сделать на стороне клиента или сервера? (предположим, больший набор данных - от 2 до 3 секунд SQL-запроса) Я прочитал Microsoft Project Silk. Это хороший путь? Как это сравнить с Backbone.js или другими?

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

Я очень привык к многоуровневой архитектуре, эти концепции несколько выбрасывают это в окно? Кажется, что MVC похож на кучу мини N-ярусных секций внутри того, что раньше было интерфейсом или верхним уровнем.

Это действительно зависит от того, чья фантазия о том, что MV? является. ИМО, микромир имеет тенденцию работать очень хорошо. Класс виджета, который разделяет данные, связь и представление, связанные внутри, прекрасно работает. В сети на стороне клиента критически важным моментом, IMO, является поддержание баланса, состоящего в том, чтобы разделять проблемы, без необходимости разбивать их на крошечные мелочи, повторная сборка которых затрудняет понимание, повторное использование и изменение вещей. Базовый "дух" ООП прекрасно работает здесь. Вы не хотите сложных процессов. Вы хотите явно названные вещи, которые можно перемещать и заставлять делать вещи. Вот несколько советов по этому вопросу:

  • ПОЦЕЛУЙ, что (ООП) интерфейс Я не хочу видеть DOM или jQuery или что-нибудь еще, что неимоверно серверный разработчик не мог понять довольно быстро в моем коде реализации. Все, что этот человек должен знать, - это какой класс шлепать по контейнеру div и какой переключатель перевернуть, чтобы сделать довольно общий набор UI активным на данной странице. Вариации на тему по-прежнему должны быть выполнены путем передачи хорошо документированных / прокомментированных объектов параметров, прежде чем они начнут смотреть на document.get <что-нибудь> или понимать что-либо за пределами основ CSS.

  • Хорошо, так как ты это делаешь? Ну, у нас уже есть модель. Это называется DOM. И у нас есть делегирование событий. Если вы не без разбора отключаете всплывающие сообщения о событиях (не делайте этого - они есть, потому что это полезно), вы можете взять все, даже с тела, если хотите. Затем проверьте целевое свойство переданного объекта события и определите, кто именно «отбеливал». Если вы разумно структурируете HTML-документ , нет причин не использовать его в качестве модели делегирования. Поведение и структура контента естественно связаны между собой. Это нормально для двоих иметь перекрывающиеся идентификаторы.

  • Не платите за привязку данных И под «платой» я, конечно, подразумеваю «наложить библиотеку на вашу кодовую базу, которая настаивает на том, чтобы вы все делали просто так - постоянно, чтобы получить какое-то чудо-преимущество, которое на самом деле нетрудно сделать самостоятельно». Система событий JQ делает это довольно легко.

Пример времени:

function PoliticianData(){ //a constructor

    var
        that = this, //I hate 'that' but example so convention

        flavorsOfLie = {

            lies: "Oh Prism? Psh... no we're all good. There's a guy keeping an eye on that.",

            damnedLies: "50% of the people chose to not give a damn when asked whether it was better to let the terrorists win or not give a damn."

        }
    ;//end instance vars

    this.updateLies = function( lieType, newData ){
        flavorsOfLie[lieType] = newData;
        $(that).trigger({type:'update', lieType:lieType, newData: newData });
    }

    //so everytime you use the updateLies method, we can have a listener respond
    //and pass the data
}

var filthyLies = new PoliticianData();

$(filthyLies).on('update', function(e){
    stickNewDataInHTMLWithSomeFuncDefinedElsewhere(e.lieType, e.newData);
} );

filthyLies.update('damnedLies','50% of the people said they didn\'t give a damn');
//oh look, WaPo's front page just changed!
  • Не скрывайте Интернет Основной источник неприятностей во всех ранних попытках сделать клиентскую часть легкой для серверной части и разработчиков приложений зависела от этой критической точки. HTTP-запросы не были и никогда не были сложными. Им не требовалось уродливого слоя 18! @ # $ Ing confusion-event-name-at-each-stage monstrosity, чтобы его было легче понять. Кроме того, есть много информации о клиентской стороне, но нет причин скрываться от HTML и DOM, которые взаимодействуют с ним, накладывая на него гигантскую гигантскую модель. Это уже большая гигантская модель, и она работает очень хорошо. Все, что нам нужно, чтобы сделать его немного более управляемым, - это некоторые разумные методы ООП и знания JS и DOM.

  • Фавор Гибкость

EXTjs <==== гибкость масштабирования ====> jQuery (не обязательно любой из его плагинов)

ИМО, инструменты, которые позволят вам быстро сделать DIY, всегда лучший выбор. Инструменты, которые сделали все это для вас, - это только правильный выбор, когда никто над вашей головой не особенно разборчив в деталях, и вы не против сдать контроль над тем, что должно вам помочь. Я на самом деле видел плагины, которые проверяют HTML, чтобы убедиться, что вы не крадете элемент другого типа с точно такими же чертами отображения. Зачем? У меня есть только теории. Я думаю, что все сводится к тому, что константисты действительно ненавидят идею того, что кто-то использует их вещи не по назначению, и это всегда неизбежно то, что кто-то хочет, чтобы вы делали в пользовательском интерфейсе.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.