AngularJS vs IML

от автора

image

disclaimer: сравнение не подразумевает поднятие “холивара”, а делает обзор задач, решаемых одним инструментом в сравнении с другим. Я не являюсь знатоком всех тонкостей angularJs, но прочитав 10 статьей обзора этого инструмента, привожу альтернативный пример решения тех же самых задач на IML.

Что будем сравнивать ?

  • Controller
  • Inheritance
    примечание: отсутствует в IML
  • Accessing server
  • Push data
  • Submit form
  • Template
  • Promises
    примечание: отсутствует в IML и может быть полезным только при работе со сторонними сервисами, а так решается все с помощью продуманного выбора данных для возврата.

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

Как будем сравнивать ?

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

Controller

Angular JS View

<div ng-controller="angularController"> <button ng-click="sayHello()">Say</button> </div> 

Angular JS

app.controller('angualrController', function ($scope) {   $scope.sayHello = function(){       alert('Hello')     }  }); 

IML

@(Html.When(JqueryBind.Click)       .Do()       .Direct()       .OnSuccess(dsl => dsl.Utilities.Window.Alert("Hello"))       .AsHtmlAttributes()       .ToButton("Say")) 
Чем лучше :

  • Поведение и разметка вместе
    примечание: многим данный момент покажется спорным, из-за того, что логика усложняет работу верстальщикам страниц, но в рамках asp.net mvc, C# код во View ( cshtml ) неотъемлемая часть и поэтому те преимущества, которые можно получить полностью перекрываю довольно таки абстрактную модель разработки логики отдельно от разметки.
  • Поддержка Initilesence
    примечание: атрибуты AngularJs не являются стандартом html, поэтому подсветки синтаксиса или авто-дополнения не будет, а IML это C# библиотека.
  • События представляют флаги
    примечание: упрощает группировку, когда надо продублировать действия для другого события When(JqueryBind.Click | JqueryBind.Focus)
  • Управлением поведением события ( Prevent Default, Stop Propagation)
    примечание: AngularJS позволяет управлять этим в рамках метода контроллера, но IML включает это как часть общей схемы
Accessing Server

Серверный код

