Как я могу избежать суп-суп с помощью MVC?

Я читал это в своих поисках, чтобы оправдать MVC над не-mvc, как обычный старый php (не используя MVC, даже классический asp мог бы использоваться, хотя и больно):

http://www.codinghorror.com/blog/2008/07/web-development-as-tag-soup.html

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

Я не буду использовать модульное тестирование, поэтому это не так важно. Я не уверен, как я могу избежать уродливого взгляда, теперь важно, как я получаю это wither mvc или просто испуская html.

Я не вижу, чтобы было легче поддерживать представление со всем странным кодированием (и это код), чем с помощью response.write "<table>".

example: Работа с суп-тегом ASP.NET MVC "

Ответ Арниса (без обид ему или кому-либо еще), исправляет ужасный код в вопросе, но для меня это все еще выглядит плохо или, по крайней мере, не то, что я ожидаю. Для меня эти угловые скобки также могли быть <% %> или <?php ?>.

Мне нравятся такие вещи, как codeigniter, и это действительно самое чистое, что я видел, но это все еще не то, что я ожидаю. Я думаю, я надеялся, что в MVC присутствует какая-то магия, которая сделала все красивым. По-видимому, если кто-то действительно не очень осторожен, там не лучше, чем с классическим asp, поскольку это относится к представлению.

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

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

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

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

Ответы

Ответ 1

Посмотрите на использование механизма просмотра Razor, который включен в MVC 3. Также попробуйте сохранить всю свою логику в классе Controller и построить модель на основе того, что отображается в представлении.

  • Razor - один из очевидных способов избежать супа для тегов, поскольку нет необходимости в каких-либо тегах <% и %> - просто @ перед тем, как ваш код и механизм просмотра будут работать где заканчивается С# и начинается HTML.

    <span class="name">@Model.Name</span>
    

    Четные циклы, и если утверждения по-прежнему выглядят сексуально в файле .cshtml с помощью Razor и этого волшебного символа @.

    @if(shouldDisplayDiv) {
        <div id="mydiv">Div is displayed!</div>
    }
    
    
    @foreach(User user in Model.Friends) {
        <a href="@user.Url"><img src="@user.ImageUrl" title="@user.Name" /></a>
    }
    

    Razor также обрабатывает HTML-кодировку по умолчанию, поэтому ваше представление не будет заполнено вызовами Html.Encode. (Примечание: если вам нужно вывести HTML, вы можете использовать вспомогательный метод Html.Raw).

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

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

  • Помощники HTML также очень полезны (спасибо subkamran). Там аналогичная концепция здесь относится к частичным представлениям, упомянутым выше, но HtmlHelpers несколько отличаются, потому что вы указываете параметры метода (и их типы), в отличие от частичных представлений, которые вы можете передать одному объекту модели. Вот хороший пример того, как их реализовать. Опять же, они могут выглядеть очень аккуратно в вашем коде cshtml.

     <div class="specialdiv">@Html.SomeMethod(Model, "String", 5)</div>
    
  • MVC на стороне клиента - это еще один вариант и сильное предложение, если вы разрабатываете тяжелые веб-приложения AJAX. Следуя логике в контроллере, вы должны использовать структуру MVC на стороне клиента, например Backbone.js, в шаблон HTML, и использовать jQuery .ajax() для разговора с вашим контроллером. Это отличная практика для разделения вашего слоя презентации, оставляя вас с красивой разметкой вида!

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

РЕДАКТИРОВАТЬ: Обратите внимание, что все эти пункты включены в ASP.NET MVC 3, и все "лучшие практики" далеки от Microsoft. Нет необходимости устанавливать какие-либо дополнительные фреймворки, плагины или дополнения, чтобы придерживаться этих рекомендаций.

Ответ 2

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

Также важно понять, что такое MVC: http://en.wikipedia.org/wiki/Model-view-controller. Преимущества, которые вы получаете от него, - это более чистое разделение и простая замена.

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

У меня 7 лет опыта написания приложения в формах ASP.NET. Как только я переключился на MVC и начал понимать MVC, я понял, что никогда не вернусь. Представления чище, отладка проще и логика более очевидна. Последнее приложение, которое я написал, использует MVC и jQuery, имеет 3000 пользователей в день и стало образцовым сайтом, для которого теперь все наши сайты написаны.

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

