AngularJs vs IML 17

Article3_Medium

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

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

примечание:  отсутствует в IML

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

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

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

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

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

 

Controller

Angular JS

View

JS

IML

Чем лучше :
  • Поведение и разметка вместе

примечание: многим данный момент покажется  спорным, из-за того, что логика усложняет работу верстальщикам страниц, но в рамках asp.net mvc,  C# код во View ( cshtml )  неотъемлемая часть и поэтому те преимущества, которые можно получить  полностью перекрываю довольно таки абстрактную модель разработки логики отдельно от разметки.

  • Поддержка Initilesence 

примечание: атрибуты AngularJs не являются стандартом html, поэтому подсветки синтаксиса или авто-дополнения не будет, а IML это C# библиотека.

  • События представляют флаги

примечание:  упрощает группировку, когда надо продублировать действия для другого события When(JqueryBind.Click | JqueryBind.Focus)

  • Управлением поведением события ( Prevent Default, Stop Propagation) 

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

Accessing Server

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

AngularJS
View

JS

 IML

примечание: при построение 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

Push data

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

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

Angular
View

 JS

IML

Чем лучше:
  •  MVD 

как и в предыдущем примере когда мы делали Query, в Incoding Framework можно выполнять push без написания Action

  •  Selector абстрагирует от способа получения значения

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

Submit Form

Angular
View

JS

 IML

Чем лучше:
  • Отправка формы в одну строку

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

Template

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

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

Angular JS
Template

View
JS

IML
Template

View

Чем лучше :
  •  Опять типизация

примечание: Incoding template требует больше кода для реализации типизированного синтаксиса, но это окупается при дальнейшей поддержке

  • Один template для одного или многих объектов
  • Замена template engine
  • Поиск template по Selector, что имеет больше возможностей ( ajax , cookies and etc )
  • Cache ( подробней )

AngularJs  имеет механизм работы с Cache, но с очень важными отличиями

    • Требует настройки для каждого 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, где применяя более мощные и подходящие языки, можно избежать усложнения.

Vlad Kopachinsky

I am a Senior developer at Incoding Software in Russian Federation. I created the Incoding Framework for rapid development

More Posts - Website - Twitter - Facebook - LinkedIn