public ActionResult Get(GetProductByCodeQuery query) {  List  vms = dispatcher.Query(query);  return IncJson(vms); // for AngularJs need use Json with AllowGet } 

примечание: серверная часть одинакова, как для AngularJS, так и для IML

Angular Html

<div ng-conroller="productController">  @Html.TextBoxFor(r => r.Code)  <label>{{model.Name}}</label>  <button>Get name</button> </div> 

Angular Js

kitchen.controller('productController', function ($scope, $http) {   $scope.get = function(){     $http.get({                 url:'product/get',                 params:{Code:$('[Name="Code"]').val()}               })           .success(function(data) {                $scope.Name = data.Name            });  } }); 

IML

@{ var labelId = Guid.NewGuid().ToString(); } @Html.TextBoxFor(r=>r.Code) @(Html.When(JqueryBind.Click)   .Do()   .AjaxGet(Url.Action("Product","Get",new {                        Code = Html.Selector().Name(r=>r.Code)                       })   .OnSuccess(dsl => dsl.WithId(labelId).Core().Insert.For(r=>r.Name).Text())   .AsHtmlAttributes()   .ToButton("Get name")) 

примечание: при построение url, можно использовать в качестве Routes не только анонимный объект, но и типизированный вариант Url.Action(“Product”,”Get”,new GetProductQuery() { Code = Html.Selector().Name(r=>r.Code) })

Чем лучше:

  • Типизация на всех этапах
    • Url – адрес в AngularJs строится без серверной части, что не позволяет учитывать route и отсутствие возможности перейти ( переименовать ) в Action из кода.
      примечание: по скольку руководство по AngularJs рекомендует выносить JavaScript код во внешний файл, то по этой причине не получится использовать серверные переменные в рамках js кода.
    • Query – AngularJs не связан с серверной моделью и не позволяет получить схему модели, что как и в случае с Url не позволяет использовать инструменты для переименования и go to declaration
      примечание: в случаи с IML, если мы переименуем поле Name или Code в GetProductQuery, то изменения отразятся и на клиентскую часть, но для AngularJs придется дополнительно заменить {{model.Name}} и $(‘[Name=«code»]‘) на новые значения.
    • Selector – для указания параметров запроса в рамках IML можно использовать мощный инструмент для получения значений из Dom ( hash, cookies, js variable and etc ) объектов

  • MVD

В Incoding Framework можно обойтись без написания дополнительных Controller и Action если в качестве url применить MVD

Url.Dispatcher().Query(new GetProductQuery() {Code = Html.Selector().Name(r=>r.Code)}).AsJson() 
Push data

Серверный код

public ActionResult Add(AddCommand input) {  dispatcher.Push(input); return IncJson(); // for AngularJS need use Json() } 

примечание: серверная часть одинакова, как для AngularJS, так и для IML

Angular View

<div ng-controller="productController">   @Html.TextBoxFor(r => r.Name)    @Html.CheckboxFor(r => r.IsGood)   <button ng-click="add"> Add </button> </div> 

Angular JS

kitchen.controller('productController', function ($scope, $http) {  $scope.add = function(){     $http({        url: 'product/Add',        method: "POST",        data: {               Name : $('[name="Name"]').val(),              IsGood : $('name="IsGood"]').is(':checked')              }          })       .success(function(data) { alert('success') }); }); 

IML

@Html.TextBoxFor(r=>r.Name) @Html.CheckboxFor(r=>r.IsGood) @(Html.When(JqueryBind.Click)       .Do()       .AjaxPost(Url.Action("Product","Add",new {                                                  Name = Html.Selector().Name(r=>r.Name),                                                  IsGood = Html.Selector().Name(r=>r.IsGood)                                                }))       .OnSuccess(dsl => dsl.Utilities.Window.Alert("Success"))       .AsHtmlAttributes()       .ToButton("Add")) 
Чем лучше:

  • MVD
    как и в предыдущем примере когда мы делали Query, в Incoding Framework можно выполнять push без написания Action
    Url.Disaptcher().Push( new {                                    Name = Html.Selector().Name(r=>r.Name),                                    IsGood = Html.Selector().Name(r=>r.IsGood)                             }) 

  • Selector абстрагирует от способа получения значения
    примечание: на примере видно, что для получения значения из checkbox нужно использовать is(‘:checked’), но в IML этот момент не требуется указывать
Submit Form

Angular View

<div ng-controller="productController">    <form name="AddForm">     @Html.TextBoxFor(r => r.Name)     @Html.CheckboxFor(r => r.IsGood)      <input type="submit" value="save"  ng-submit="submit" />   </form> </div> 

Angular JS

controller('productController', function ($scope, $http) {  $scope.submit = function(){     $http({        url: 'product/Add',        method: "POST",        data: angular.toJson($scope.addForm)         }).success(function(data) { alert('success') }); }); 

IML

@using(Html.When(JqueryBind.Submit)            .DoWithPreventDefault()            .Submit()            .OnSuccess(dsl => dsl.Utilities.Window.Alert("Success"))            .AsHtmlAttributes()            .ToBeginForm(Url.Action("Product","Add")))  {     @Html.TextBoxFor(r=>r.Name)     @Html.CheckboxFor(r=>r.IsGood)     <input type="submit" value="add">  } 

Чем лучше:

  • Отправка формы в одну строку
    примечание: angularJs работает с формой точно так же, как и с обычным ajax запросом, что требует указания параметров Url, Type, Data

Template

Серверный код

public ActionResult Fetch() {    var vms = new List()      {       new PersonVm(){ Last= "Vasy", First = "Smith", Middle = "Junior"},       new PersonVm(){ Last= "Vlad", First = "Smith", Middle = "Mr"},      };   return IncJson(vms); // for angular need use Json with AllowGet } 

примечание: серверная часть одинакова, как для AngularJS, так и для IML

Angular Template

<script id="person.html" type="text/ng-template"> {{person.last}}, {{person.first}} {{person.middle}} </script> 

Angular View

<div ng-controller="productAddForm">   <div ng-repear="person in persons" ng-template="person.html">      </div> </div> 

Angular JS

app.controller('personController', function ($scope,$http) {    $scope.refresh= function(){       $http.get('person/fetch', function(data){                            $scope.Persons= data        });    }  }); 

IML Template

@{     var tmplId = Guid.NewGuid().ToString();     using (var template = Html.Incoding().Template(tmplId))     {       using (var each = template.ForEach())       {  @each.For(r=>r.First),@each.For(r=>r.Middle),@each.For(r=>r.Last) }     } } 

IML View

@(Html.When(JqueryBind.InitIncoding)  .Do()  .AjaxGet(Url.Action("Personal","Fetch"))  .OnSuccess(dsl => dsl.Self().Core().Insert.WithTemplate(tmplId.ToId()).Html())  .AsHtmlAttributes()  .ToDiv()) 

Чем лучше :
  • Опять типизация
    примечание: Incoding template требует больше кода для реализации типизированного синтаксиса, но это окупается при дальнейшей поддержке
  • Один template для одного или многих объектов
  • Замена template engine
  • Поиск template по Selector, что имеет больше возможностей ( ajax, cookies and etc )
  • Cache
    AngularJs имеет механизм работы с Cache, но с очень важными отличиями
    • Требует настройки для каждого template отдельно
      myApp.run(function($templateCache) {   $templateCache.put('templateId.html', 'This is the content of the template'); }); 

    • Не хранится между сессиями
      примечание: Incoding Framework сохраняет пре-компилированную версию template в local storage, что позволяет после первого прохода пользователем все последующие обращения к template брать сразу из local storage.

В чем же общие преимущество:

  • Да, да и снова это типизация – это достигается за счет использования C# на всех этапах ( template, client scenario and etc ) разработки
  • Один язык для backend и frontend — разработчик знающий C# может без проблем освоить IML и далее вызывать свои Command и Query на клиенте

Вывод: AngularJs разворачивает mvc архитектуру на клиенте, что с одной стороны позволяет структурировать код, но так же добавляет дополнительные проблемы в поддержке. Разработчик asp.net mvc имеет серверную реализацию mvc, где применяя более мощные и подходящие языки, можно избежать усложнения.

ссылка на оригинал статьи http://habrahabr.ru/post/214293/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *