...

суббота, 1 марта 2014 г.

[Из песочницы] 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"))


Чем лучше:



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, но с очень важными отличиями


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




  • Да, да и снова это типизация – это достигается за счет использования C# на всех этапах ( template, client scenario and etc ) разработки

  • Один язык для backend и frontend — разработчик знающий C# может без проблем освоить IML и далее вызывать свои Command и Query на клиенте


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


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


Комментариев нет:

Отправить комментарий