17 thoughts on “AngularJs vs IML

  1. Shaddix 27.02.2014 Thu, 27 Feb 2014 15:09:22 +0000

    Безусловно, IML дает очень удобные шорткаты для типовых действий, для отправки форм, что и требуется во многих “простых” случаях.
    Однако основное назначение Angular – построение сложных клиентских приложений с использованием MVVM.

    В случае же IML, если я правильно понимаю, вы предлагаете при изменении модели перерисовывать view на сервере(asp.net mvc). Это мне слегка напоминает подход WebForms, когда на каждый клик кнопки происходил серверный вызов.

    Простейшим и типичным примером Angular-приложения может служить что-то вроде:

    Привет, {{model.Name}}
    Где значение “Привет, ХХХ” динамически обновлялось бы при вводе имени. Может ли это IML?

    Мне кажется, что если бы сравнение проходило с JS-шаблонизаторами (Mustache, handlebars, etc), то оно было бы более корректным. Но даже в этом случае сравнивались бы шаблонизация на клиенте и на сервере, а это принципиально разные вещи.

    • Vlad Kopachinsky 27.02.2014 Thu, 27 Feb 2014 15:21:56 +0000

      Где значение “Привет, ХХХ” динамически обновлялось бы при вводе имени. Может ли это IML?

      Конечно IML это может, вот рабочий код.

      @{ string labelId = Guid.NewGuid().ToString();}
      @(Html.When(JqueryBind.KeyPress)
      .Do()
      .Direct()
      .OnSuccess(dsl => dsl.WithId(labelId).Core().Jquery.Manipulation.Text(Selector.Jquery.Self()))
      .AsHtmlAttributes()
      .ToInput(HtmlInputType.Text, ""))

      Мне кажется, что если бы сравнение проходило с JS-шаблонизаторами (Mustache, handlebars, etc), то оно было бы более корректным

      Template это только одна часть IML, по факту тот же hanldebars используется для построения, но это не основная работа IML, можно убедится в этом на примере do, action, insert

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

      не совсем понял вопрос, потому что IML выполняет template на клиенте, client template

      В случае же IML, если я правильно понимаю, вы предлагаете при изменении модели перерисовывать view на сервере(asp.net mvc)

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

      Это мне слегка напоминает подход WebForms, когда на каждый клик кнопки происходил серверный вызов.

      А разве AngularJS не используется Ajax для вызова сервера? Вы можете делать Direct и тогда это будет просто обработчик на клиенте.

      • Shaddix 28.02.2014 Fri, 28 Feb 2014 03:14:27 +0000

        не совсем понял вопрос, потому что IML выполняет template на клиенте

        Спасибо за указание, я действительно упустил, что IML включает “клиентскую” шаблонизацию. Ваша реализация весьма любопытная, возможность использования разных js-шаблонизаторов “под капотом” действительно удивила.

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

        Конечно IML это может, вот рабочий код.

        Если продолжить логику, то AngularJS в принципе не нужен, и можно везде использовать JQuery 🙂
        Я думаю, вы тоже понимаете, что чем больше становится клиентской логики, тем более сложным и непрозрачным становится “ручное” манипулирование DOM’ом.
        Конечно, в простых случаях можно (и нужно) обойтись jquery, и IML в этом случае также справится. Для сложных и придуман Angular, и здесь IML проигрывает (что неудивительно, IML – фреймворк более общего назначения, что ли).

        В целом, основным минусом IML мне кажется как раз попытка “избавиться” от js. Конечно, это дает свои плюсы – строгую типизацию, например. Но и минусы (по сравнению с использованием JS) – инвестиции в изучение, проблемы в “сложных” сценариях.
        В этом плане просматривается параллель с тем же TypeScript – за ним стоит Майкрософт, а все равно внедрение в рынок очень небыстрое.

        • Vlad Kopachinsky 28.02.2014 Fri, 28 Feb 2014 05:17:45 +0000

          Было бы, конечно, совсем замечательно, если бы сохранился синтаксис Razor 🙂

          Razor, кроме символа “@” особо ничего своего не имеет, потому что по факту Вы пишите C#.

          Ваш dsl необходимо изучать, с ходу он не совсем понятен.

          В этой статье я представляю сразу примеры решения задач, но не описывая работу DSL, поэтому для быстрого понимания стоит начать со структурной схемы работы и Jquery vs IML. В ближайшее время постараюсь оформить более подробное руководство.

          Если продолжить логику, то AngularJS в принципе не нужен, и можно везде использовать JQuery

          Согласен, чтобы построить сложное приложение ( не обязательно SPA ) на клиенте, то написанием скриптов на Jquery сложно (а ещё сложнее поддерживать), но разворачивая MVC или MVVM мы тоже усложняем код. Разница между IML и Jquery в том, что в первом из коробки идет набор инструментов для решения задач, а также плотная интеграция с серверной частью, которая позволяет поддерживать типизацию на всех ( ниже будет пример ) этапах.

          Я думаю, вы тоже понимаете, что чем больше становится клиентской логики, тем более сложным и непрозрачным становится “ручное” манипулирование DOM’ом.

          А разве в AngularJS не приходится работать с DOM (получить Val у элемента, скрыть и т.д.) средствами Jquery?

          Конечно, в простых случаях можно (и нужно) обойтись jquery, и IML в этом случае также справится.

          Мы выполнили десятки сложных проектов на IML, вот к примеру

          Для сложных и придуман Angular, и здесь IML проигрывает (что неудивительно, IML – фреймворк более общего назначения, что ли).

          Хорошо, приведу пример IML, а Вы если будет время переделайте ( если интересно, то я могу переделать Ваш пример AngularJs на IML ) его на AngularJS и сравним.

          @{
          string urlAuthorize = Url.Dispatcher()
          .Query(new IsAutorizeUserQuery
          {
          UserId = Selector.Incoding.Cookie("UserId")
          })
          .AsJson();
          }
          @(Html.When(JqueryBind.InitIncoding)
          .Do()
          .AjaxGet(urlAuthorize)
          .OnSuccess(dsl => dsl.Self().Core().Trigger.Invoke("SignIn")
          .If(builder => builder.Data(response => !response.IsHas)))
          .When("SignIn")
          .Do()
          .AjaxGet(Url.Dispatcher().AsView("~/Views/Admin/Account/SignIn.cshtml"))
          .OnSuccess(dsl => dsl.WithId(GlobalSelector.DialogId)
          .Behaviors(inDsl =>
          {
          inDsl.Core().Insert.Html();
          inDsl.JqueryUI().Dialog.Open(options => options.Title = "Sign In");
          }))
          .AsHtmlAttributes()
          .ToDiv())

          Пример проверяет авторизирован ли пользователь и если нет, то показывает Dialog, в котором View Sign In, стоит отметить плюс IML в том, что не надо искать логику по всему проекту. Разметка в комментариях конечно представлена не очень, по этом лучше перенести в Visual Studio ( в любой cshtml файл )

          минусы (по сравнению с использованием JS) – инвестиции в изучение, проблемы в “сложных” сценариях.

          1. инвестиции в изучение – AngularJS не требует изучения их директив и разметки? IML это C# библиотека, что позволяет нажать “ctrl + space” и увидеть, что можно делать, скажем тот же AngularJS не имеет ( ну по крайней мере без дополнений ) подсветки синтаксиса.
          2. проблемы в “сложных” сценариях – мне кажется Вы рано начали судить о возможностях IML, особо не изучив. Я понимаю, что это требует время, поэтому вот видео, которое демонстрирует самые ( их на самом деле в разы больше ) основные возможности IML.

          В этом плане просматривается параллель с тем же TypeScript – за ним стоит Майкрософт, а все равно внедрение в рынок очень небыстрое.

          Сходства никакого нет, потому что TypeScript это язык без функциональной части, то есть работа с Hash, Ajax, Dom да и вообще любое действие требует написания кода для решения задачи, а IML это framework для разработки.

          P.S. Спасибо за комментарии, я всегда рад хорошей аргументированной дискуссии. Кстати напомню, что IML очень хорош в комплексе с остальными частями framework, например MVD

  2. Shaddix 08.03.2014 Sat, 08 Mar 2014 07:09:17 +0000

    А разве в AngularJS не приходится работать с DOM (получить Val у элемента, скрыть и т.д.) средствами Jquery?

    нет, работать с jquery из контроллеров обычно нет необходимости.
    И пример Push Data мог бы на самом деле выглядеть как-то так:

    Add

    $scope.Form = @Model.ToJSON();
    $scope.add = function(){
    $http({
    url: 'product/Add',
    method: "POST",
    data: $scope.Form
    })
    .success(function(data) { alert('success') });
    });

    Пример, который ты привел на IML, конечно, развернется в нечто большее в случае Angular. В основном потому, что если мы имеем просто набор форм и их отправку, то в использовании Angular нет необходимости, это не тот кейс, для которого Angular создавался. Для аяксовой отправки форм действительно логичнее использовать либо собственные хэлперы (которые, в частности, есть и в IML), либо встроенные в MVC варианты от Майкрософт типа @Ajax.BeginForm. В параллельном использовании их и Angular нет ничего необычного.

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

    • Vlad Kopachinsky 08.03.2014 Sat, 08 Mar 2014 07:43:36 +0000

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

      Может конечно я субъективен, но когда речь идет о фильтрации, то тут скорей предпочтительней сервер, который имеет много чего для оптимизации. Но, IML тоже имеет средства для фильтрации.
      @(Html.When(JqueryBind.Click)
      .Do()
      .Direct(new List {
      new PostCommand{CheckBox = true,TextBox = "Well"},
      new PostCommand{CheckBox = false,TextBox = "Bad"},
      })
      .Where
      (r => r.CheckBox == Selector.Jquery.Name(whereName))

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

      Чаще всего пайджниг или сортировка идет по все таблице, к примеру таблица в миллион записей, на вряд ли будет удобная для транспортировки на клиента .

      пример Push Data мог бы на самом деле выглядеть как-то так:

      Стоит заметить, что адрес ( url: ‘product/Add’ ) не поддерживает Asp.mvc routes ( а так же rename и т.д. )

      либо встроенные в MVC варианты от Майкрософт типа @Ajax.BeginForm.

      Я писал об этом

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

      P.S. IML это не набор хелперов, а полноценный декларативный язык.

  3. mark goldin 20.06.2014 Fri, 20 Jun 2014 16:35:08 +0000

    So, you are saying that IML allows us to create SPA applications without JS. Well, how about UI specific functionality? What about using custom UI widgets? Do you have any samples for that?

    Thanks

    • Vlad Kopachinsky 20.06.2014 Fri, 20 Jun 2014 19:13:19 +0000

      Do you have any samples for that?

      You can look sample application TODO MVC ( refactor version ) or at look other our repositories

      how about UI specific functionality?

      Sure, you are can use any jquery plugin.
      Actual 2 way :
      1. Use iml contrib ( Dialog , Datepicker and other JQuery UI )

      r.WithId(targetId).JqueryUI().Dialog.Open(options =>;
      {
      options.HideOnClose = true;
      options.Title = "Title";
      options.CloseOnEscape = true;
      options.Draggable = true;
      options.Show = JqueryShowOptions.Slow;
      });
      })

      2. Call jquery plugin

      r.Self().Core().Jquery.PlugIn("plugInName",new { Opt = 1, NextOpt = 2})

      What about using custom UI widgets?

      We are “package” our controll with C# extensions ( please look sample ).
      Sample usage

      @Html.Todo().Container(setting =>
      {
      setting.Id = containerId;
      setting.Url = Url.Dispatcher().Query().AsJson();
      setting.Tmpl = Url.Dispatcher()
      .Model(new GetTodoByClientQuery.Tmpl { FooterId = footerId })
      .AsView("~/Views/Home/Todo_List_Tmpl.cshtml");
      setting.DependencyId = footerId;
      })

      We are developing powerfull controll ( widjet ) Grid

      P.S. Let me know if you have any question or suggestion. Thanks

  4. mark goldin 20.06.2014 Fri, 20 Jun 2014 19:19:03 +0000

    But with Angular I can use UI libraries open source or commercial, it’s not as easy but very possible. Seems like that is not an option with IML. Am I correct? Do you have any plans on that?

    Thanks

    • Vlad Kopachinsky 20.06.2014 Fri, 20 Jun 2014 19:29:21 +0000

      IML have ability call JavaScript function or eval code

      dsl.Self().Core().Eval("some code"); // eval("some code")
      dsl.Self().Core().Call("name",Selector.Jquery.Id("id")); // eval("name($('#id').val())
      dsl.Self().Core().Jquery.Call("name"); // $(this.self).name()

      dsl.Self().Core().Jquery.PlugIn("name",new { Color = "red" }) // $(this.self).name({color:"red"})
      dsl.Self().Core().Name("red") // C# extensions as alternative above sample

  5. mark goldin 20.06.2014 Fri, 20 Jun 2014 19:35:19 +0000

    Would it be possible to put together a small working sample? I am just starting looking into IML and it’s hard for me to understand how the provided code works.

    Thanks

  6. mark goldin 20.06.2014 Fri, 20 Jun 2014 20:07:12 +0000

    <and more content but only by Russian language
    Did you mean documentation in Russian?

  7. mark goldin 20.06.2014 Fri, 20 Jun 2014 21:14:51 +0000

    I tell you what I need. I am developing web based applications. Not web sites as some of your live demos show. The UI is a crucial part of such applications because that is what actually creates positive user experience. That means the way application looks is as important. So for me, using third party UI components is a must. I would really appreciate an example of using such component. for example, jQWidgets or dhtmlx. Or at least some guidelines of how to do it.

    Thanks

    • Vlad Kopachinsky 21.06.2014 Sat, 21 Jun 2014 09:18:12 +0000

      Ok let’s look scenarios.
      case 1:Apply jquery plugin for any controls ( input,checkbox,select and etc ) after load element on DOM.
      solution:

      @(Html.When(JqueryBind.IncInsert | JqueryBind.InitIncoding)
      .Direct()
      .OnSuccess(dsl =>
      {
      dsl.WithClass("dropdown-toggle").Core().Jquery.Plugin("dropdown");
      dsl.WithClass("carousel").Core().Jquery.Plugin("carousel");
      // some code
      })
      .AsHtmlAttributes()
      .ToDiv())

      case 2: invoke IML from 3d-party library
      JavaScript code on external files

      function InitScheduler(instanceId,editBtnId)
      {
      scheduler.init(instanceId, null, "week");
      scheduler.attachEvent("onEventChanged", function(event_id, event_object) {
      GetUserData(event_id);
      $('#'+ editBtnId).trigger('incoding');
      return true;
      });
      }

      IML code from View ( razor cshtml )
      @{
      var instanceId = Guid.NewGuid().ToString();
      var editBtnId = Guid.NewGuid().ToString();
      }
      @(Html.When(JqueryBind.InitIncoding)
      .Direct()
      .OnSuccess(dsl => dsl.Self().Core().Call("InitScheduler",instanceId,editBtnId))
      .AsHtmlAttributes(new {id = instanceId})
      .ToDiv())
      @(Html.When(JqueryBind.None)
      .AjaxGet(Url.Dispatcher().AsView("Dialog/Edit"))
      .OnSuccess(dsl =>
      {
      dsl.Self().Core().Insert.Html();
      dsl.Self().JqueryUI().Dialog.Open(options =>
      {
      options.Title = "Edit";
      });
      })
      .AsHtmlAttributes(new {id = editBtnId})
      .ToDiv())

      Summary : IML have ready many Jquery UI extensions as plugin to framework ( package to contrib ) and ability call/apply any jquery plugin. For integrated with 3d-party well way use trigger on IML element how demonstration on case 2.

      You are can self development ( guide ru ) plugin for dhtmlx like are JqueryUI().Dialog or JqueryPlugin().BlockUI.Block and etc.
      We are have article about extensions ( ru ) also.

      P.S. Let me take few days for publish source code with worked sample on github.

Leave a Reply