Пока пример кода из http://www.codinghorror.com/blog/2008/07/web-development-as-tag-soup.html выглядит ужасно, вы когда-нибудь смотрели на ASP.NET GridView? HTML ужасен. Образец, который вы предоставили, также показывает того, кто мог бы сделать некоторую работу, чтобы очистить свои взгляды. Ниже приведено сравнение gridview vs MVC с Razor:

GridView:

<asp:datagrid id="voucherGrid" runat="server" CssClass="dg" CellPadding="2" AutoGenerateColumns="False" DataKeyField="cx_nbr" 
        Width="800px" AllowPaging="True" AllowSorting="True" PageSize="20" OnPageIndexChanged="voucherGrid_PageIndexChanged" 
        OnSortCommand="voucherGrid_SortCommand" OnItemDataBound="voucherGrid_ItemDataBound">
        <SelectedItemStyle CssClass="dgSelectItem"></SelectedItemStyle>
        <AlternatingItemStyle CssClass="dgAlternateItem"></AlternatingItemStyle>
        <ItemStyle CssClass="dgNormalItem"></ItemStyle>
        <HeaderStyle ForeColor="White" CssClass="dgHeader"></HeaderStyle>

        <Columns>
            <asp:TemplateColumn HeaderText="Image">
                <ItemStyle HorizontalAlign="Center"></ItemStyle>
                <ItemTemplate>
                    <asp:HyperLink id="voucherImageLink" Target="_blank" runat="server">Image</asp:HyperLink>                                               
                </ItemTemplate>
            </asp:TemplateColumn>
            <asp:BoundColumn DataField="cx_voucher_nbr" SortExpression="cx_voucher_nbr" HeaderText="Call #">
                <ItemStyle HorizontalAlign="Center"></ItemStyle>
            </asp:BoundColumn>
            <asp:BoundColumn DataField="cx_pkup_datetime" SortExpression="cx_pkup_datetime" HeaderText="Date" DataFormatString="{0:MM/dd/yyyy}">
                <ItemStyle HorizontalAlign="Center"></ItemStyle>
            </asp:BoundColumn>
            <asp:BoundColumn DataField="cx_pass_name" SortExpression="cx_pass_name" HeaderText="Passenger">
                <ItemStyle Wrap="False"></ItemStyle>
            </asp:BoundColumn>
            <asp:BoundColumn DataField="cx_pkup_address" SortExpression="cx_pkup_address" HeaderText="Pick-Up">
                <ItemStyle Wrap="False"></ItemStyle>
            </asp:BoundColumn>
            <asp:BoundColumn DataField="cx_dest_address" SortExpression="cx_dest_address" HeaderText="Destination">
                <ItemStyle Wrap="False"></ItemStyle>
            </asp:BoundColumn>
            <asp:BoundColumn DataField="cx_trip_miles" SortExpression="cx_trip_miles" HeaderText="Miles" DataFormatString="{0:N2}">
                <ItemStyle HorizontalAlign="Right"></ItemStyle>
            </asp:BoundColumn>
            <asp:BoundColumn DataField="cx_pkup_datetime" SortExpression="cx_pkup_datetime" HeaderText="Time" DataFormatString="{0:t}">
                <ItemStyle HorizontalAlign="Center"></ItemStyle>
            </asp:BoundColumn>
            <asp:BoundColumn DataField="cx_vch_wait_time_amt" SortExpression="cx_vch_wait_time_amt" HeaderText="Wait" DataFormatString="{0:C}">
                <ItemStyle HorizontalAlign="Right"></ItemStyle>
            </asp:BoundColumn>
            <asp:BoundColumn DataField="cx_vch_other_amt" SortExpression="cx_vch_other_amt" HeaderText="Other" DataFormatString="{0:C}">
                <ItemStyle HorizontalAlign="Right"></ItemStyle>
            </asp:BoundColumn>
            <asp:BoundColumn DataField="cx_vch_admin_charge_amt" SortExpression="cx_vch_admin_charge_amt" HeaderText="Admin Charge" DataFormatString="{0:C}">
                <ItemStyle HorizontalAlign="Right"></ItemStyle>
            </asp:BoundColumn>
            <asp:BoundColumn DataField="cx_vch_fare_amt" SortExpression="cx_vch_fare_amt" HeaderText="Rate" DataFormatString="{0:C}">
                <ItemStyle HorizontalAlign="Right"></ItemStyle>
            </asp:BoundColumn>
        </Columns>

        <PagerStyle ForeColor="White" CssClass="dgPager" Mode="NumericPages"></PagerStyle>
    </asp:datagrid>

Бритва:

<table id="voucherGrid" class="dg" style="width: 800px;">
   <th class="dgHeader">
      <td>Image</td>
      <td>Call #</td>
      <td>Date</td>
      <td>Passenger</td>
      <td>Pick-Up</td>
      <td>Destination</td>
      <td>Miles</td>
      <td>Time</td>
      <td>Wait</td>
      <td>Other</td>
      <td>Admin Charge</td>
      <td>Rate</td>
   </th>
   @foreach(var voucher in Model.Vouchers) {
   <tr>
      <td>@voucher.Image</td>
      <td>@voucher.CallNum</td>
      <td>@voucher.Date</td>
      <td>@voucher.Passenger</td>
      <td>@voucher.PickUp</td>
      <td>@voucher.Destination</td>
      <td>@voucher.Miles</td>
      <td>@voucher.Time</td>
      <td>@voucher.Wait</td>
      <td>@voucher.Other</td>
      <td>@voucher.AdminCharge</td>
      <td>@voucher.Rate</td>
   </tr>
   }
</table>

Ты говоришь мне, что легче понять? Для меня это намного чище, чтобы иметь дело с html-тегами и несколькими дополнительными тегами @или <%.

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

Ответ 3

Там и обратно. Опять и опять. Сырой HTML. Dreamwearver. ASP. MS Word. ASP.NET, MVC.NET. Мы, кажется, можем поразить любой конец спектра, но в середине нет сладкого пятна.

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

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

Структура MVC, такая как Ruby on Rails или MVC.NET, поможет повысить эффективность кодирования при кодировании в парадигме MVC; это не сделает вас быстрее кода как такового. И это, безусловно, не помешает кошмару кодового обслуживания, если вы не знаете, какого черта вы делаете.

Ответ 4

  • Использовать движок просмотра razr (Мое предпочтение, я думаю, он выглядит аккуратно). response.write "<table>" достаточно легко написать. Но делаете ли вы это в файле/классе, который ТОЛЬКО контролирует представление и может быть легко заменен или изменен, не касаясь какой-либо логики обслуживания? Это подводит меня к # 2.
  • Обсудите разделение проблем с вашей группой и определите, где живет каждая часть логики. Где находятся контрольные точки зависимостей, все ли ваша логика сгруппированы в DLL, которые не имеют представления о просмотрах/контроллерах? Решите от начала и запишите его где-нибудь.
  • Сохранять представления как виды!
  • Не делайте ничего с точки зрения!
  • Как только вы на виду, вы просто просматриваете!
  • Я упомянул, что взгляды - это только то, что?

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

мои 2cents

Ответ 5

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

  • Код, который преобразует данные в HTML, является логикой отображения.
  • Код, который создает или получает данные, которые впоследствии преобразуются в HTML, не отображает логику.

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

Ответ 6

Не делайте никаких вычислений в вашем шаблоне кода.

Взгляните на то, что разрешено в Django: https://docs.djangoproject.com/en/1.3/topics/templates/

Нет арифметики. Отсутствие параметров для методов. Никаких определений какого-либо рода (кроме как в циклах). Это заставляет вас делать почти все в методах представления и передавать любые требуемые объекты и списки, что сохраняет его в чистоте.

Ответ 7

Вы можете использовать GWT, ZK, Vaadin, JSF 2 или что-то, что скрывает HTML. Я не знаю, что вы подразумеваете под MVC. Модель Django/RoR/CakePHP Model-View-Presenter, иногда называемая MVC или реальным MVC. Если вы придерживаетесь MVC, у вас должен быть ТОЛЬКО привязка данных и триггеры событий в вашем коде просмотра.

Я думаю, что это проблема дизайна, а не технология.