Пользователь
0,0
рейтинг
27 декабря 2014 в 16:07

Разработка → Почему вам НЕ стоит использовать AngularJs

Много времени прошло с момента появления AngularJs (в масштабах веб-технологий конечно). Сейчас в интернетах есть огромное количество постов восхваляющих этот фреймворк до небес, что это манна небесная не иначе, а критики не так уж и много как он того заслуживает. Но такие статьи уже потихоньку начинают появляться, и меня это радует, надеюсь индустрия переболеет ангуляром так же, как переболела MooTools, Prototype, %какой-нибудь новый язык под JVM%, %другая-супер-революционная-технология%. Не знаю почему, но в IT-области такие революционные технологии, которые поднимают шум, а потом пропадают, появляются довольно часто. Хороший разработчик должен уметь отличать очередную модную технологию, от работающего инструмента. И для этого очень важно критически смотреть на вещи. Моя статья — это компиляция самых весомых выводов из других статей, и моих личных умозаключений. Ангуляр создает хороший вау-эффект, когда видишь его впервые: «ух ты, я написал ng-repeat, и реализовал эту логику одними тегами и все само обновляется!», но как только приходится реализовывать реальные приложения, а не очередной TODO-лист, то все становиться очень печально. Сразу хочу сказать, что фреймворк я знаю хорошо, даже больше чем мне хотелось бы его знать, я программировал на нем в течении 2 лет. И для следующего проекта я его точно не выберу, и это хорошо, все мы учимся на ошибках. Так что же не так с ангуляром? Тут нет однозначного ответа, слишком много разных недостатков, которые создают такой облик фреймворку. Если одним словом – непродуманная архитектура. Под катом я привожу конкретику, так что устраивайтесь поудобнее. ДА НАЧНЕТСЯ ХОЛЛИ ВАР!

Двусторонний дата-биндинг


Существует фундаментальное правило программирования, оно относиться к совершенно любому языку или технологии, это правило гласит — явное лучше неявного. Все эти watcher'ы это неявный вызов обработчиков событий. В реальности события происходят при клике по элементу, а не при изменении данных, поэтому когда вы пишите на ангулярке вам необходимо думать следующим образом: «ага, тут кликнули по кнопке и изменилась модель, теперь нужно слушать изменения на этой модели и когда она меняется вызывается хэндлер», а не «кликнули на кнопку, вызвался хэндлер», ДВУСТОРОННИЙ БИНДИНГ — ЭТО НЕ ТО КАК ПРОИСХОДИТ ОБРАБОТКА СОБЫТИЙ В ПРИНЦИПЕ. Это тоже самое, что вы достаете данные из базы данных и записываете их в модель, и только на изменениях модели вызываются колбэки, да так вообще нигде не реализовано, даже на Java, язык который вообще не имеет анонимных функций (когда я на нем еще писал), реализовывал колбэки на классах. Потому что это явно, потому что такая концепция описывает реальное положение вещей. Даже будущая версия Ember.js не будет использовать двусторонний дата-биндинг.

Еще двусторонний биндинг означает, что изменив что-либо в своем приложении, это тригерит сотни функций, которые наблюдают за изменениями. И это чудовищно медленная операция, особенно все становится плохо на мобильных платформах. И это фундаментальная часть фреймворка. Ангуляр даже накладывает ограничения на то насколько богатый UI можно писать. И что самое интересное, это не какое-то эфемерное и далекое ограничение в которое вы никогда не упретесь. Это всего лишь 2000 биндингов, и если вы разрабатываете более-менее большое приложение, ТО ВЫ ТОЧНО УПРЕТЕСЬ В ЭТО ОГРАНИЧЕНИЕ. И тут вам придется драться с фреймворком. Ангуляр вводит возможность одностороннего дата-биндинга, что бы избежать проблем с производительностью. Создаем себе проблему и решаем ее костылем (непродуманная-архитектура#1). Сами глянте, какое количество людей, которые борются с производительностью ангуляра. Да если вы в гугле вобьете angular performance, то вы ужаснетесь количеству статей, описывающих как его ускорить, не является ли это достаточным аргументом, в пользу того, что ангуляр медленный?

Тут есть еще один момент, иногда все-таки двух сторонний дата-биндинг нужен, но UI все равно тормозит. Например при первой загрузке пользователь видит {{ выражения в скобочках }}. Хм… так это ж не баг, это фича! Нужно ввести директиву, которая будет прятать UI, что бы пользователь не видел мерцания, и не мешал фреймворку решать его несуществующие проблемы. И для этого вводится директивы ngCloak, ng-bind, ng-bind-template, которые собственно этим и занимается. Этих проблем бы не было, если бы использовался более шустрый фреймворк, который сразу показывает данные, как только они появились, ангуляр же после появления данных, требует времени что бы их отобразить. Опять создаем себе проблемы и решаем костылями (непродуманная-архитектура#2).

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

Dependency Injection


Следующий пример того, как ангуляр сначала ставит грабли, а потом заставляет вас плясать с бубном, что бы их обойти — это Dependency Injection. В ангуляре переменные внедряются по имени аргумента:

function MyController($scope, $window) {
    // ...
}

Здесь ангуляр вызывает у функции .toString(), берет названия аргументов и потом ищет их в списке со всеми существующими зависимостями. Поиск переменной по имени — это еще терпимо, учитывая типизацию JavaScript, а проблема тут в том что, ЭТО ПЕРЕСТАЕТ РАБОТАТЬ ПРИ МИНИФИКАЦИИ КОДА. Когда вы минифицируете свой код, то он перестает работать, потому что переменные инжектятся по имени. Вам либо нужно использовать такой синтаксис:

someModule.controller('MyController', ['$scope', 'dep1', 'dep2', function($scope, dep1, dep2) {
}]);

Или такой:

MyController.$inject = ['$scope', '$window'];

Но непонятно, зачем нужно было вводить несколько способов сделать одно и тоже, но еще больше непонятно, зачем нужно было вводить заведомо неработающий способ (непродуманная-архитектура#3).

Следующая важная часть — это то, как зависимости объявляются. Прежде чем внедрять зависимость ее нужно как-то объявить. Как это можно было сделать, если вы психически здоровый человек:

 injector.register(name, factoryFn); 

Где name — это название зависимости, и factoryFn — функция, которая будет инициализировать зависимость. Вот и все. Буквально в одном предложении уместили очень лаконичную идею. Теперь смотрим на то что предлагает ангуляр docs.angularjs.org/guide/providers. Там вводятся 5 новых сущностей: provider, service, factory, value, constant (непродуманная-архитектура#4). И каждая из них чем-то отличается друг от друга, но по сути это все одно и то же. Но самое главное, что все они могут быть легко заменены одним методом, который я привел выше. Но это слишком просто и не интересно, уж лучше давайте заставим людей мучится.

Дебаггинг


Дебаггинг сам по себе сложный, но этого мало, нужно это усложнить! Ангуляр питается вашей болью и страданьями!

ОШИБКИ В БИНДИНГАХ ВООБЩЕ НЕ ВЫЛЕТАЮТ, например в вот этом коде:

<div ng-repeat="phone in user.phones">
    {{ phone }}
</div>

если user не определен, то никакой ошибки не будет (непродуманная-архитектура#5). Ангуляр молчит как партизан. Более того вы не можете поставить брейкпойнт внутри {{ такого идиотского выражения }}, потому что это не JavaScript. Теперь идем дальше, ошибки, которые произошли в JavaScript'е ловятся внутренним ангуляровским перехватчиком, и ВОСПРИНИМАЮТСЯ БРАУЗЕРОМ КАК ПОЙМАННЫЕ ОШИБКИ (все что произошло в ангуляре, остается в ангуляре). Из-за этого приходитья ставить в хроме флаг «Pause on caught exeptions» (что бы дебаггер останавливался на всех ошибках, а не только на непойманных (обычно интересуют именно непойманные ошибки, которые выкидываются в консоль)), поэтому приходится в дебаггере проходить по всем внутренним пойманным исключениям ангулярки пока она инициализируется (непродуманная-архитектура#6) и только потом вы попадаете именно в ваше исключение. И тут-то вы увидите вот такой стактрейс:



Ошибка вылетает из digest цикла и это означает, ЧТО ОНА МОГЛА БЫТЬ ВЫЗВАНА ИЗМЕНЕНИЕМ ЛЮБОЙ ПЕРЕМЕННОЙ ВО ВСЕМ ПРИЛОЖЕНИИ. Вы хрен когда проследите в дебаггере откуда растут ноги у ошибок. (непродуманная-архитектура#7)

Наследование скопов


Это без сомнения самая распространенная ошибка с которой сталкивался абсолютно каждый разработчик на angular. Например, если вы напишите вот такой код:

<div ng-init="phone = 02"> {{ phone }} </div>
<div ng-if="true">
    <button ng-click="phone = 911">change phone</button>
</div>

То при нажатии на кнопку переменная phone меняется не будет, в то время как в этом коде:

<div ng-init="phone = {value: 02}"> {{ phone.value }} </div>
<div ng-if="true">
    <button ng-click="phone.value = 911">change phone</button>
</div>

Все работает корректно, и номер телефона меняется при нажатии на кнопку. Либо например вот этот код, который даже опытных разработчиков поставит может поставить в тупик jsfiddle.net/1op3L9yo. Даже введен новый синтаксис для объявления переменных в контроллере через this, который решает эту проблему. (непродуманная-архитектура#8).

Очевидно, что это поведение абсолютно бесполезное и очень вредное:
  • Если вы опираетесь в своей логике на наследование скопов, то такую логику становиться крайне сложно тестировать (нужно инициализировать еще состояние родительского контроллера).
  • Логика становиться более запутанной и неявной (вы используете переменную, которая в текущем модуле не объявлена)
  • Унаследованные переменные чем-то похожи на глобальные переменные (из дочернего скопа вы имеете доступ к абсолютно любой переменной из любого родительского скопа). А все знают, что глобальные переменные — это зло.
  • Увеличивает входной порог и количество теории, которую нужно знать: вам нужно знать прототипное наследование, вам нужно знать как работает tranclude и как можно поменять скоп в котором он работает, вам нужно знать что ng-repeat, ng-if, ng-switch работают со скопами по другому, вам нужно знать, что в директиве есть 3 разных параметра что бы указать какой скоп она создает внутри себя, да перечислять можно еще долго.

Да по количеству вопросов на stackoverflow.com и статей в интернете можно уже понять, насколько это запутанная тема, вот такие вот дела, а кстати, что вы делаете сегодня вечером, я вот хочу какой-нибудь фильм глянуть, может посоветуете что-нибудь ? Даже в продвинутых стайл-гайдах советуют избегать использования $scope. И за 2 года работы на ангулярке я не встретил ни одного места, где обращение к переменным объявленным в родительском скопе было бы хорошей идеей (за исключением конечно стандартных директив типа ng-repeat, на реализацию которых мне, как пользователю библиотеки, вообще пофиг). Самое интересно, что такое поведение можно было бы избежать УБРАВ ВОЗМОЖНОСТЬ НАСЛЕДОВАНИЯ СКОПОВ (Например в ExtJs создается обертка над классами для имитации OOП, уверен, что и в каких-нибудь других фреймворках есть похожее). Обычно фреймворки должны прятать недостатки платформы и предоставлять в своем API логичное и максимально прозрачное поведение, но ангуляр наоборот бросает этот недостаток JavaScript вам в лицо и заставляет с ним драться. Из-за этого косяка был потрачен не один человеко-месяц.

Директивы


Мы подошли к самому интересному, директивы — это святая святых ангуляра. Им воспевают песни и хвалят все, кому не лень. Но я буду прагматичным, вот полный синтаксис объявления директивы:

var myModule = angular.module(...);

myModule.directive('directiveName', function factory(injectables) {
    var directiveDefinitionObject = {
        priority: 0,
        template: '<div></div>', // or // function(tElement, tAttrs) { ... },
        // or
        // templateUrl: 'directive.html', // or // function(tElement, tAttrs) { ... },
        transclude: false,
        restrict: 'A',
        templateNamespace: 'html',
        scope: false,
        controller: function($scope, $element, $attrs, $transclude, otherInjectables) { ... },
        controllerAs: 'stringAlias',
        require: 'siblingDirectiveName', // or // ['^parentDirectiveName', '?optionalDirectiveName', '?^optionalParent'],
        compile: function compile(tElement, tAttrs, transclude) {
            return {
                pre: function preLink(scope, iElement, iAttrs, controller) { ... },
                post: function postLink(scope, iElement, iAttrs, controller) { ... }
            }
            // or
            // return function postLink( ... ) { ... }
        },
        // or
        // link: {
        //  pre: function preLink(scope, iElement, iAttrs, controller) { ... },
        //  post: function postLink(scope, iElement, iAttrs, controller) { ... }
        // }
        // or
        // link: function postLink( ... ) { ... }
    };
    return directiveDefinitionObject;
});

Что бы понять этот синтаксис и зачем это нужно, надо действительно заморочиться. Вместо того, чтобы описывать ЧТО нужно сделать, вы больше заморачиваетесь на том КАК это сделать. И что самое обидное — ЭТА СЛОЖНОСТЬ НЕ НЕСЕТ НИКАКОЙ ПОЛЬЗЫ. Нету логических причин разделять логику на 3 метода (compile, link, controller), все это можно легко реализовать в одном методе. Опять таки смотрим какое количество проблем это породило. И учтите еще что в какие-то функции scope передается, в какие-то нет, какие-то функции выполняются один раз, какие-то каждый раз при $digest цикле, у каждой директивы так же имеется приоритет выполнения. Да даже, чтобы интегрировать какой-то код в мир ангуляра, например какой-нибудь jQuery плагинчик, вам нужно обернуть его обязательно в директиву. Потому что это было бы слишком просто, если бы разработчики могли сразу использовать готовые решения! И еще непонятно почему controller в директиве и реальный контроллер имеют одно название, они используются в совершенно разных местах и для разных целей, у них должно быть разное имя! (непродуманная-архитектура#9).


Проблемы с людьми


Во первых из-за того, что фрейворк чрезмерно сложный, мало разработчиков его понимают на действительно хорошем уровне и найти таких людей сложно. Во вторых серверные разработчики вообще не будут понимать, что творится на front-end'е и не смогут читать код. А это очень большой недостаток, создается черный ящик, в котором может разобраться только один человек в команде, и если этот человек уйдет, то никто не сможет его заменить. Это было бы нормально, если бы разработка на front-end'е действительно бы требовала таких сложных инструментов (например разработка GUI на ExtJs намного сложнее, чем на Angular, но там эта сложность оправданна), но нет, она сложная потому что сложности создаются целенаправленно. Если вы используете ReactJs или jQuery, то любой серверный разработчик, да даже любой программист, сможет разобраться в коде.

Невозможность серверной шаблонизации


Если вы попытаетесь использовать серверную шаблонизацию, например что бы ускорить прорисовку страницы, либо что бы поисковики индексировали (либо и то и другое), то вас постигнет разочарование. Т.к. серверная шаблонизация добавляет логики в HTML и AngularJs тоже пишет логику в HTML, то не происходит четкого разделения ответственности и как результат очень запутанный спагетти-код. Ангуляр просто не предполагает того, что разработчики захотят ускорить загрузку страницы, либо захотят индексацию поисковиками, он не создан для этого. (непродуманная-архитектура#11). Да, вы можете обойти эту проблему, используя prerender.io (это сервис, который парсит ваш SAP и выдает вам HTML файлы, которые вы должны скармливать поисковикам). Но опять таки — это костыль, а не коренное решение проблемы.

AngularJs 2.0


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

Важные вещи россыпью


  • Ужасная документация. Приходится дополнительно гуглить много информации.
  • До сих пор отсутствуют директивы для Drag and Drop событий (на момент написания этой статьи). Само по себе это не очень большая проблема, но это сигнализирует о продуманности продукта и внимании к деталям. Эти события уже поддерживаются подавляющим большинством десктопных браузеров и являются таким же базовыми, как и onclick или mousemove.
  • Когда вы пишите на ангуляре вы помещаете логику в ваш HTML. ng-repeat, ng-show, ng-class, ng-model, ng-init, ng-click, ng-switch, ng-if — что это как не помещение логики в представление. Само наличие такой логики — это не настолько страшно, как то что — это невозможно тестировать юнит-тестами (а это самые очень важные части приложения), невозможно продебажить и оттуда не кидаются ошибки (непродуманная-архитектура#12).
  • Гугл не использует AngularJs для своих основных продуктов (gmail, google+). И это вызывает подозрения, если это такой хороший фрейворк и они сами его создали, что тогда сами и не используют? Хотя например изобретенный в фейсбуке ReactJs они используют в facebook.com и в инстаграмме. Я знаю, что гугловцы используют этот ангуляр для других более мелких проектов, но все таки они не используют его в самых главных.


Заключение


Большинство проблем, которые я описал, можно обойти при желании (и мне приходилось их обходить, не бросать же проект, который сам написал). Но это тупиковый путь, это тоже самое, что ездить на ладе калине, вместо качественно сделанной иномарки. — Холодно в салоне? — Одевайтесь теплее! — Легко отваливаются детали? — А нечего их трогать, зачем они вам! — Шумит на большой скорости в салоне? — А вы включите магнитолу погромче, и ничего не слышно! И вообще если она сломалась — то просто приезжаете в салон и вам ее чинят. Вот ангуляр — это та же лада калина. Ездить можно, но вы гарантировано задолбаетесь. Факт того, что проблемы можно обойти НЕ ОЗНАЧАЕТ, ЧТО ПРОБЛЕМ НЕТ. Единственное хорошее, что ангуляр имеет — это то что он форсит разработчиков, разбивать код на модули, и код получается гранулированным, больше плюсов от использования ангуляра я не вижу. Вместо ангуляра лучше использовать React (предпочтительно) либо jQuery (для тех кто боится использовать реакт по какой-то причине), либо что-то еще, но уже на свой страх и риск потому что негативных отзывов о backbone, knockout и тому подобных тоже много. И я прошелся только по самым важным и заметным косякам, обычно когда программист говнокодит, он говнокодит везде, так что если вы собираетесь использовать этот фреймворк, приготовьтесь встретится не только с описанными проблемами, но и с кучей других, более мелких, но все равно проблем. Я не знаю почему ангуляр популярный, но это точно не потому что это хороший фреймворк. Поэтому я категорически не советую использовать текущую версию ангуляра. Надеюсь мой опыт поможет кому-нибудь принять правильное решение при выборе стека технологий для следующего проекта.

Источники


Why you should not use AngularJS
What I would recommend instead of Angular.js?
React vs AngularJS – How the two Compare
From AngularJS to React: The Isomorphic Way
The reason Angular JS will fail
Pros and Cons of Facebook's React vs. Web Components (Polymer)
AngularJS: The Bad Parts
What’s wrong with Angular.js
Things I Wish I Were Told About Angular.js

P.S. Я хочу думать о бизнесс-логике и о том какие задачи мне нужно решить по факту, но я не хочу думать о бессмысленных суррогатных коцептах: наследовании скопов, когда нужно использовать односторонний или двусторонний дата-биндинг, когда нужно использовать compile, link, controller, когда мне нужно использовать value или constant, provider или factory, я не хочу думать о том, что делать когда я хочу интегировать натинвые события события в мир ангуляр, я не хочу думать должна ли директива видеть родительский скоп или нет, я не хочу думать о наследовании скопов в стандартных директивах и всех обходных путях, я не хочу думать о том, использовать мне глубокий $watch, обычный или $watchCollection, я не хочу думать о том, зачем нужны Provider для каждой внедряемой сущности и не хочу знать ничего о run и config фазах, я не хочу думать о том увидел ли пользователь {{ скобочки }}, я не хочу решать проблемы производительности, там где их нет, я знать не хочу о том, что такое трасклюд и как он работает со скопами. ГОСПОДИ, АНГУЛЯР ОТПУСТИ, ВЕДЬ Я НЕ В ЧЕМ НЕ ВИНОВАТ, ДАЙ МНЕ ПОЖАЛУЙСТА ПО ПРОГРАММИРОВАТЬ, МНЕ ЭТО НРАВИТСЯ.
@mnemosha
карма
38,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (387)

  • +2
    AngularJS с его замысловатым способо организовывать директивы (за него уже извинились) — это меньшее из зол на сегодня.

    В сложных приложениях, как раз при помощи DI главным образом, датабиндингами (не нравятся двусторонние — используетй one-time) количество проблем сокращается драматически по сравнению с классикой в виде jQuery. ReactJS упрощает биндинг не касаясь другого.

    Все якобы недостаки говорят только о том, что «вы просто не умеете его готовить» =)

    > ЭТО ПЕРЕСТАЕТ РАБОТАТЬ ПРИ МИНИФИКАЦИИ КОДА.
    npm install ng-annotate

    >УБРАВ ВОЗМОЖНОСТЬ НАСЛЕДОВАНИЯ СКОПОВ
    Не доконца ясно зачем, но хочется не наследовать — создайте изолированный scope.

    >ОШИБКИ В БИНДИНГАХ ВООБЩЕ НЕ ВЫЛЕТАЮТ
    Это позволяет в большинстве случаев игнорировать undefined и null — меньше кода — лучше читаемость.
    Если очень хочется и у вас почему-то сложные выражание — отлаживайте

    >Проблемы с людьми
    Нужен только человек с хорошим Javascript — остальное налаживается за пару недель интенсива.

    И далее по списку.
    • +41
      ng-annotate — это не решение проблемы, это чистой воды костыль. Вместо того, что бы сделать так, что бы все работало без плагинов (и это легко выполнимо), придумывается плагин, который исправляет косяки.

      Наследование скопов — катастрофически вредно для юнит-тестирования, и порождает большие сложности из-за прототипного наследования. Плюсов от наследования скопов никаких не вижу.

      Зачем я должен использовать другой дебаггер, когда стандартный в разы более функциональный и удобный. Тот дебаггер не покрывает даже 20% функционала стандартного, да и создавались они с разной целью и это не замена.
      • –2
        Вместо того, что бы сделать так, что бы все работало без плагинов.

        function.$inject = ['$scope']? На практике ng-annotate справляется с этим наура самостоятельно. Меньше кода — лучше читаемость.

        Плюсов от прототипного наследования никаких не вижу.

        Зачем теоретизировать. Вы постройте нормальное приложение то со вложенными контроллерами, директивами и далее. И увидите.
        • +15
          Вопрос, возможно, глупый. Но что, если я не хочу использовать ноду? Вот хочу я сократить количество задействованных решений. Что тогда?
          • +15
            Немного дополню предыдущий вопрос. Когда мы говорим об использовании ноды для сборки и минимизирования яваскрипта в приложении (для production-версии), при условии, что работоспособность самого приложения на develop-, testing-, staging-, production- и остальных окружениях ни коем образом от ноды не зависит, это я еще могу понять. Когда речь об автотестах, например… ясно. Но если мы не используем ноду (пишем на python, например, или на, прости господи, php). Я не понимаю желания приплетать дополнительные решения в такую карусель.

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

            PS
            Господа, когда так остро реагируете — поясняйте, пожалуйста, свою реакцию, а то не интересно.
            • 0
              Хм, а что именно в ангуляре требует сервера на ноде? Всё работает и без неё. Примеров полно даже в официальной страничке примеров, если по ним погулять, можно найти много на руби или просто статике, есть даже на c#.
              • +9
                Человек имеет ввиду: как сборка фронтенда относится непосредственно к реализации бэкенда. Ответ — никак. Просто в ноде больше всего инструментов для этого было разработано.
            • 0
              Большая часть всяких шаблонизаторов, препроцессоров и систем сборки фронтенда была реализована на node.js и ruby. Так просто исторически сложилось. Я тоже хотел бы прикрутить сборку к своему Play2 или golang'у (python не годится для масштабируемых реактивных приложений с push-нотификациями, и без костылей типа celery или микросервисных архитектур, а «прости-Господи» РНР вообще ужасен), к сожалению сущесвтующие решения на ноде очень сильно обгоняют всё остальное по функционалу. Вот мой немного кривой gulp-seed для примера. В случае с ангуляром так ещё есть перепаковка всех шаблонов в один большой js файлик который сразу ложится в кэш браузера при загрузке приложения, и другие довольно полезные вещи. А ещё я люблю писать шаблоны под Angular на jade, а вёрстку в Stylus, и получается целая вязка бубликов. В принципе фронтэнд, есть фронтенд — он просто кушает RESTful API и на сервере ничего не рендерится, и абсолютно всеравно на чём этот сервер будет написан — сборка фронта нам просто отдаст кучу больших файликов с ещё большей кучи мелких, и спрайты упакует, и векторные иконочные шрифты соберёт, и вектор под каждую плотность экрана растерезирует. Для того что бы не было проблем с SEO — просто прикручивают prerender.io, но я не поощряю такого подхода. Гораздо проще гонять тот же react прямо в node.js без каких либо заморочек с webkit'ом. Также gulp асинхронен без лишних побочных эффектов если его правильно готовить, и в нём есть возможность LiveReload'a.
            • НЛО прилетело и опубликовало эту надпись здесь
              • +3
                Ну вот далеко не всегда
              • +1
                То есть, YUI тоже не вариант? Хоть какое-то сжатие. Плюс gzip.
                • +2
                  Gulp с Livereload'ом и асинхронным building pipeline'ом намного веселее. И в него тоже можно интегрировать YUI.
      • +2
        А как вы предлагаете сделать так, чтобы все работало без «плагинов»?
        Если не хочется наследования — существует «controller as» синтаксис. А плюсом является доступ из контроллера к scope парентовых контроллеров без директив и всяческих $parent
  • –7
    Извините, но ваша статья похожа на «заметки белок истеричек». Невозможно читать.

    что это как не помещение логики в представление

    Вы говорите как должны выглядеть данные, которые передали в слой view. Это логика отображения, а не бизнес логика, все на своих местах.
    • +2
      Кстати, если она становится сложной, то её всегда можно поместить в функции.
    • +8
      Кстати да, так часто люди принимают за любой код в представлении — бизнес-логику, что страшно.

      Позволю дополнить примером:

      <div onclick="DB.query('update table1 set field1 = 1 where field2=2')"></div>


      Вот это смешение бизнес-логики и представления.

      <div onclick="this.style.top='1px;'"></div>


      Это смешение императивного и декларативного кода, но все это касается только представления.
      • +10
        Приведу пример типичного шаблона для twig/jinja2 и такой же для angular.

        {% for item in list %}
        <div class="item {% if item.draft %} item--draft {%endif %}">
            {{ item }}
        </div>
        {% endfor %}
        


        и

        <div class="item"
                ng-repeat="item in letter.list"
                ng-class="{'item--draft': item.draft}"
        >
            {{ item }}
        </div>
        


        Мне порой кажется просто что люди не понимают что это не HTML а XML-based синтаксис шаблонов и только. Там нет никакой ереси типа onclick и т.д. Так же согласен что люди частенько любую логику воспринимают именно как бизнес-логику.

        Вообще порекомендую автору статьи подышать свежим воздухом и вглянуть на Angular2 где уже даже сейчас видно что была проделана неплохая работа над ошибками. Да даже если брать Angular1.3 и Angular 1.1 разница чувствуется.
        • +18
          Они очень много переделали в Angular2 как я посмотрю. Это означает, что даже разработчики фреймворка в какой-то степени понимают что были большие ошибки.
      • НЛО прилетело и опубликовало эту надпись здесь
        • +1
          Нужно понимать, что React хранит и предполагает получение View-Model состояния с сторонних источников, с последующим вызовом обработчиков для перестройки VirtualDom дерева, и по другому это просто нереализуемо. Другие шаблонизаторы будут тупо оперерировать пустым HTML — создавать бешеный overhead на перерисовки и его разбор, и Angular тоже не исключение. Поэтому появляются такие странные вещи как ngReact :x Вьюхи не генерятся кусками — они формируют дерево компонент со своими состояниями, это может быть и непривычно и я сам не поощряю такой дизайн, но сделано чисто для реюзабельности и простоты работы с DOM деревом.
          • НЛО прилетело и опубликовало эту надпись здесь
            • +1
              Адепты гуглополимеров с вами не согласны.
              Не дизайнер, а верстальщик… дизайнерам вообще не положено лезть в вёрстку.
              Верстальщику не составит особо проблем разобраться с компонентами, да и кто сказал что он увидит слишком большую разницу между HTML и JS с React компонентами. Эт только заядлые ригидные фанатики будут материться, а для всех остальных — обучится чему-то новому счастье.
            • 0
              Причем тут дизайнер и HTML? Пусть фронтендом занимается фронтенд-разработчик, который умеет все, что нужно.

              Вообще react все правильно делает, используя pure js. Они не создают лишних сущностей в виде yet another template language, в отличие от всех остальных. Свой язык шаблонов — это дичайший оверхед на всех уровнях, и, что самое смешное, в итоге он скомпилируется в тот самый JS.
              И к тому же, вот вы задумайтесь, долго вы учили директивы angular-а, отдельный кривой и убогий язык? А тут уже всем знакомый JS, отвратительный, но знакомый, более того, прекрасно отлаживаемый на лету.
            • +7
              Как ни странно — все как раз наоборот. Это по собственному опыту где-то на 150 KOC с помощью React+Backbone.

              React отвечает только за представление. Используется JSX (с препроцессором, понятно), который похож на HTML, но не совсем. Так как все бьется по компонентам, в большинстве случаев получается древовидная иерархия (а не граф), что хорошо влияет на структуру проекта. Ну а поскольку все в изолированных компонентах — их легко тестировать. Очень легко.

              Добавляем backbone (модели+роутинг), require для зависимостей, etc и получаем отличный фреймворк под свои задачи.

              У нас есть верстальщик, который максимум что может это подключить плагинчик jQuery. Т.е. не программист вообще. Но вот HTML пишет хорошо. И его получилось очень быстро обучить следующему алгоритму:

              1. Делает обычную HTML верстку для страницы включая CSS
              2. Он связывается с фронтендщиком, они обговаривают логическую иерархию компонент (как бить кусок HTML на части)
              3. Разбивает свою же верстку на компоненты в соответствии с иерархией и отдает фронтендщику без логики
              4. Фронтендщик добавлет логику

              Так вот, я хочу сказать что конвеер отлично работает. Код остается читабельный — находить ошибки очень легко, учитывая доступный плагин для Chrome Dev Tools. Из за иерархии компонент можно легко найти что за что отвечает. Без каши из scope, без отдельного DSL для шаблонов (JSX не считается — он только теги оборачивает, все остальное в JS). И самое главное — приложение все же пишет программист, который понимает что такое производительность, качество кода и тестируемость.

              Думаю следующий вопрос — а как это все поддерживать? Да очень просто. Если изменения небольшие (CSS класс добавить, например) — это может сделать и верстальщик. Если что-то больше, то смотри пункты выше.

              И что я хочу добавить, после 50 KLOC проекта на AngularJS — React это просто чудо.
              • +2
                Расскажите про опыт: как оно React + backbone. Как правильно разделять их, что бы потом не плакать?

                Какие есть практики для динамического апдейта данных с сервера?

                Вот мне приезжают данные из вебсокета: мне правильнее на уровне бекбона вмерживать апдейты в имеющуюся структуру или просто пересоздавать всё и отдавать потом результат на рендеринг в реакт?

                Если вопросы некорректные, то буду рад, если поправите.
                • 0
                  Посмотрите эту презентацию staltz.com/dont-react/#/
                  • +3
                    Там автор начал за здравие (о различиях интерактивного и реактивного программирования), а кончил как обычно (написал интерактивный велосипед, обозвав его внезапно реактивным)
                • +4
                  Backbone и React живут параллельно. От Backbone мы используем Collection, Model и Router.

                  Архитектура приложения типовая three-tier: сверху у нас UI, по середине слой Business Logic, снизу Data Access). Компоненты React просят что-то у BL, тот считает или просит у DA.

                  Да, у нас тоже есть realtime update — сервер может что-то пушнуть. Сделано через обычный shared state (который спрятан в BL). Компонента React подписывается и когда что-то приходит — ее уведомляют. Построено поверх событий Backbone. В нашем конкретном случае модели для обновлений не используются — сообщения обрабатываются в BL и передаются отдельными объектами.

                  А вот если нужно хранить историю (например список текущих уведомлений, который глобален для клиента) — то коллекция как синглтон и подписка на ее события. Как только добавляется новое событие (будь то результат AJAX запроса или пришло из вебсокета или кто-то из UI убрал) — подписчики об этом узнают. И да, детали спрятаны в BL и для этого всего есть нормальный API.

                  Для всяких AJAX запросов — обычные коллекции и модели Backbone. Для React написан небольшой mixin, который умеет слушать .change() события для моделей (и автоматически отписываться если уходит из Virtual DOM) за счет чего получается реактивность.

                  Ну и насчет вопроса про пересоздавать. Если кратко — React вообще все равно что за данные и откуда они приходят. Если более развернуто: React ожидает что метод render() вернет дерево компонент. Каждый раз — целое дерево компонент. В идеале, render() это чистая функция от аргументов компоненты и внутреннего состояния компоненты.

                  В связи с этим, если надо отрисовать массив из 10 элементов, внутри которого меняется только 1 элемент, render() каждый раз будет возвращать все 10. И React уже сравнивает что именно поменялось, по сравнению с предидущей версией DOM и обновляет только то что нужно. А, поскольку, виртуальный DOM это просто структуры данных JS, то работает это все достаточно быстро. Это совершенно не отличается от подхода в том-же AngularJS, разве что более явно (с соответствующими плюсами, так как можно оптимизировать).
                  • +2
                    Слушайте, а если есть о чем написать, может, сможете поделиться опытом в виде поста на Хабр? Очень интересны нюансы реализации.
      • 0
        Дополнил немного статью: это невозможно тестировать юнит-тестами, невозможно продебажить, оттуда не кидаются ошибки и при добавлении большего количества логики в onclick он значительно усложнится для чтения.

        По поводу ошибки в термине — суть не в том, какой термин используется, а в том, что под ним подразумевается.
        • НЛО прилетело и опубликовало эту надпись здесь
          • НЛО прилетело и опубликовало эту надпись здесь
            • +17
              Ты просто слишком не конструктивно настроен. Я пишу эмоционально, но подкрепляю фактами, ты выдираешь что-либо из контекста, и агрессивно просишь меня, что-то тебе доказать. Если бы ты был более конструктивен и привел весомые доводы, я бы тебе ответил.
              • НЛО прилетело и опубликовало эту надпись здесь
                • +41
                  Вместо того чтобы друг-друга обкидывать «нубасами», грамарнаци и неконструтивом — давайте аргументы, почему тестируется/не тестируется — вас тут слушают внимательно, вы не в привате общаетесь :)
                  • НЛО прилетело и опубликовало эту надпись здесь
                • +1
                  А пока что в каждом Вашем жирном капсе читается фанатичная истерика

                  Ага
              • +1
                Фактов по поводу unit-тестов Вы не привели. Необходимость дебага выражений в шаблонах больше говорит о программисте, чем об AngularJS.
            • +6
              Судя по статье, он совсем не полный ноль.

              У нас ангуляр используется в нескольких проектах последние полтора года и в целом мы им недовольны. Сейчас новый проект переводится на Backbone и разница просто чумовая. На простейшем коде ангуляровский проект подтупливает и подлагивает.

              Под подлагивает я имею ввиду ситуацю, когда на полупустом экране, в хроме страница меняется не во время нажатия мышкой, а ощутимо после отпускания мышки.

              С backbone страничка меняется до того, как отпускаешь мышку.

              Нет, спасибо, что-то дальше ангуляр с его скрытыми глобальными переменными в виде наследованных скоупов не очень хочется.
              • 0
                • +2
                  Да-да, я подобные аргументы видел до перехода с jQuery на ангуляр.

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


                Ну вы бы что ли ссылку дали или use-case подробнее описали. Если бы такое имело место сколько-нибудь широко, Angular бы вообще никто не использовал.
                • 0
                  Дать ссылку я вам на админку у пользователей я по понятным причинам не могу, могу дать триальный ключ к нашему стриминговому серверу и могу пояснить, как добавить 800 тестовых потоков, что бы вы увидели, как оно перестает работать на таком небольшом количестве строк.
                  • 0
                    Да вобщем-то хватит и описания: правильно я понял, что Вы одновременно отрисовываете 800 progress bar-ов с какой-то информацией для каждого элемента?
                    • 0
                      не, не прогресс бары. 800 строк в таблице, в каждой информация о потоке: время жизни, количество клиентов, битрейт и т.п.

                      Некоторые строчки можно развернуть, что бы увидеть подробнее информацию о конфиге, клиентах и т.п.
                      • +2
                        Ясно. Сложно, правда, представить 800 элементов на полупустой странице.

                        В общем это как раз те случаи «100500 элементов на одной странице». Везет мне как-то на клиентов — они такое плохим UX считают. Но проблема не является непреодолимой. Причём вариантов решения больше одного. Хотя если у Вас большинство страниц такие, то AngularJS вам, похоже, ни к чему. Выбор инструмента под задачу, все же, никто не отменял.
                        • 0
                          такая страница ровно одна. Разбить эти строки как-то по-другому (постранично) не очень то получается.
                          • 0
                            В концепцию реакта отлично ложится:

                            1. Компонент для потока. Рисует информацию об одном потоке.
                            2. Нужен какой-то простой маршрутизатор сообщений. Компоненты потоков подписываются на события из этого роутера и получают «свои» обновления
                            3. Вебсокет клиент кидает входящие данные в роутер
                            4. Компоненты получают новые данные, обновляют свое состояние
                            5. Обновление состояния автоматически запускает render() для компоненты
                            6.…
                            7. Профит
              • 0
                То же самое — пришлось переписать приложение с AngularJS на Backbone+MarionetteJS. В форме с 50-100 полей получились более 7000-10000 watcher'ов, после попыток оптимизации число сократилось до 3000. При этом реакция на нажатия клавиш запаздывала на 0.5-1 секунду. Переписал на BB — всё летает, никаких тормозов. Конечно больше ручной работы, надо следить за утечками памяти.
                • 0
                  Какие антипаттерны приводят к утечкам?
                  • 0
                    Да там не антипаттерны, просто в Backbone нужно закрывать свои view.
                • 0
                  А для биндингов данных в полях форм вы что использовали? Расскажите пожалуйста!
                  Я попробовал Stickit, но он оказался не очень гибким. Перешел на Rivets.
                  • 0
                    Использовал stickit там, где он мог, сложные вещи руками. Rivets вроде смотрел, но не помню почему отказался от него.
    • +58
      Извините, но ваша статья похожа на «заметки белок истеричек».

      Нет, не похожа. Автор выразил свое мнение. С тезисами, с аргументами, с доказательствами.
      Со всем тем, чего нет у вас в комментарии.
      • НЛО прилетело и опубликовало эту надпись здесь
        • +17
          Лучше раскажите почему вы считаете, что он неправ. И как бы вы решили эти проблемы.
          • НЛО прилетело и опубликовало эту надпись здесь
            • +27
              Тратить своё время, чтобы рассказать ему обо всех его ошибках в Angular?

              Ну вы же тратите свое время, сидя на хабре и постя неаргументированные комментарии. Комментарии (в частности) для того и нужны, чтобы указывать автору поста на его ошибки, разве нет?
              • НЛО прилетело и опубликовало эту надпись здесь
                • 0
                  Уже перелопатил и отписал ниже.
            • +1
              я давно ищу человека, который помог бы нам с неработающим куском кода на ангуляре, но вам я бы не хотел платить деньги.
          • +34
            1. Data-binding и его возможные тормоза. Простой ответ — за удобство приходится платить. Нефиг всю логику на него завязывать. Понятно, что watchCollection на тысячи элементов будет тормозить. Поэтому никого не должно удивлять, что особо критические места, возможно, придется оптимизировать ручками и без байндинга (гриды/чарты/etc). Вообще напоминает недавний пост про сборщик мусора в C#, который якобы течет и тормозит — а у автора просто-напросто объекты во второе поколение и LOH попадали очень быстро
            2. DI. В JS невозможно его реализовать с использованием типов аргументов, как в нормальных языках, поэтому приходится использовать алиасы. Есть три возможных варианта использования, один из которых не дружит с минификацией или, например, с неймспейсами. Проблем с двумя другими нет. Автору только считает синтаксис уродливым. Срочно всем перестать использовать ангуляр! По поводу 5 «новых» сущностей и мучающихся людей. Тут просто сказать нечего, у некоторых этих сущностей вообще-то даже разный жизненный цикл
            3. Дебагинг. Не самое приятное дело, да. Но дебагинг в среде, построенной на асинхронных событиях от браузера, вообще штука печальная
            4. Наследование scope'ов. Нужно. Все в сервисы не понапихаешь, хотя бы потому, что они синглтоны. И да, 'Controller As' синтаксис. Хотфикс примера на fiddle — jsfiddle.net/1op3L9yo/253/. Вообще пример хороший, заберу в качестве задачки на собеседования с вопросом «почему так?» :)
            5. Синтаксис директивы довольно сложный, да. Но как правило сокращается до scope, restrict и link. Остальное иногда пригождается. Пункт аналогичен — не пишите на Java, там стопиццот различных ключей в командной строке.
            6. Проблемы с людьми — так на любой технологии эти проблемы, сильные разработчики работу долго не ищут :) Адекватные разработчики основы понимают довольно быстро, а структурированность ангуляра сильно помогает, особенно тем кто имеет опыт в бэкенде. Если лабать визитки на JQuery последние лет 5, то да, есть опасность разрыва шаблона. Но черт возьми, это же не C++!
            7. Серверная шаблонизация — наверное единственный стоящий пункт здесь. Никто не мешает генерить HTML template на сервере тем же .NET'ом или каким-нибудь шаблонизатором, но мне кажется имелось в виду нечто типа isomorphic js раз уже SEO помянут. Мы эту проблему не решаем, у нас немного иной класс приложений :)
            8. Документации достаточно. Если есть проблемы с тем, как и почему использовать — это не в документацию, а на амазон за литературой
            Остальное по 10 раз объяснено в других комментариях.

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

              Отходя от темы на 100%. Почему печальная?
              Если не использовать паттерн «коллбэк в коллбэке, коллбэк погоняет» то даже как-то очень просто.
              Или вы про что-то конкретное?
              • +1
                ну человек жалуется на то что у него стэк-трейс режется до digest-loop'а. Но он всегда будет резаться, потому что колбеки всегда будут, даже при использовании promise'ов, которые их по сути всего лишь прячут. На ответ от сервера, на банальный setTimeout чтобы отдать управление браузеру, и т.д. Пример, где «не печально» — async/await шарповые
                • 0
                  К слову по поводу этого, есть чудная библиотечка под названием zone.js, одной из возможностью которых является построение нормальных стактрейсов.

                  p.s. Эта библиотечка будет использоваться в Angular2 для запуска $digest циклов (если браузер не поддерживает Object.observer то используется старый добрый дирти-чекинг)
                • 0
                  Точку зрения понял. Что до шарпа, то нет нормального опыта и понимания, поэтому ничего не скажу.
    • +2
      Таки автор аргументировал свою точку зрения.
  • +2
    >Двусторонний дата-биндинг

    Есть bindonce https://github.com/Pasvaz/bindonce
    В 1.3 можно прямо так {{::item}}
  • +8
    До сих пор отсутствуют директивы для Drag and Drop событий

    github.com/angular-dragdrop/angular-dragdrop
    github.com/fatlinesofcode/ngDraggable

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

    Когда вы пишите на ангуляре вы помещаете логику в ваш HTML

    Логику представления, заметьте, где ей самое место. Если там что-то сложное то это проблема разработчика а не фреймворка. И коль уж вздумалось вам тестить UI так и пишите UI тесты (e2e тесты если быть точнее). Ну или сложную логику можно опять же инкапсулировать в директиву и покрывать быстрыми юнит тестами уже оные штуки.

    Гугл не использует AngularJs для своих основных продуктов

    Гугл много чего не использует из того, что было сделано его сотрудниками в свободное от работы время. И таки гугл использует на паре мелких в масштабе гугла проектов (youtube 4 psp, DoubleClick Digital Marketing)

    Гугл может передумать и закрыть этот проект.

    Это не проект гугла, угомонитесь. И в конце концов это не продукт. Это инструмент для разработки продуктов. Гугл поддерживает такие штуки что бы ВЫ реализовали клевый продукт, Гугл купил бы его и закрыл по вашей же логике.

  • 0
    Вместо ангуляра лучше использовать React
    В тегах не увидел ничего о Node.js


    Так что хочу задать вопрос еще и автору статьи. Можете ли вы поделиться туториалом такого приложения с бэкендом, не зависящим от Node.js? Такое ощущение, что для разработчиков одностраничных приложений весь остальной мир исчез и состоит только из Node.js (против которой я ничего плохого сказать не могу, кстати!).
  • +20
    Например при первой загрузке пользователь видит {{ выражения в скобочках }}

    У меня создалось впечатление что автор лукавит по поводу своего опыта работы с AngularJs. Если бы вы прошли хотя бы официальный tutorial, вы бы знали как это решается. Или же вы намеренно не упомянули о директиве ng-bind и ng-bind-template, что указывает на ваше предвзятое отношение к фреймворку, и на то что вы искали к чему бы докапаться.

    Конечно существует множество спорных моментов и недоработок, но технология новая и активно развивается. Писать большими буквами «НЕ ИСПОЛЬЗУЙТЕ АНГУЛЯР» выгладит глупо и по-детски. Мне эта технология помогла решить много проблем в сложных приложениях и она мне действительно очень нравится, но я не стану кричать всем «ИСПОЛЬЗУЙТЕ AngularJs, {{ваш_фреймворк}} отстой».
    • +12
      Если бы вы прошли хотя бы официальный tutorial, вы бы знали как это решается.
      Автор пишет что решение есть, но есть один большой нюанс… Могли бы обойтись и без решения. Т.е. мы сначала создаём проблему, потом создаем её решение, и так много где в ангуляре => что-то не так в архитектуре даже если это помогает что-то решить. Собственно весь пост к этому и сводится, пусть немного истерично, но всё же. И, судя по второй версии ангуляра, разработчики angularjs об этом знают и идут верным путем, но не торопясь(по причинам описанным вами же)
      • +4
        Автор пишет что решение есть

        Покажите мне где автор пишет о решении? Если вы имеете ввиду директиву ng-cloak, которую он упомянул, то это не решение, а затычка. Костыль, если хотите, как автор его и назвал. И если вы его используете, то с большой уверенностью могу сказать что вы уже пошли не по той дорожке. Bad practice, как говорится. Это, как я уже говорил, показывает что у автора просто недостаточный опыт.
        В любом фреймворке вы найдете инструменты, которые использовать не желательно, и использование которых сигнализирует о том что вы неправильно его (фреймворк) используете.
  • +8
    Вполне обоснованно, а значит уместно. Для расширения кругозора и во избежании «зашеренности». Идеальных инструментов нет и все мы должны это понимать и принимать. И делать выбор в соответствии с задачей. Спасибо!
  • +12
    Это вы еще не пытались быть умнее фреймворка при работе с knockout.js
    • +2
      А поделитесь пожалуйста, с какими проблемами вы столкнулись при работе с knockout.js и как их решали?
      • +3
        Все беды, в общем-то, из-за желания заниматься велосипедизмом.

        1. Начнем с того, что все KnockoutObservable<T>.subscribe(t => any) и KnockoutComputed имеют dispose(). Таким образом, если создавать SPA с кучей представлений, то рано или поздно память начнет течь. Поэтому приходится делать отдельно функцию, вызывающую .dispose() для всех локальных подписок и вычисляемых значений. Код начинает походить на C# или C++, где на каждый конструктор пишешь деструктор.

        2. В knockout поддержка асинхронной загрузки шаблонов появилась только в версии 3.3 и, насколько мне известно, только для knockout components. Естественно, что в большом приложении грузить все .html разом файлы смысла нет. Пришлось писать свой враппер поверх template, который учитывал бы все возможные варианты(шаблон уже есть в разметке, шаблон загружается, шаблон следует загрузить, работу с with, as, data, foreach)

        3. Любой более-менее сложный контрол требует простыни описания для конкретного случая. Писать в разметке по 5-10 строчек в data-bind было неинтересно, тем более, что typescript там не поддерживается, да и intellisense работает, мягко говоря, через раз. Я решил решить эту проблему возможностью вынесения кода из data-bind в отдельный файл с общим ключом привязки по строке. То есть <div data-bind=«bindId: 'myKey'» ></div>. Проблема начинается, когда через этот bindId проходит привязка, контролирующая дочерние элементы DOM. По логике, казалось бы, ты привязал данные, инициализатор привязки вернул { controlsDescendantBindings: true }, но это осталось в коде. Как только код добавляет (да через тот же foreach) элемент в документ, заболтивый нокаут бежит по всем data-bind указанным в разметке, и не найдя там привязки, вернувшей controlsDescendantBindings, начинает повторную привязку. Самое ужасное, что во время первой инициализации все нормально и глюк может иногда не воспроизводиться. Таким образом для слишком умных привязок или приходилось добавлять привязку-пустышку data-bind=«stopBinding: true», все тело которой controlsDescendantBindings: true, или отдельно учитывать эти моменты в инициализаторе bindId.

        Кстати с новыми pureComputed я тоже не очень хорошо подружился, так что катить бочку раньше времени на них не стану
        • 0
          С вашими аргументами я соглашусь, по этой и описанным уже тут причинам я стараюсь делать ui как можно проще, да и пользователям намного лучше, когда не приходится совершать кучи лишних действий. А вообще я использую фабрику виджетов — jquery ui widget (виджеты пишу свои или юзаю плагины для jquery) вместе с нокаутом и пока эта связка меня не разочаровала, может быть и вам стоит обратить на это внимание. Если проект нормально разбит по папкам, то проблем нет. И конечно же, нужно управлять загрузкой этих виджетов, но это уже другая история.

          Инструменты не совершенны, да.
          • +1
            А расскажите, как вы решаете следующую проблему: в разметке есть один div для popup. Биндинг к данным сделан в Knockout. Хочется через knockout открывать и закрывать (уничтожать) несколько попапов с разными данными. Есть ли красивое решение для этого?
            Что я делаю сейчас — делаю div невидимым, пишу обертку, которая при открытии попапа клонирует html и делает клону ko.applyBindings(). Имхо, это дичайший костыль.

            tl;dr Как в Knockout жить с моделями, которые могут быть дуплицированы и привязаны к разным данным?
            • 0
              Первой проблемы у меня не появляется, потому что я использую jquery виджеты и там логика у меня немного другая, можно попап написать свой и вешать его на любой элемент. Конечно, div попапа будет создаваться на каждый попап, но зато сразу решается ваша проблема. Вообще с этой фабрикой виджетов и нокаутом получается как в веб-компонентах — есть шаблон html файл отдельно, есть js код отдельно (виджет и есть модель), подгружаем два этих файла и всё хорошо (можно сделать простой загрузчик виджетов на 150 строк).

              Вторая проблема с моделями. Последнее время я использую централизованное хранилище (можно сделать очень простое, а можно покруче). Так получилось, что нам в компании для упрощения работы понадобилась реализация схем данных mongoose (node.js) на клиенте и пришлось реализовать этот механизм — в результате получился хороший storage со схемами данных, с валидацией, работающий с knockout + es5 (https://github.com/SteveSanderson/knockout-es5) + еще несколько других фишек из mongoose. Так вот, если использовать его, то получается, что все данные у вас в одном месте и вы просто запрашиваете их для конкретного виджета (в нашем случае). Пока, при таком подходе, я проблем не заметил.

              Если вам интересно, я могу сделать демку, поделиться своими наработками в плане нокаута.
            • 0
              Полагаю вам необходимо написать собственную привязку (binding) или компонент, который будет инициализровать разметку или еще чего, когда вам надо.
              Как я уже выше подмечал, можно указать, что bindingHandler будет сам обрабатывать дочерние привязки или вообще вручную работать с DOM.
  • +14
    Ну есть проблемы да, ну а где их нет? Половина статьи описывает проблемы в духе нужно хорошо изучить фрэймворк, чтобы его использовать на полную катушку.

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

    >либо jQuery
    Лол, что? Надо было сразу прочесть конец и не читать статью.
    • +3
      2K датабайндингов лечится, об этом отписал ниже.
      • 0
        Да, читал про лечение, но хочется попробовать реакт. Он судя по тестам работает намного быстрее.
        • +1
          Реакт с ангуляром нельзя сравнивать, реакт это просто вид и загрузка дынных без контроллеров или сервисов.
          В ангуляр React спокойно интегрируется через ngReact.
          • 0
            Собственно по этому Ganesh и говорил про «возможно в связке с angular».
  • +2
    > Гугл не использует AngularJs для своих основных продуктов (gmail, google+). И это вызывает подозрения, если это такой хороший фрейворк и они сами его создали, что тогда сами и не используют?

    Nowadays, the framework is used by more than 100 projects just at Google, and it is maintained by its own internal team, in which Miško takes part.
    • +6
      У гугла просто море проектов (видимо из-за того самого «правила о скольки-то там процентах рабочего времени на свой прожект» чуть ли не у каждого сотрудника))) Естественно, большинство из них никому не нужны, а иногда они становятся огромными, но все равно умирают. Покажите в каких действительно _рабочих_ проектах гугл используется этот фреймворк? Похоже, что автор прав.
  • +38
    Автор немножко переборщил с эмоциями, но в целом первое впечатление от ангуляра передал верно.

    Я после просмотра туториала по дурости решил, что смогу склепать ui на ангуляре самостоятельно. В результате целую неделю собирал все возможные грабли и косяки (вот какого дьявола в диалоге автоматически создаётся лишний scope, например?) — а потом забил на это дело, и передал доводку UI фронтэндщикам. Дальше было чистейшее шаманство: ребята говорили, что «вот тут надо написать именно вот так, потому что только этот способ работающий, а тот, который я углядел в доке — он именно здесь не подходит, потому что такая магия», и это надо тупо выучить. Я серверный программист, я привык к тому, что всякие там фреймворки пляшут под мою дудку, а не заставляют учить заклинания.

    Ну, и если уж быть до конца честным, с годами ситуация с web-based ui как-то качественно лучше не становится. 6 лет назад я писал на ExtJS, и это было ужасно, потом мне здорово покушал нервов проект на JSF, теперь вот появился ангуляр — годы идут, а сложность, противность, и незрелость используемых инструментов никак не уменьшается. Печально это.
  • +27
    Лишь отчасти соглашусь с некоторыми суждениями, но СЛИШКОМ МНОГО BOLD'оВОГО КАПСА НИКОГДА НЕ БЫВАЕТ МНОГО.

    Во многом согласен с комментариями о дилетантстве — все описанные проблемы достаточно просто решаются при наличии желания и гугла.

    Ограничения $digest цикла можно легко преодолеть, об этом уже было написано тут и о результатах в 1200ms -> 35ms тут.

    DI не работает после минификации — в офф доках ангуляра прямо говорят (раздел Note on minification): используйте $inject, или аннотации. Опять же, не стоит ныть по поводу «мне влом написать 5-6 слов со знаком $ — этого не должно быть, это проблема фреймворка !». Указать минификатору наличие сторонних глобальных переменных не составляет особого труда, и это никак не относится к дизайну самого фреймворка.

    По поводу «нетестированности» самого фреймворка, а автор пробовал Protractor с ngMock'ом? Есть $exceptionHandler и им вполне так удобно перехватывать любые ошибки. Хватит ныть — читайте документацию.

    Наследование скоупов не имеет прямого отношения к ангуляру непосредтсвенного — это просто заморочка прототипного наследования в JS'e. Немного гугломагии подтверждает, и такого уже было написано очень много. Опять же, сами ангуляровцы в доках советуют не использовать глубокое вложение объектов внутри $scope потому что там будут глюки с $watch'ерами и $digest циклом. Использование нескольких уровней вложения в рамках одной директивы не поощряется, по тем же причинам что и указанны в статье… и это не является проблемой — ничего не мешает писать $scope.btnCaption вместо $scope.btn.caption.

    Синтаксис
    ng-controller="SomeController as OtherName"
    не более чем синтаксический сахар для избежания путаницы в описаниях контроллеров, и никакого отношения к проблеме не имеет.

    Понимание или непонимание работы директив зависит от каждого конкретного разработчика — проще чем есть сделать не получится. Если для вас это сложно — это ваши проблемы.

    По сравнению с тем же backbone или ember — Angular совсем не сложный, и в нём ничего не протекает. Конечно после jQuery у людей странное выражение лица, но качественный богатый фронтенд не подразумевает место для поиска «плагина завоевания мира нажатием одной кнопки». Учитесь, и не нойте!

    Невозможность серверной шаблонизации… хм, ну это зависит как посмотреть на проблему — берём prerender.io, прикручиваем рендер страниц при изменении моделей, кэшируем нормально в Nginx'e и отдаём поисковым роботам. Не то что бы это было изящно, но и писать серверный рендер ангуляра под каждую платформу бессмысленно. Тем более такой подход при небольших нагрузках на запись вполне нормально работает. Для прозрачной клиент-серверной шаблонизации нужна трансляция OT-патчей в CQRS-ES'e — это довольно сложные подходы которые используются в корпоративных приложениях с незапамятных времён (привет vaadin, привет gwt, давно не виделись).

    А кто сказал что гугол не использует у себя Angular?

    В общем все проблемы которые описанны в статье — вполне решаемы.
    Было бы желание погуглить, и не постить на хабр всякую ерунду из-за собственной лени.

    Я не говорю что React плох, но сравнивать React с Angular'ом НЕЛЬЗЯ. React это лишь View и View-Model из MVVM, а Angular — чистое MVC. У ангуляра рендер реально слоупочный, и появляются такие странные вещи как ngReact (чую запах жареных мозгов). Я и сам спокойно гоняю React + rx.js в браузере, и на node.js, и вполне так доволен производительностью для средних проектов.

    Я надеюсь что во втором ангуляре исправят косяки рендера и начнут напрямую оперировать DOM деревом, без лишних перерисовок и перекомпоновок чего-попало.
  • +6
    Само собой, статьи на тему «почему не ангуляр» нужны. Но эта статья какая-то странная… Здесь скорее перечислены проблемы, возникающие при старте, чем какие-то фатальные недостатки, которые будут преследовать вас на протяжении всего процесса разработки.

    Собственно, из недавно прочитанного я бы посоветовал это:
    www.fse.guru/2-years-with-angular
    www.fse.guru/why-you-should-learn-angular-anyway
    • +8
      Я автор вышеприведенных статей.
      Статьи написаны «по верхам» с умыслом.
      Если у вас будут вопросы — то я с радостью отвечу :)
      • 0
        О, я тогда хочу вам сказать спасибо, за упоминание mithril.js в обзоре фронтенд-фреймворков. Чудесная штука.
        • 0
          Посмотрите еще cycle.js: github.com/staltz/cycle

          Правда, я бы не сказал, что это продакшн-реди фреймворки, подходящие под мои критерии. Но идеи и тенденции в них заложенны более здравые.
          • 0
            Спасибо, я посмотрю на cycle и попробую разобраться с FRP еще раз. До сих пор не осилил как-то.
        • 0
          Он сыроват пока, и для продакшена не готов (
          • 0
            Ну что ж поделать-то. Значит, нужно использовать в pet project-ах и ждать готовности. =)
  • +5
    «ага, тут кликнули по кнопке и изменилась модель, теперь нужно слушать изменения на этой модели и когда она меняется вызывается хэндлер», а не «кликнули на кнопку, вызвался хэндлер»

    Хм, ng-click=«clickHandler()»?
    ДВУСТОРОННИЙ БИНДИНГ — ЭТО НЕ ТО КАК ПРОИСХОДИТ ОБРАБОТКА СОБЫТИЙ В ПРИНЦИПЕ

    Угу, и, $watch() моевтон в 99% случаев, особенно в таких, которые вы описали.
    Еще двусторонний биндинг означает, что изменив что-либо в своем приложении, это тригерит сотни функций

    Странно, а я думал что там dirty checking цикл, и изменение переменной абсолютно ничего не триггерит.
    ТО ВЫ ТОЧНО УПРЕТЕСЬ В ЭТО ОГРАНИЧЕНИЕ

    Стоит подумать о своей архитектуре, а не об архитектуре ангуляра. Да, на RICH приложения он и не затачивался (это, кстати, к слову о gmail'e). Если вам нужно 1000+ биндингов, то вы неверно выбрали инструмент.
    Когда вы минифицируете свой код, то он перестает работать

    Когда это минификатор, особенно с агрессивной политикой оптимизаций, не требовал препроцессинга / своего стиля написания кода?
    Наследование скопов

    Хм, а прототипное наследование в JS вас не напрягает заодно? А ОО-архитектура со странными всплывающими багами при непонимании парадигмы? Имхо, скопы и их наследование довольно хорошая штука. Если посидеть 15 минут с отладчиком и поразбираться в их механике, то в дальнейшем вопросов нет.
    сделать одну единственную функцию

    Вы не поверите, но описывать директивы можно одной единственной функцией. Использование синтаксиса директив на полную не всегде нужно, но он придаёт довольно сильную гибкость директивам.
    трансклюд вообще хрен пойми

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

    Программирование на достойном уровне вообще сложная штука. Даже без ангуляра более-менее сложное приложение не разобрать с наскоку. Ну скажем, если не хотите async hell'a, то у вас будут промизы, которые в серверных языках не всегда используются.

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

      Очевидно, но, надо признать, достаточно геморройно, особенно если юзаешь сторонние директивы и их приоритеты.
    • 0
      Странно, а я думал что там dirty checking цикл, и изменение переменной абсолютно ничего не триггерит.


      Обычно в сложном приложении получаются много $watch('xxx', function(...){...}). Вот они вызываются при каждом $digest цикле и не по одному разу.
  • +2
    Недостатки будут везде, их не избежать.

    Но плюсов, то больше. Фреймворк позволят весьма удобно организовать код, и сразу знать где что искать.

    Директивы — это конечно ад, зачем их так сложно сделали, понять просто не возможно. Если их не писать постоянно, то скорость непонимания уже написанного просто феноменальна.

    P.S. Мой личный фаворит в недовольстве — «а давайте обернем весь остальной мир в директивы». Это просто ужас, делать столько бестолковой мало чем оправданной работы… При том что авторы того, что мы оборочаиваем тоже не дураки и часто их решения по подключению бибилиотеки просто в разы удобней всяких директив, за которыми надо еще следить потом.

  • –7
    Как всегда, собственно. Сначала всем всё нравится, но обязательно должен появиться кто-то, кто скажет, что это плохо. Думайте, наконец, своей головой, ей богу. Ни один из аргументов в статье нельзя воспринимать всерьёз.
    • +3
      Мне вот например не нравится бутстрап, который нравится очень многим :)
      • +1
        Не только вам.
        Он гробит семантику разметки и задачи самого HTML5.
        Так что годится не более чем для внутреннего использования и прототипирования.
        • +1
          Не гробит, просто нужно уметь готовить www.sitepoint.com/sass-semantically-extend-bootstrap/
          • 0
            Хороший пример
          • +4
            В очередной раз «умение готовить» демонстрирует принцип — сначала создадим себе проблему, а потом будем её решать сторонними дополнениями.
        • 0
          Просто нужно использовать CSS-препроцессоры, и никто ничего гробить не будет.
          • +1
            Раздражает его привязка к тегам, а не классам.
            • –1
              Бутстрап весь на классах.
              • 0
                • 0
                  это нормализация, а не часть функционала. все на классах.
                  • 0
                    • +1
                      тэги используются там, где обусловлены семантикой — для них это стало главным с выходом 3й версии.
                • 0
                  Понял, думал, что вы про общие теги (например, привязка div.alert или table). Вообще, есть такое.
      • 0
        Мне тоже. :) Но я хотел сказать не об этом. Автор статьи, толком не разобравшись с проблемами, вставшими у него на пути (а все эти проблемы вполне себе преодолимы), рекомендует нам не использовать Angular, что, по сути, весьма неразумно, учитывая все те прелести, что фреймворк нам предлагает.
        • +6
          Разве? По-моему автор часть решений проблем разобрал. Его позиция заключается в том, что это не практические проблемы, а проблемы плохого дизайна.
  • +1
    • 0
      Вы мне только что как верстальщику камень с души сняли. А то я уже думал, что всё – дальше расти только в Angular/ReactJS/etc. Сейчас понял, что фигушки – лучше верстать буду хорошо, чем очень долго и очень плохо пытаться программировать сайты на инструментах для создания приложений.
  • +3
    После знакомства с Ангуляром мне в голову пришла следующая метафора.

    Предположим, у нас есть некоторое приложение. Мы, как архитектор этого приложения, знаем как в нём организованы потоки данных. В приложении мы задекларировали эти потоки данных и то как их следует обрабатывать в виде некоторого кода. То есть у нас описаны некоторые конкретные блоки, которые связаны конкретными линиями-направлениями данных.
    В противовес этому, Ангуляр представляет собой что-то вроде «множества универсум», где всё связано со всем. В первый момент это вызывает wow-эффект. В самом деле, путём нескольких деклараций и пары строк кода мы организовали полноценный ввод пользователя, обработку и автоматическое обновление представления (!). Но в дальнейшем становится ясно, что такая полносвязная схема имеет свои побочные негативные эффекты: низкая производительность и сложность восприятия.

    Я был очень рад услышать, что идёт разработка Angular 2, который (как и обязано мажорному релизу) будет обладать существенными изменениями, и в частности упрощениями, выпиливанием целой кипы фич. Также, существует разработка angular-light, которая освещалась на Хабре и ознаменована той же цели: упростить и оздоровить Ангуляр.

    После использования Ангуляра я пришёл к выводу, что лучше строить приложение, основываясь на явных потоках данных. Для этого лучше всего подходит идея FRP. Что замечательно, FRP прекрасно компонуется с существующими библиотеками (я считаю, компонуемость — это очень хороший признак действительно здоровой концепции), например, можно использовать jQuery для получения источников данных (пользовательские события, которые инициируют flow/поток), так и для отображения ($.text, $.html в конце цепочек), также FRP прекрасно дружит со всеми существующими шаблонизаторами.

    В общем, явное лучше неявного, FRP и компонуемость это будущее.
    • +2
      Абсолютно согласен, на парадигмах FRP писали реактивный манифест.
      Пробуйте React + rx.js если интересует полноценное FRP в браузере, и Typesafe Stack со Scala на сервере…

      За реактивными приложениями действительно большое и светлое будущее.
      • +1
        Мне очень по нраву Highland за началом вот этого замечательного человека. Highland не такой зрелый, как Rx, но меня радует его лаконичное API и вообще подход.
        • 0
          На вкус и цвет — все фломастеры разные.
    • +1
      На самом деле Angular никак вас в этом плане не ограничивает. Есть Angular-bacon для того что бы строить FRP в angular-based приложениях.

      Более того, я лично вижу проблему во фразе «Angular-way». В частности, довольно популярная библиотека для работы с localStorage полностью построена на ватчерах и циклах дайгест. То есть просто так. Потому что это этот самый angular-way. Откуда у людей берутся такие идеи я не знаю.

      Проблема в том что инструменты предоставляемые фреймворком зачастую используются не по назначению, не оптимально, не эффективно а просто потому что можно. Люди видят это и начинают делать так же. Почему-то мало у кого свои какие-то мысли возникают на счет как что делать.

      p.s. основная идея Angular Light не в том, что бы «оздоровить» Angular, а в том что бы дать возможность использовать тот самый синтаксис шаблонов (а с ним и директивы + фильтры) без необходимости использовать полноценный фреймворк.
      • 0
        Такие идеи из примеров, пропагандировавших этот подход.
        Ранняя документация имела конкретные намеки на angular way.
      • +1
        p.s. основная идея Angular Light не в том, что бы «оздоровить» Angular, а в том что бы дать возможность использовать тот самый синтаксис шаблонов (а с ним и директивы + фильтры) без необходимости использовать полноценный фреймворк.
        Я тут не вижу противоречия. Похоже, что мы с вами говорим об одном и том же. Под «оздоровить» я как раз и имел ввиду «выделить ключевую идею и убрать мишуру».
        • 0
          Под мишурой вы имеете в виду то, что делает Angular фреймворком а не библиотекой как react.js? Ну так в Angular2 уже решили сделать все модульным. То есть начиная с версии 2.0 фреймворк будет полностью разделен на отдельные независимые компоненты (кое какие, например тот же DI, уже доступны и как по мне вполне себе стабильны) и вы будете вольны использовать только то что используете. Меня же устраивает монолитная структура Angular так как я задействую всю эту мишуру (DI, директивы, модули, разделение на этап конфигурации и выполнения и прочую «чушь»).
  • +6
    О, вы меня сподвигли начать писать статью про vue.js, наконец.
    Который при желании может прикидываться и ангуляром, и бэкбоном (в минимальной форме, конечно, но порог входа для тех, кто с ними имел дело, около плинтуса), летает (перфоманс — изумительный). Поддерживается буквально двумя людьми, но при этом мелкие issue-ы, которые я им пишу, например, вечером в четверг, в 6 утра в пятницу оказываются уже исправлены :)

    Ну и подход очаровывает.
    «DI? да нахрена вам DI в фреймворке для клиентсайда, у тебя есть AMD или CommonJS или что еще придет в твою больную голову»
    «Что? Навигация? Чувак, тебе оно точно надо? Посмотри сколько клевых библиотек для навигации и без нашей помощи сделано, мы тебе сделали директиву для смены лейаутов, на здоровье»
    «Компоненты? Службы? Модели? Директивы? Сервисы? Чо ты к нам пристал. На тебе фильтры для шаблонов, компоненты для, собственно, автономных компонентов, и директивы для всяких мимимишных жкверишных плагинов твоих, хватит тебе».
    И реально хватает ведь.
    А что самое крутое — он эти шаблоны свои — ну вот такой, например: {{ profiles[currentUserId] }} — (да-да, привет, ангуляр) он не разворачивает как-то, а превратит в
    try {
    return this.profiles[this.currentUserId];
    } catch (e){
    ...
    }
    

    и если флаг debug установлен — он сам вызовет дебаггер на ошибке. А this реально указывает на окружение, которое можно полноценно поинспектировать.
    Я так приложение в айфрейме дебажил (был один прикол, связанный с хромовскими приложениями). Как бы я с другими фреймворками это делал — вообще бы не представляю.
    • 0
      vue штука действительно хорошая и минималистичная.
    • 0
      Видимо вы не видели обёрток backbone которые пытаются предотвращать утечки, но у них это не очень хорошо получается. И не строили рективных приложений с частыми (50-60 в сек) push-нотификациями с сервера по comet'у или websocket'aм…

      Vue.js достаточно простое решение производительность которого под большим вопросом — авторы говорят что сравнивать его с React'ом, Backbone'ом или Angular'ом на данном этапе развития нельзя — слишком разные методы рендеринга, больше меряем производительность браузера нежели фреймворка… хотя на самом деле авторы хотели переплюнуть React, но у них это не получилось и им стыдно стало :3 А вот с тем что с остальным сравнивать бесполезно — там будет разница просто адовая, я вполне согласен.

      Но опять же очередное сырое решение не готовое для продакшенов средних размеров.
      • +1
        С react-ом — сравнивать вообще что-либо сложно, особенно с react+om.
        А в нынешней версии (0.11.х) почти все детские ошибки исправили. Я за проектом почти год уже слежу и могу на полном серьезе сказать — 99% кейсов покрыто, и неожиданные ошибки в духе «что-то не работает, хотя должно» — на 0.11 у меня ни разу не появлялись. Да, были ляпы, связанные именно с новыми фичами (вот два, которые я закоммитил: #652, #594, например) — но конкретно с работой приложения они уже не были связаны.

        Я бы сказал, что сейчас Vue — medium rare. Да, немного сыроват, но удовольствие от употребления будет наблюдаться у большинства :)

        А насчет 50-60 обновлений в секунду — я в январе за подобный проект берусь. При этом это полноценный энтерпрайз с джавой на бэкенде и прочими удовольствиями жизни. Сейчас думаю над выбором: ангуляр или React+Om. При этом совесть меня склоняет к первому, а предчувствие жопы с перформансом — к второму. О Vue там и речи быть не может, конечно — даже не из соображений того, что он нестабилен так или иначе, а как минимум из-за того, что он поддерживаться будет не один год, и найти разработчиков на vue в дальнейшем будет сложнее, чем на react или angular.
        • 0
          J2EE сервлеты vs Plain Netty это ~35 к 1 по скорости обработки пустых запросов.
          При больших БД, и толстых кэшах нужно внедрять offheap кэширование, можно на hazelcast'е или terracotta'е.
          ClojureScript'овый Om выглядит лично для меня очень небрежно — как если бы elisp с prolog'ом смешали.
          Кроме всего этого нужно ещё внедрять rx.js или highland для отработки асинхрона без лишних проблем.
          • +1
            Да я-то тут при чем. Я фронтэнд обеспечиваю. Я вообще джаву не умею и не хочу уметь (но, видимо, андроида ради и придется когда-нибудь).
            Как специалист я сраный фронтэндщик, который даже верстает медленно, зато умеет в джаваскрипт так, что все вокруг хренеют, на этом мои прикладные способности заканчиваются. То, что я умею дизайн, ux, настраивать nginx, спокойно кодить под рельсы, работать с кучей других языков, читать исходники v8, паять усилители, управлять разработчиками и разбираться в особенностях низкоуровневых протоколов — это круто, но это исключительно жырный плюс к тому, что я хороший фронтэндщик, который понимает как работает все, с чем он взаимодействует — начиная от того, как работают http-запросы на всех уровнях модели OSI и заканчивая тем, как повысить конверсию :) Потому и занимаюсь такими замороченными проектами.
            И вот честно, никакого желания в этот неплохой багаж знаний добавлять особенности работы кэшей под джаву)

            Но про Om запомню, спасибо.
      • 0
        Извините, но что у Вас за задача такая, которая вынуждает слать 50-60 нотификаций в секунду с сервера?
        • 0
          Учёт работы ~400 человек персонала в реальном времени: телефония, консультирование, денежные транзакции, доставка товаров…
          • +3
            Смысла нет так часто слать, раз в секунду достаточно, человек же не машина.
            • 0
              Там очень много данных вбивается и редактируется в реальном времени достаточно большим количеством людей — нужно это всё синхронизировать и формировать Batch запросы на запись в журнал изменений, проставлять временные метки в векторных часах и решать задачу консенсуса (у меня пока raft). Это можно представить как один большой гуглодок с табличками которые очень быстро правят 5-6 человек, и в метериализованном представлении которых постоянно пересчитываются и перепроверяются данные после каждой правки в браузере.
            • 0
              Да, именно поэтому и спросил. Мне сразу представилось перемигивание разных кнопочек и формочек в окне, от которых начинает рябить в глазах. Так и не понял почему нельзя посылать «сумму» изменений к примеру раз в секунду (а то и реже).
  • –3
    Количество плюсов этой статьи напрямую отражает количество дилетантов на хабре, и это печально.
    • –1
      А может некоторые уже давно перешагнули ангуляр? Ну хотя бы разработчики самого ангуляра ;) Версии 2.0. Хотя там вроде даже люди поменялись, но это другое
      • +1
        Для тех, кто перешагнул ангуляр, не составит особого труда погуглить и решить все проблемы описанные в статье.
        • +2
          Автор решил. Не использует ангуляр.
          • +1
            Как по мне это не перешагнуть а сдаться.
            • +4
              как многие сдались c YUI, mootools, prototype etc.
  • +4
    Использую Angular не два года, а всего полгода, но хорошо понимаю автора.

    После известий о Angular 2.0, который всё поломает, я решил посмотреть на что-то другое и сейчас читаю документацию по ember.js — и знаете, СЛЕЗЫ СЧА^W^W слезы счастья катятся по моим щекам. Если кто-то испытывает непонятный баттхерт от прекрасной, как все вокруг говорят, технологии — советую посмотреть на ember.
    • 0
      У ember'a долгое время до первой версии были проблемы с API и сообществом — не было документации нормальной, и обратная совместимость отваливалась от версии до версии. Сейчас это один из ходовых фреймворков без особых заморочек, «который работает». Его задачей было: сохранить простоту, и не раздувать излишне свой функционал. Angular любят за то что там можно писать меньше кода, и от него бывает больше толку. Но шаг влево — шаг вправо, не по гайдлайнам — сразу начинаются приколы. В общем порог вхождения не большой — нужно просто много читать и разбираться, а не писать вот такие вот бесполезные статьи на хабр.
      • 0
        Пишу и на Ember, и на Angular. На Ember у меня всегда меньше кода получается. И самое главное: я могу пересесть с одного Эмберовского проекта на другой без особых разбирательств, а Angular в каждой команде почему-то готовят по-своему и приходится время тратить, чтобы разобраться, какие тут приняты правила и конвенции.
    • +1
      Пишу на Ember. По началу — все радужно. Потом всплывают разные косяки, которые обещают починить в 2.0

      Основное, что считаю поломанным сейчас:
      1. собственно EmberData. Да, оно в бете, и грех жаловаться, но готовьтесь к тому, что: rollback не работает на one-to-one, one-to-many, DataBoundPromise никак не доедут до релиза
      2. документация отличная, но не покрывает все моменты (некоторые вещи приходится смотреть прямо в коде)
      3. многострадальные queryParams. Они вроде как есть, но некоторые вещи в них не работают и на них заведено много issue
      4. синглтон контроллеры настолько всем не нравятся, что их убирают в 2.0
      5. сложно писать сложные компоненты, где требуется обновление большого кол-ва property и не хватает one-way binding property. Новый подход к компонентам обещают в 2.0 (больше похоже на React)

      Что действительно радует — роутер, к нему претензий нет.

      Судя поrfc для 2.0, они хотят с помощью HTMLBars + one-way binding сделать компоненты похожими на React, но при этом использовать всю мощь роутера и EmberData для моделей
      • 0
        По 4му пункту я сейчас обхожусь тем, что пишу без контроллеров. Все контроллеры — автогенеренные Эмбером везде, где можно. По факту пишу свои только если нужны queryParams. Решает кучу проблем.
        • 0
          Это то, к чему они идут в 2.0. Т.е. все property, фильтры и прочее в Route?
    • 0
      Скажите, а зачем вы выбираете инструменты, которые «умеют все»?
      • 0
        А такие существуют?
        • +3
          Я о том, что многие инструменты пытаются добавить все на свете в свой функционал. ИМО это плохо заканчивается.
          • 0
            Согласен, «разделяй и властвуй».
            • 0
              Угу. При чем плохо заканчивается для разработчика/продукта. Вместо замены одного компонента приходится выбрасывать 80% кода при переходе от А к Б.
      • +3
        Вопрос не в том, что инструмент умеет все, а в том, сколько у вас накапливается в проекте кастомного и glue-кода, который ничего не делает кроме как соединять отдельные «идеальные» микро-библиотеки.

        Многие считают:
        1. о, я возьму вот эту микробиблиотеку, соединю вон с той, буду брать все самое лучшее, все то и только то, что подходит для моей задачи, — и получу идеальный проект.
        2. потом в коде для склейки частей у них возникает какое-то дублирование кода, вырисовываются какие-то шаблоны, они их начинают вычленять, радуются, как у них все идеально и идиоматично, и т.д.
        3. так из идеальных кусочков у них получается свой недофреймворк, на котором они пишут свое приложение.
        4. а потом этот фреймворк начинает трещать по швам из-за «особых частных случаев», обхода багов в выбранных библиотеках, несостыковываемостью выбранных компонентов между собой, проблем с производительностью и т.д.
        5. а времени фиксить недофрейсворк нет — проект, сроки, заказчик, менеджер. Взяли человека в команду — ему с ним теперь неделями разбираться. А если «автор» фреймворка уже ушел из команды, и вы — как раз тот человек, кому придется разбираться в костылях вокруг идеальных библиотек образца 2013 года?

        Иногда проще взять готовое большое решение и быстро решить задачу. Плюсы Эмбера:

        — это такой же фреймворк, как и ваш самописный, но его в том или ином виде дорабатывают с учетом требований различных разработчиков несколько лет. Получается, что у вас фора — несколько десятков человеколет на вашем проекте. Багов в нем мало, шансов столкнуться с ними — не один раз в день, а один раз в месяц, например. Если у вас возникает «особый случай», очень высока вероятность, что где-то в Эмбере предусмотрены лазейки и хуки, чтобы его вписать во фреймворк.
        — архитектура решена за вас, не нужно ничего придумывать, не нужно спорить о том, как сделать лучше.
        — вопрос инструментов сборки или подключения аддонов для вас тоже не стоит: все уже решено, вы делаете как все.
        — в отличие от Angular подводных камней гораздо меньше, мест где нужно изобретать велосипед — тоже, инструменты лучше, диагностировать и решать проблемы производительности проще.
        — полно больших open-source проектов — всегда можно посмотреть, а как люди решают ту или иную задачу.
        — все пишется в открытую: нет такого «ой, мы тут версию 2.0 готовим — все теперь будет не так, как раньше»

        Он не делает для вас все, но 90% того, что он делает, вам наверняка подойдет.
        • 0
          Здраствуйте. Что-то просмотрел пост в свое время.

          Относительно избыточного клей-кода. Тут работает правило: «надо делать хорошо, нехорошо делать не надо». Ну и старое, «заставь дурака...» ну а дальше все знают.
          Просто лично я обычно вижу обратное, когда тянут комбайн для одной функции. И все эти проблемы клейкодов и оверкилов комбайном для колоска они ИМХО в основном от непонимания языка и не умения программировать.

          Что до Эмбера, то ничего не скажу. С виду хороший, во многом наверное лучший фреймворк для многих задач.
  • +6
    Довелось мне как то переписывать код с angular на backbone. Angular не понравился из-за вшитого кода в html. Htmlу и так уже плохо от всяких штук, а тут ещё и angular. Так что я не против angular, но только если мне не придется на нем писать.
    • +2
      «Я не против angular, но только если мне не придется на нем писать» — гениальное выражение :) Его кстати можно применить к вообще любой технологии :)
    • 0
      А мне довелось переписывать с backbone на angular, потому что backbone кушал 80Mb+ оперативки xD
      • +3
        а мне как разработчику не знакомому тогда ни с тем, не с другим, к backbone сразу любовь, а вот к ангуляру отвращение. Код был не рабочий, и понять что в нем не работало было невозможно.
        • 0
          У всех свои задачи. И есть инструменты которые подходят, или не подходят… нужно всё пробовать и мерить. А «любовь»/«нелюбовь» или «удобство»/«неудобство» не совсем конструктивное отношение по отношению к реализации любых продуктов. Это ведёт к «golden hammer»'ам и фанатизму.
      • +1
        Было бы интересно узнать, что там такое жрало много памяти. По моим представлениям там просто ничего такого нет, чтобы много жрало.
    • +1
      То есть вас не смущает вкрапления JS в шаблонах для lodash/underscore или специфичный синтаксис handlebars? Если бы шаблоны лежали с расширением не html а aml (angular markup language) вам было бы спокойнее? Это просто синтаксис шаблонов, ничего более. Чего все так зациклились на этом…
      • +3
        ну значит мне просто не нравятся шаблоны похожие на перенасыщенный html с атрибутами ангуляра.
  • 0
    этой проблемы можно было бы легко избежать просто УБРАВ ВОЗМОЖНОСТЬ НАСЛЕДОВАНИЯ СКОПОВ
    Вы имеете ввиду, если бы был один scope на все?
    В данном примере ng-if отвечает за дочернюю структуру (DOM и scope), и когда значение в ng-if будет = false, эта директива уничтожит дочернюю структуру (DOM и scope), если бы был один scope на все, то было бы не понятно, какая его часть является дочерней и что уничтожать, это разграничение обязанностей.
    Если просто убрать наследование, то не будут видны родительские объекты напрямую — это неудобно.
  • +4
    К вопросу о проблемах с людьми, ну и взгляд извне веб-разработки:

    Основной мой профиль — C#+WPF, опыт web/js был лет 7 назад, когда ещё jQuery только набирал популярность.
    Пришлось добавлять фичи в соседний проект на ASP.NET MVC Web Api + AngularJS, был приятно удивлён удобству Angular и схожести концепции байндингов с WPF. Втянулся за пару дней, реализовал несколько довольно объёмных формочек, пару директив. Конечно, спотыкался на многом, но в целом всё понравилось. У коллег тоже проблем не возникло.

    Считаю, что идея байндингов — очень правильная и удобная. И опции байндинга (one time, one way) вовсе не является костылями.
  • 0
    Ну видимо в гугле gmail и другие сервисы написаны до angular-а
    А тот же React как я понимаю писался под facebook (или параллельно, как например Django — изначально писалась для новостного портала)
  • 0
    Насчет сложности проекта на ангуляр и что в нем не разберешься…
    Все зависит ведь от разработчиков. Мне попадались проекты на jquery — где черт ногу сломит. Сейчас есть проект где используется React.js — тоже много спорных моментов.
    С ангуляром достались два проекта — в которых все средне (то есть разобраться можно, но есть весьма и весьма спорные моменты)
    Однако с ангуляром же есть и удачный пример. Когда мне попался код, написанный на coffeescript + angular
    По сути читал проект как книгу, все ясно и понятно и на своих местах, при том что до этого я на coffee не писал.
    • +2
      Ну криворукость отдельных индивидов от фреймворка не зависит. Костылять можно везде, не зависимо от инструментов, и к инструментам это не имеет никакого отношения. Я видел костыли и хорошую реализацию во всём с чем приходилось работать.
      • 0
        Собственно я о том же. В статье просто есть упрек, что в ангуляр проекте сложно разобраться новичку, а дескать в React все лекго и просто. Хотя на самом деле все зависит от реализации конкретного проекта
  • +13
    Смешались в кучу кони и люди…

    ДВУСТОРОННИЙ БИНДИНГ — ЭТО НЕ ТО КАК ПРОИСХОДИТ ОБРАБОТКА СОБЫТИЙ В ПРИНЦИПЕ

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

    ТО ВЫ ТОЧНО УПРЕТЕСЬ В ЭТО ОГРАНИЧЕНИЕ

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

    ЭТО ПЕРЕСТАЕТ РАБОТАТЬ ПРИ МИНИФИКАЦИИ КОДА

    Одноразовая ужасная проблема для новичка.

    Там вводятся 5 новых сущностей: provider, service, factory, value, constant (непродуманная-архитектура#4).

    Проблема на один раз разобраться и потом использовать по месту удобный способ объявления.

    Дебаггинг

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

    Я не буду объяснять почему так происходит, на эту тему столько статей написано в интернете. И что самое интересное — этой проблемы можно было бы легко избежать просто УБРАВ ВОЗМОЖНОСТЬ НАСЛЕДОВАНИЯ СКОПОВ. Это был бы правильный дизайн. К тому же когда вы используете переменные из родительского скопа, это становится крайне сложно тестировать, странно, что фреймворк, который ставит одной из своих самых сильных сторон легкость тестирования, вводит такую логику.

    Слабо раскрытая тема, я бы сказал, никак не аргументированная. Хотя следующий раздел про директивы наталкивает на мысль о глубине понимания автором директив и шаблонов в AngularJS.

    И что самое обидное — ЭТА СЛОЖНОСТЬ НЕ НЕСЕТ НИКАКОЙ ПОЛЬЗЫ.

    Абсолютно популистское утверждение. Только я один не заметил никакой аргументации по этому пункту?

    Проблемы с людьми

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

    Ужасная документация. Приходится дополнительно гуглить много информации.

    Хм, я начал изучать AngularJS еще до первой версии. И даже тогда мне документация не казалась ужасной. Надо было немного мозги подперестроить с императивного на декларативный стиль для чего эту документацию надо было прочитать в несколько проходов. А уж сейчас ужасной я документацию бы точно не назвал.

    До сих пор отсутствуют директивы для Drag and Drop событий (на момент написания этой статьи). Само по себе это не очень большая проблема, но это сигнализирует о продуманности продукта и внимании к деталям.

    Для вот этого? И как оно по Вашему должно в стандартной поставке выглядеть?

    Когда вы пишите на ангуляре вы помещаете логику в ваш HTML. ng-repeat, ng-show, ng-class, ng-model, ng-init, ng-click, ng-switch, ng-if — что это как не помещение логики в представление. Само наличие такой логики — это не настолько страшно, как то что — это невозможно тестировать юнит-тестами, невозможно продебажить и оттуда не кидаются ошибки

    В каком смысле невозможно тестировать? И что Вы там дебажить то хотите?

    НЕ ИСПОЛЬЗУЙТЕ АНГУЛЯР

    если вы ничего не знали и не хотите знать про двойной датабиндинг или он вам не нужен;
    если вам ближе разработка UI в императивном, а не в декларативном стиле;
    если вы предпочитаете дебажить вместо того, чтобы тестировать;
    если вы не хотите разбираться с «ужасными» директивами;
    если вы считаете что фреймворк должен думать за вас.

    А в целом в любом активно развивающемся направлении/инструменте всегда будут какие-то проблемы, ошибки и т.п. Как вообще без ошибок можно развиваться? Систему характеризуют не ошибки, а реакция на них. Ну и легкость решения возникающих проблем. Не увидел в этой статье ни одной непреодолимой проблемы. Хотя, честно говоря, и проблем то особых не увидел.
    • +4
      Отметил кстати для себя, что ангуляр как правило не любят бэкэндеры (по крайне мере в моей практике это так). Обычно бывает такая ситуация — человек смотрит туторы — все легко и просто. Начинает делать сам и сталкивается с суровой реальностью — что все не так легко и просто, когда делаешь не «hello world» и тут наступает момент разочарования и мысли что лучше бы я использовал — backbone, react, asm.js и т.д

      • +1
        Да, я бы даже обобщил: используется ли Angular для создания SPA или как-то по-другому.
      • 0
        У меня 5 лет опыта разработки бэкэнда. А последний год я пишу на ангуляре. И доволен как слон.
        • 0
          Аналогично, у меня 5 с лишним лет бэкенда вперемежку с спагетти-коддингом «на jQuery». Потом я понял, что в фронтенд-разработке должно быть что-то более удобное, что помогает, а не мешает писать код. Мои поиски привели меня к ангуляру. Да, поначалу трудно понять, нужно менять мировоззрение после jQuery, но потом все становится на свои места.
          Сейчас у меня около полутора лет опыта разработки с использованием ангуляра и могу сказать, что в целом он удобен. Да, есть недочеты и есть тонкости, но они есть везде и с ними можно жить.
  • +20
    Если вы действительно хотите получить ответ, то не спрашивайте напрямую как сделать XXX на фреймворке ZZZ. Надо писать так: да ваш ZZZ — полный отстой, на нем даже нормально XXX нельзя сделать. И вам очень быстро ответят как правильно сделать, то что вы хотели.
  • +3
    У меня давно впечатление, что написать что-то разумное на js просто невозможно.
    • +3
      ну-ну
    • +6
      Разумность написанного зависит от разумности пишущего.
      • –1
        Маслянность масла зависит от маслянности масла.
        По делу то что сказать хотите?
        • +2
          Я уже сказал. Говорить о том что на {язык} невозможно написать что-то разумное в ситуации когда на {язык} написано много разумного слишком противоречиво.
          • –6
            Для людей с бинарным мышлением хочу подчеркнуть, что выражения «у меня впечатление, что невозможно» и просто «невозможно» не эквиваленты. Как бы вам не хотелось, я сказал не то, что вам захотелось прочитать. Будьте внимательнее.
            • +1
              Нет, я вас все таки правильно понял. Однако, углубляться в словарную казуистику не стану.
              • –3
                «Не стану» надо было делать поста 3 назад.
                • –1
                  Когда мне понадобятся от вас советы, я обязательно обращусь. А пока, оставьте свое дурное воспитание при себе.
                  • –3
                    У меня все в порядке с воспитанием. Если вам не нужны советы, зачем вы комментируете мои посты? Думаете мне нужны ваши?
  • +9
    Тема «что-то не так с Ангуляром» обсуждается довольно давно и многочисленно. Чтобы собрать ссылки по этой теме, сделаем простой поиск и обход англоязычных источников.

    What’s wrong with Angular.js
    !0 проблем и тем: (чтобы сравнить с названным в статье — вот список)
    * Angular — HTML-парсер. Вследствие этого — трудности отладки.
    * Двустороннее связывание автор считает антипаттерном (связывать View в направлении Model).
    * Затратные средства наблюдения за событиями, что часто избыточно и сказывается на загруженности мобильного приложения.
    * Дублирование структуры с angular.module, что приводит к двойным изменениям кода в HTML и контроллере.
    * Медленность из-за dirty checking and HTML parsing (следствие п.3)
    * Нет серверного рендеринга, если без хаков.
    * Высокий порог входа (по факту), хотя провозглашали обратное. Признаётся как результат плохого дизайна. Много абстрактных слоёв.
    * Google сам не использует его в своих флагманских приложениях Gmail и Gplus
    *… Поэтому им ничего не стоит закрыть проект когда угодно
    * Будет скоро переписан [2.0], что есть хороший знак, но и будут новые проблемы.

    Как видно, очень много пунктов пересекаются в сравнении с названными 12 в статье автора, т.е. это — действительно, многими признаваемые системные проблемы. Но есть и некоторые новые для топик-стартерской статьи пункты относительно политики Google.

    Прочее (из популярного найденного первым же поиском):
    AngularJS: The Bad Parts
    Почему (и куда) мы ушли от Angular
    Things I Wish I Were Told About Angular.js
    The reason Angular JS will fail
    Почему земля круглая и мывсеумрём Не менее очевидный набор фактов
    • +2
      Как видно, очень много пунктов пересекаются в сравнении с названными 12 в статье автора, т.е. это — действительно, многими признаваемые системные проблемы.


      Спорный вывод. Я вижу в той статье и приведенном резюме другое: автор является убежденным противником двухстороннего связывания и декларативного программирования. Кроме того, автору кажется, что «медленный» dirty-checking особенно сильно скажется на мобильном приложении. Ну и плюс страшилки про закрытие проекта, абстрактные слои и переписывание.

      По поводу медленного dirty checking, особенно, в мобильных приложениях. На мой взгляд, это не так. Согласно моему опыту в мобильном приложении больше проблем возникает из-за количества одновременного рендеринга (сложный DOM, который еще и анимируется). В качестве примера: live-search с вываливающемся списком категорий при пустом поле ввода. Я тоже сначала подумал, что вся беда в dirty-checking — ведь надо слать запросы, частенько случается $digest и т.п. Убил некоторое количество времени на профилирование, добавление оптимизаций в js-код (запросы то, конечно, изначально не на каждое изменение поля ввода слались). Ощутимой разницы вообще не было. Проблемы оказались две: слишком много пытались отрендерить, что реально было не нужно — 3-5 записей максимально одновременно на мобильном экране были видны. Ну и в вываливающемся списке категорий изначально были svg. Замена svg на png дала, мягко говоря, ощутимый прирост скорости.
      Вообще, конечно, dirty-checking был и будет большой темой для споров. Это осознанный выбор авторов. Обсуждение его в отрыве от плюсов и минусов альтернативных решений, особенно в манипулятивном стиле без явных кейсов — это скорее популизм.

      По поводу серверного рендеринга. Наверное это сильно зависит от задачи, но в нашем проекте серверно рендерить надо было не более десятка состояний из сотен. Причем эти состояния по-большому счету надо отрендерить для роботов, т.е. в максимально облегченном виде. Абсолютно тривиальная задача и мы просто решили ее без AngularJS, используя Mustache.

      Ну и еще немного про приведенную статью:
      We are developers, we write and debug code. But Angular is HTML parser. I really don’t want to debug any string based parser instead of my code.

      Первый пункт, наверное, должен быть самым важным и мощным. Но это прям какой-то каминг-аут. Если вам приходится дебажить строки шаблонов вместо вашего js-кода (последнее тоже не совсем хорошо, но иногда нужно), то с вами что-то не так. А с кодом 99,9% почти все не так.

      И еще раз про то, для кого же создан AngularJS:
      для тех, кто будет стараться тестировать вместо того, чтобы дебажить;
      для тех, кто считает, что надо использовать декларативный подход для построения UI, а не императивный (как минимум, для тех, кто хотел бы уйти от императивного);
      для тех кто будет часто и много думать о декомпозиции приложения и повторном использовании.
      Я думаю, именно это потом оказывается «высоким порогом вхождения», а не количество абстрактных слоев, качество документации и т.п.
  • +5
    вот что плохо в подобных статьях — много слов, мало кода, ДАЙТЕ КОДА, особенно для примеров с плохой производительностью
  • +2
    А есть ли нормальный js фреймворк для построения многостраничного приложения в котором страницу изначально рендерит backend а frontend js потом подхватывает?
    Angular он все же для одностраничных приложений. И если стоит задача связки backend+forntend без API то он вообще не подходит. И сколько я не искал, ничего удобнее для таких целей чем jquery я не встретил. Но jquery это библиотека и она не очень подходит для больших сайтов.
    • 0
      Polymer как вариант. Это не то что бы фреймворк… скорее полифил для web components… но это единственное что подходит к любому многостраничному приложению. А далее идут нюансы и различные юзкейсы которые можно решать отдельными библиотеками типа того же накаута или бэкбона.
    • +1
      Так как на бэкэнде (на сервере) ещё нет никакого DOM, то задача «отрендерить страницу» сводится попросту к задаче «подставить данные в шаблон на сервере», если я правильно понял формулировку задачи.

      На языке JavaScript выбор средств для решения этой задачи — это выбор сервера и движка шаблонов.

      Полагаю, что неплохим выбором является употребление Express в качестве сервера, Handlebars в качестве движка шаблонов (достаточно популярный выбор по данным опросов) и express-handlebars в качестве средства подключения движка шаблонов к серверу.

      (Это простое решение. Если взаимодействие клиента и сервера подразумевается более тесным, чем скачивание страницы, тогда какие-то более навороченные средства применяются.)
    • +2
      На данный момент, этот здравый подход является практически святым граалем веб разработки.

      Это то к чему стремятся сейчас все все веб приложения.
      Mithgol очень толково подсказал что можно уже сегодня легко использовать и пускать в продакшн.

      Для расширения кругозора можно также посмотреть это видео:
      OSCON 2014: How Instagram.com Works; Pete Hunt
  • +4
    Давно присматривался к AngularJS. Но вот после таких публикаций пропадает желание применить его в новом крупном проекте. Испугался типичного сценария, где на первых этапах радость и эфория от новой технологии, а по мере развития проекта снежный ком из граблей и костылей.
    Лучше попробую применить AngularJS в каком нибудь маленьком и некритичном проекте. А серьезный проект буду реализовать по старинке на jQuery, где есть уверенность что абсолютно все проблемы решаемы и не потребуют больших извращений.
    (Может автор и не прав, но мне стало страшно.)
    • –2
      Я думаю несмотря на предвзятость и агрессивность автора статьи, большой проект на jQuery он тоже вряд ли одобрит =)
      Он этот пост написал чтобы попиарить React.js и унизить Angular.js.

      По поему опыту Angular.js в проектах любого уровня хорош, очень легко поддерживается и не требует гуру JS на каждый чих как для React.js. А проекты с jQuery после нескольких килобайт кода превращаются в адское месиво, где непонятно что и откуда вызывается, особенно если в команде есть люди которые не придерживаются code style.

      P.S. Правильное ощущение от Angular.js можно понять только когда через год залазишь в какой-либо проект чтобы что-то допилить и разбираешься в этом за 5 минут + минут за 15 допиливаешь и ты молодец.
      • +1
        Я видел много всякого ангулярного дерьма, которое писалось дилетантами, и которое нереально поддерживать. После рефаторинга и покрытия тестами оно становится в половину легче и в раз 20 шустрее… Для Реакта не нужно быть «гуру JS», просто нужно относится к нему как к шаблонизатору загружающему различные данные, а их контроллеры уже нужно реализовывать отдельно в асинхронных решениях типа Rx.js или highlandjs.
        • 0
          1. Ну когда нужно чуть-чуть поправить вёрстку и надо лезть в JS код, где шаблон описан кодом и при ошибке всё может сломаться, туда простых верстальщиков пускать не надо, а ведь в большинстве компаний не «фронтенд разработчики», а верстальщики, которые с JS совсем «на вы». Про «гуру» я конечно перегнул, но это должен быть человек который умеет программировать настолько чтобы всё не сломать в чужом коде, для этого в нём ещё и разобраться нужно.
          2. Да и уже несколько раз я участвовал в подобных спорах по поводу «пошустрее», никто так и не привёл пример проекта где использование React.js действительно оправдано перед Angular.js. Это нереально субъективная вещь из разряда — почему вы пишите на PHP/Ruby/Python/Perl, если на Java быстрее? Большая часть задач, особенно в web-разработке, не требует мегапроизводительности, и то что больше половины сайтов в мире сделано на wordpress это доказывает.

          А вообще я считаю для каждой из технологий и React.js и Angular.js есть своя ниша и моё мнение что эти ниши не особо-то и пересекаются.
          • +1
            Ко второму пункту:

            Обычно медлительность ангуляра является следствием чрезмерного использование ватчеров. Многие не используют ресолверы для контроллеров и вставляют кастыли на промисах что бы подгрузить данные что так же сказывается на отзывчивость системы. Скажем в том же angular 1.3 был добавлен bindOnce который при обдуманном использовании так же нехило ускоряет отрисовку. Ну и да, непосредственно работа с DOM (если мы говорим о стандартных средствах angularjs а не о кастомных директивах) реализована очень эффективно. По сути единственное преимущество React.js которое я увидел — он заставляет людей думать, что я считаю не плохо. Angular же предоставляет удобный и универсальный но не совсем эффективный метод работы с обновлением view. Это не означает что нельзя использовать более эффективные методы (тот же bindOnce) просто подавляющее большинство разработчиков не парятся особо.

            По сути все сводится к тому что при помощи стандартных средств Angular можно довольно быстро поднять довольно большое приложение а затем уже оптимизировать узкие места. Ровно то же справедливо для проектов на PHP/Riby/Python. Сначала реализуется проект или его версия а затем происходит оптимизация узких мест. В WEB на бэкэнде узкое место это I/O и использовать более быстрые языки программирования (типа Java, D и т.д.) не имеет смысла так как время выполнения кода в большинстве случаев составляет всего 10%-20% от общего времени запроса.

            Конечно если на сервере чиселки считаются то тут имеет смысл взять другую технологию, хотя еще лучше опять же определить узкие места постфактум и затем уже реализовать оные на более эффективных технологиях типа golang/rust/d/c++.

            Так же и в Angular. Скажем у меня в одном из проектов была довольно серьезная проблема с производительностью для построения календариков с событиями и подобными штуками связанная именно с data-binding. Сам календарь изначально был инкапсулирован в директиву так что можно было безболезненно переделать все на ванильный JS максимально оптимизированный под задачу, и с этим дальше жить.

            Увы нет таких инструментов которые позволяют решать задачи эффективно как с точки зрения потребления вычислительных мощностей так и с точки зрения трудозатрат. Обычно перекос идет в одну или другую сторону.
    • +1
      Если умеешь пользоваться гуглом и читать доки — нет проблем.
      Все проблемы в статье решаемы, и связаны с нежеланием автора искать какое-либо решение, а гневно ПОСТИТЬ КАПСОМ, потому что эта технология оказалась для него слишком сложной в освоении.

      Если хочется шустрее чем Angular, Ember или Backbone — пробуй лучше React с rx.js или highlandjs.
      • +1
        Кстати, да. Очень напрягли рассказы о тормозах при сложных интерфейсах и моделях. Обязательно покапаю React.
        • 0
          У меня несколько проектов на ангуляре где есть странички с тысячами объектов, с событиями, всякими выражениями, работает быстро, кстати, там такое количество объектов обусловлено непродуманным UI, потому их и несколько. Производительность вещь крайне субъективная, кто-то коллайдером управляет и каждую миллисекунду учитывает, а кто-то форму обратной связи делает, это только практически выясняется.
          Опять же высокая скорость обычно обозначает больше кода и код более сложный в поддержке. И лично мой опыт говорит о том, что тормозит чаще не от архитектурных проблем, а от кривых рук программистов и там где больше кода эта кривизна явственнее.
  • +1
    По-моему проблемы, описанные вами в статье отчасти уже поднимались на англоязычных ресурсах (как уже заметил один из комментаторов), а отчасти являются вашим субъективным мнением. На самом деле большая часть проблем, поднятых вами действительно существует, но среди них нет ни одной неразрешимой.

    Меня немного удивила позиция по поводу поддержки клиентского кода серверными программистами. Вы считаете, если человек знает Python (например), то он должен разбираться в JS фреймворках и наоборот? Такие утверждения, по своей сути, являются колыбелью быдлокодинга: «Давайте наймём Васю, он знает Python и если что, сможет поддерживать фронтенд часть».

    По поводу серверного рендеринга и т.п: если вам нужен информационный сайт, который будет индексироваться поисковиками, то использование ангуляра было, как вы говорите, непродуманным решением №1. Что касается скорости рендеринга, то я немного не понял: генерируя страницу на стороне сервера, вы просто подставляете параметры в шаблон, рендерит её всё равно браузер. Да, вы можете закешировать страницу, с подставленными в неё значениями, но скорость рендеринга от этого не изменится, вы просто уберете время на процессинг шаблона (что на современных клиентских машинах, пусть даже на мобильных устройствах) занимает сотые доли секунды. Но если хотите и это оптимизировать, можете взглянуть в сторону appcache и кешировать то же самое на стороне клиента, тем самым убрав с сервера часть расходов процессорного времени и памяти.
  • –2
    Во многом поддерживаю автора. Спасибо за статью. Постоянно пытаюсь найти что-либо, чтобы пересесть на это с jQuery, но так и не могу. Одностраничные приложения не пишу, но часто бывают нужны хитрые динамические формы с изменением структуры на лету и подгрузкой попап-диалогов, которые бы влияли на исходную форму, может кто-то что-то посоветует не такое оверинженирное?

    И я охотно верю, что автор пишет 2 года на ангуляре. Я уже 4 года борюсь с симфонией, и тут достаточно недели не работы с кодом, чтобы припомнить все недостатки, с которыми казалось должен был смириться. Эта общая проблема всех переусложненных фреймворков. Либо ты пишешь только на нем без перерывов и привыкаешь, либо же при перерыве или просто дергании редко используемой фичи тут же понимаешь насколько все плохо.
    • 0
      Могли бы вы раскрыть немного свою мысль про «симфонию»? Что именно так плохо, что печалит больше всего. Интересен взгляд со стороны.
      • +1
        Симфония требует тонн бойлерплейта, кучи вещей, которые нужно помнить или лезть в справочник — аннотации к моделям, контроллерам. Бойлерплейт для типов форм, за типами полей и параметрами нужно лезть в справочник. Темизация форм хороша до тех пор пока не нужно прикрутить кривой, но нужный скрипт с гитхаба. Мне мало form_row, мне нужен form_row_password_spellchecked, но я не могу сделать такую функцию темизации чтобы она работала, я максимум могу сделать макрос в Twig, который будет делать что-то похожее по смыслу.

        Расширяемость фактически не пригождается — у меня в проекте 26 форм. Валидаторы в Entity превращаются в тыкву, когда нужно добавить в форму левое поле не связанное с Entity, потому что приходится ставить data_class в null.

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

        Примерно нулевая интеграция фреймворка с клиент-сайдом из коробки. Динамические формы, перегенерируемые на сервере через неудобны до ужаса. Мне проще не создавать форм-тайп для такой формы и делать все вручную на клиенте, чем возиться ЭТИМ. Я считаю, что делать аплоад файлов в коде Entity это идиотизм, я не вижу нормального способа сделать загрузку нескольких файлов так, чтобы поля загрузки добавлялись одно за другим.

        Ассетик — это ад, особенно когда в проекте куча левых скриптов — у меня на машине установка ассетов срабатывает 8-10 секунд. Если пускать выдачу ассетов через AsseticContoller, то получается все равно безумно медленно и неудобно.

        DQL — это зло, хотя 99% проектов обычно не меняют движок базы данных за всю жизнь, вы все равно обязаны использовать этот недоSQL, который позволяет работать с аггрегатными фунциями через седьмую задницу. У меня вообще начинаются проблемы каждый раз когда я отхожу от стандартных случаев, прописанных в документации, потому что чтобы решать проблемы мне приходится плодить сущности и бойлеопрлейт. Но не для решения проблемы, а для того чтобы фреймворк разрешил мне решить проблему.

        Длинные неудобные команды для ассетов, миграций, запуска команд — приходится ко всему делать алисасы на bash или обертки в Makefile/phing.

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

        Документация неудобна. Невозможно держать в голове такой объем информации. А документация по сути учебник, искать в котором неудобно. Мне часто проще сделать криво, чем вспоминать «а как это правильно делается в симфонии», и при этом я получаю гораздо больше удовольствия от написания кода, а выходит быстрее.
        • +2
          Симфония требует тонн бойлерплейта

          Симфони как раз таки избавляет от необходимости писать тонны бойлерплейта. Хотите поспорить? Попишите на Silex что-то средних и больших масштабов. То что нельзя запомнить все эти аннотации и прочие штуки — ну… уж простите. Вопервых самые основные вы так или иначе запомните, а для всего остального есть гугл + автокомплит/сорсы.

          Темизация форм хороша до тех пор пока не нужно прикрутить кривой, но нужный скрипт с гитхаба.

          Вас никто не заставляет использовать Symfony Forms. Более того, никто не заставляет вас писать свой form type для этого.

          Валидаторы в Entity превращаются в тыкву, когда нужно добавить в форму левое поле не связанное с Entity

          Как это так? Откуда у вас вообще такая необходимость возникает? Типа галочки аля I agree и т.д.? Ну так для этого есть виртуальные проперти. Да и опять же, мне кажется тут проблема в целом в постановке задачи.

          Наследуется только один форм-тип от другого.

          И прекрасно. Не вижу проблемы. Если у вас есть общий функционал — есть экстеншены, которые позволяют вам горизонтально расширять ваши форм тайпы.

          мы не можем просто дернуть глобальный контейнер через хак, засмеют.

          Мне кажется вам само то будет Yii или Laravel с его сингелтонами/фасадами. Вы покрываете код тестами? Судя по всему нет или только функциональными/интеграционными (хотя я тоже в основном ими пользуюсь но все же).

          Примерно нулевая интеграция фреймворка с клиент-сайдом из коробки

          Есть такое дело. Проблема уже поднималась. Я полностью согласен с тем что ассетик крайне неудобен в использовании если у вас хоть сколько нибудь серьезный фронтэнд. Потому я лично использую gulp и люди делают штуки типа gassetic (замена assetic на основе gulp). Лайврелоад, инкрементная сборка, сорсмэпы… чудо просто. Правда я пока не решил проблему с элегантным способом инджекта скриптов в темплейты так что частично пока использую assetic для этих целей. Может доберусь и до этого в ближайшем будущем, благо у меня мало проектов с фронтэндом. В основном только REST Api и SPA. Админки я уже давно делаю на angular и получается намного проще.

          DQL — это зло

          Знаете в чем основная плюшка DQL — вы не привязываетесь к структуре базы. Только доменная модель имеет значение. Только поля ваших объектов. Возможно движек базы данных вы и не меняете, но за жизнь проекта может поменяться структура базы и не один раз (наследование таблиц, переименование полей тоже случается и тд.). Вы видимо не осознаете преимущества DQL перед работой напрямую с SQL. И на самом деле довольно сложно ее осознать… это можно сделать только если у вас отберут эти плюшки. Скажем в Doctrine ODM для монги нет привязки полей объектов в DQL и вы должны оперировать именно именами полей документов… что ужасно неудобно.

          Длинные неудобные команды для ассетов, миграций, запуска команд

          Как вы верно заметили… автоматизация наше все. Пусть все эти длинные команды дергают сборщики и средства автоматизации деплоймента.

          Симфония это просто квинэссенция идеи делать простые вещи максимально сложным способом.

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

          Резюмирую. Если я правильно понимаю, у вас не такой большой опыт работы с этим фреймворком (как минимум мало проектов на нем, если я правильно понимаю вообще только один проект на нем). Возможно для ваших задач он является оверхэдом. Что поделать. Подозреваю что под ваши задачи идеально подходит Laravel за счет более простой реализации и меньшего упарывания по всем этим DDD/BDD/TDD/Countinuous Integration and delivery которые вам нафиг не сдались.
          • 0
            Я рад, что вам нравится симфония. Позвольте же и другим не любить ее.
            • 0
              Ну… из вашего комментария я сделал вывод что вам не нравится конкретно symfony/forms и assetic. Прелесть симфони в том, что это всего-лишь набор компонентов и не более. И использовать что-то из этого или нет решать вам. Скажем вы могли вместо symfony/forms сделать свой мэппер объектов на формы и обратно, или воспользоваться другими реализациями форм билдеров, альтернативы ассетика тоже есть.
              • 0
                Я писал не только про формы и assetic. Если вы не считаете это проблемами, то вы счастливый человек. Пишите и наслаждайтесь.
  • 0
    Нужно все писать на Vanilla.js! Меня жутко бесят те 3-4 страничные приложения с 5-10 попап окнами которые сначала загружаются пол века, а после еще и жрут процессорное время своим рендерингом. Используйте пререндер на сервере и вставляйте кусками, как это сделал ВК.com.
    Прежде чем тыкать на минус, тыкните меня носом в сайт, который использует React, Angular, Backbone, Ember и который так же быстр, как ВК.com.
    • +5
      Фреймворки изначально задумывались не для того чтобы все быстрее работало (это понятно, что медленнее будет). А для того, чтобы сам процесс разработки шел быстрее.
      • +2
        Ладно, если мы разрабатываем хорошо масштабируемое серверное приложение, можно спокойно пожертвовать скоростью работы ради скорости разработки — докупим серверов и все будет отлично, железо дешевле программистов.
        Ладно, если мы разрабатываем внутрикорпоративное приложение — оборудование под нашим контролем, всегда можно посмотреть у кого/почему тормозит, сделать небольшую оптимизацию, когда нужно.
        Но когда речь заходит о веб, когда оборудование не под контролем, связь не под контролем, а «лишние» 10% пользователей могут принести дохода на 100 программистов — вот тут вопрос производительности встает в один ряд со скоростью разработки, и просто так жертвовать одним ради другого нельзя. Для прототипа/первой версии можно использовать фреймворки, но для полноценного приложения нужно что-то более специализированное.
    • +5
      Ну да… писать все на ванильном JS. Все с нуля. Даже если не учитывать тот факт, что среднестатистический фронтэндер без этих всяких реактов/бэкбонов и прочего сделает вам неподдерживаемую кучу гуано, которая будет жрать побольше (даже с учетом пререндринга на сервере) чем все эти ангуляры и реакты вместе взятые, подобным решением на ранних этапах жизни проекта мы сознательно увеличиваем риски, сроки разработки и соответственно стоимость заложенную в разработку. Причем это мы еще не знаем выстрелит проект или нет. Просто так. Потому что так делают в ВК. То есть если рассматривать вопрос с точки зрения продукт оунера, не думаю что вы бы остались довольны таким подходом к разработке.

      С другой стороны… Можно реализовать проект на Angular/Ember/whatever, а затем заниматься оптимизациями и т.д. и как только мы поймем что проект не мертв и дает прибыль, вот тогда можно нанять армию фронтэндеров которые будут постепенно оптимизировать все и в конечном счете все придет к ванильному JS, с пререндрингом (хотя это не пререндринг, это препроцессинг шаблонов и только, разбирать все это добро в DOM и отрисовывать всеравно придется браузеру и тут уже больше влияет верстка и взаимодействие с DOM) и чем хотите.

      Еще все забывают что верстка сама по себе может добавить лагов. Один лишний box-shadow на сложном бэкграунде и лаги при скроле на слабых девайсах вам обеспечены. А если еще поделка на ваниле будет постоянно reflow страницы вызывать то взвыть можно.

      Как по мне не стоит вообще ориентироваться на начальных этапах на проекты из ТОП100 просто потому что вы так хотите. Лучше дешевле и быстрее выпустить продукт на рынок и затем уже заниматься плюшками.

      Вспомните VK лет 5-7 назад. Он был намного менее сложный в плане реализации фронтэнда.
      • 0
        Он не был SinglePage!
        • 0
          вроде 5 лет назад закос в эту сторону уже был… не помню… помню разбирался как там это все реализовано и помню что сделано все было очень просто и влоб.
    • 0
      Можно попробовать потыкать вас носом в проекты гугла. Там не то, что angular, там gwt найти можно.
      • 0
        Gmail и Youtube не так быстро загружаются. Все что быстро прилетает статика
        • 0
          Ну если у вас gprs может и медленно. JS не плохо кэшируется и выдается с кэша браузера.
          Не вижу проблем с angular в этом смысле, я думаю у вас вряд ли получится написать лучше, чем написано там.
          Кстати у гугла не только gmail и youtube
  • –1
    Было бы неплохо в статье все примеры сделать в сравнении с ReactJS, раз уж вы его так горячо рекомендуете. Сейчас ознакамливаюсь с документацией React — на первый взглядт те же яйца, что из Angular. Так же куча каких-то методов: getInitialState, getDefaultProps и т.д.
  • +1
    Во вторых серверные разработчики вообще не будут понимать, что творится на front-end'е и не смогут читать код.
    Это многое объясняет. Если автор работает в окружении таких дубов, не удивительно, что и сам сделался ретроградом. У нас серверные разработчики за пару месяцев не просто вникли в Ангуляр, но и стали на нем полноценно писать и брать фронтендские задачи (c jQuery, backbone и проч. такого не получалось)
    • 0
      Angular как раз с прицелом на серверных разработчиков и пишется во многом. Они привыкли, что должен быть DI — вот им DI. Они привыкли, что внешние источники данных в тестах заменяются на Мокки — вот им мокки. И т.д. Все сдобрено словами Google и Enterprise — и все: орда джавистов, дотнетчиков и питонистов записывается в ваши поклонники!

      Они и хорошо — гораздо лучше, когда люди из фронтенда лучше понимают бекенд, а люди из бекенда — фронтенд. Так и общий язык найти проще, и задачи быстрее выполнять.
  • 0
    Соглашусь с мыслью о том, что в Angular приходится решать много проблем, которые создает сам Angular. Тем не менее, применять его в больших проектах можно. Возможно, ошибка в проекте автора в том, что Angular пытаются применять не как SPA-фреймворк.
    Конкретные перечисленные пункты не совсем корректны. Документация не такая плохая, минификация кода- это просто отдельная задача, структурно не относящаяся к проблемам фреймворка, разработчиков на Angular наоборот стало слишком много. Предложение не наследовать скоупы может принести столько же проблем, сколько решит.

    Интересно другое — сравнение ресурсов разработки в Angular и не Angular проектах на запуск/поддержку/расширение. Предлагаю product owner'ам поделиться своими впечатлениями, в новых статьях. Как раз сейчас Angular стал стандартом выбора для многих молодых проектов, и информация для оценки всех стадий развития может быть полезной.
  • +3
    Во вторых серверные разработчики вообще не будут понимать, что творится на front-end'е и не смогут читать код.


    Так можно сказать и про любой другой фреймворк. Для того чтобы понимать, что творится — нужно разбираться и не важно angular это или к примеру jsf, primefaces…
  • 0
    Angular, при всех его проблемах — просто-напросто более-менее юзабелен, и позволяет быстро писать красивый UI, в отличие от тонн jQuery-ада или вороха несовместимых между собой наколеночных фреймворков.
  • 0
    Раз статья вызвала такой ажиотаж, значит кому-то она оказалось полезной, или хотя бы интересной. Я учел комментарии, переработал некоторые моменты статьи, что бы более четко выразить свою позицию и охватить все аспекты. Спасибо всем критикующим, вы мне помогли сформировать более полное мнение об ангуляре и действительно подкорректировали мою позицию.
    • +3
      В вашем новом PS слишком много «я не хочу думать», в принципе это коче-что объясняет.

      Я хочу думать о бизнесс-логике и о том какие задачи мне нужно решить по факту, но я не хочу думать о бессмысленных суррогатных коцептах

      Вы тут либо лукавите, либо решили опять пострадать популизмом. Концепты бессмысленны для тех, кто не задумывался о смысле. Но разберем попунктно.

      наследовании скопов

      Это нужно в первую очередь для шаблонов, который являются базисом декларативной сущности AngularJS. Если вы хотите вместо декларативного интерфейса все создавать императивно из js-кода, то вы явно неверно выбрали инструмент. Может именно поэтому у вас так много батхерта.

      Если вы опираетесь в своей логике на наследование скопов, то такую логику становиться крайне сложно тестировать (нужно инициализировать еще состояние родительского контроллера).


      Вы никогда не задумывались, зачем было создано TDD? Если вам что-то сложно тестировать, это первый признак того, что вы что-то делаете не так. Если вместо того, чтобы подумать что и почему вы делаете не так, вы упорно наступаете на одни и теже грабли, а потом кричите о своей боли, то, конечно, определенная вина фреймворка в этом есть. Он дал вам слишком много свободы, правда при этом он дал вам инструменты для оценки того, что вы делаете (я про тесты и TDD), но вы, судя по-всему, не хотите ими пользоваться.

      когда нужно использовать односторонний или двусторонний дата-биндинг

      я не хочу решать проблемы производительности

      Ангуляр даже накладывает ограничения на то насколько богатый UI можно писать. И что самое интересное, это не какое-то эфемерное и далекое ограничение в которое вы никогда не упретесь. Это всего лишь 2000 биндингов, и если вы разрабатываете более-менее большое приложение, ТО ВЫ ТОЧНО УПРЕТЕСЬ В ЭТО ОГРАНИЧЕНИЕ.

      Тут есть два аспекта.
      Почему был выбран dirty checking и как обстоят дела с альтернативами.
      Так вот, не хотите dirty-checking, придется иметь дело с «change listeners». Вам ближе второй подход? Нафига вы выбрали AngularJS, чтобы потом громко и так популистски кричать?

      Второй аспект UX: 2000 биндингов — это 2000 элементов на странице, которые могут постоянно автоматически обновляться. Хм, не кажется, что с этим что-то не то? Как с количеством элементов (как у вас обстоят дела с проектированием UX?), так и с тем что все обязательно должно автоматически обновляться (это к вопросу, зачем нужен односторонний). Смотрите ка, я не совсем-то и в специфических терминах AngularJS рассуждаю, а в общем о подходе к построению UI. Вы не хотите об этом думать? Не уверен, что это что-то говорит о самом AngularJS.

      когда нужно использовать compile, link, controller

      Вы не хотите думать об инкапсулировании поведения в директивы. Бывают визуальные компоненты, бывают валидаторы, бывает повторно используемое поведение (всякие show/more и т.п.), которое можно один раз выделить, один раз протестировать и потом повторно использовать. У директив очень много аспектов применения. На этом держится львиная часть AngularJS. Но вы не хотите думать обо всех аспектах, проще голословно заявить «ЭТА СЛОЖНОСТЬ НЕ НЕСЕТ НИКАКОЙ ПОЛЬЗЫ. Нету логических причин разделять логику на 3 метода (compile, link, controller), все это можно легко реализовать в одном методе.» Успехов в реализации всего многообразия usecase-ов для директив с помощью одного метода.

      когда мне нужно использовать value или constant, provider или factory

      я не хочу думать о том, зачем нужны Provider для каждой внедряемой сущности и не хочу знать ничего о run и config фазах

      Вам не нужна гибкость в настройке поведения вашего приложения в зависимости от определенных факторов (простейший пример, production/sandbox/beta)? Вам дали инструмент, как подобное делается легко и единообразно в рамках AngularJS. Оно вам не нужно? Ну не нужно, не задумывайтесь, используйте просто factory, если вам его хватает.

      я не хочу думать о том, что делать когда я хочу интегировать натинвые события события в мир ангуляр

      Это к вопросу подходов, если вам data-binding на dirty-checking вместе с декларативным подходом к UI не нужен, а хочется простого императивного подхода и change listeners, нафига вы выбрали AngularJS?

      я не хочу думать о том увидел ли пользователь {{ скобочки }}

      Разработчики прошли очень немаленький путь в сокращеннии необходимости написания boilerplate кода (алиасы к объявлению сервисов тоже к этому относятся), повышению читабильности и декларативности. К сожалению, иногда это приводит к тому, что люди не хотят задумываться о причинах добавления тех или иных фич, а думают только о своем одном уютненьком случае использования. Что наталкивает их на мысль, что все можно было сделать проще и не так.
      Есть ng-bind. Если вместо скобочек всегда использовать его, то пользователь не увидит скобочки. И тут вам дали вариант выбора, где не надо, чтобы видели скобочки, используйте ng-bind или ng-cloak, а там где скобочки сразу не будут видны точно, то для читабельности можно и {{ }} заюзать (и таких случаев будет большинство, по-крайней мере в SPA и тут у меня потихоньку начинает появляться ощущение, что вы не SPA пишете). Но это же уже надо думать, что, где и когда применить — слишком сложно.

      ГОСПОДИ, АНГУЛЯР ОТПУСТИ, ВЕДЬ Я НЕ В ЧЕМ НЕ ВИНОВАТ, ДАЙ МНЕ ПОЖАЛУЙСТА ПО ПРОГРАММИРОВАТЬ, МНЕ ЭТО НРАВИТСЯ.

      Что, прям-таки пришел злой Angular, приковал вас и не хочет отпускать? Или вы его сами выбрали зачем-то?
      • +1
        Любая табличка с живыми данными (яркие примеры — эксельчик, календарь с расписаниями) и вы легко преодолеваете порог в 2000 элементов. Особенно, если монитор большой и позволяет показать сразу много данных без скроллинга.
        • 0
          Угу, и если большая часть вашего приложения такая, то надо грамотно выбрать инструмент, и в этом случае это, с большой вероятностью, будет не AngularJS. Если это одно состояние из сотен, а в остальном сильно хочется AngularJS, то с одной такой страничкой вы без проблем справитесь. Никто же не имеет ничего против того, что есть разные подходы и у каждого есть свои преимущества и недостатки. Но сравнение подходов — это не про эту статью.

          И чтобы в одном месяце календаря получилось 2000 живых элементов, надо не менее 60 в каждой ячейке. Поэтому по поводу легкости преодолевания у меня пока все же некоторые сомнения.
          • 0
            С большой вероятностью AngularJS будет выбран потому, что миллион обезьян не может ошибаться, а по началу данных совсем не много. Со временем архитектурные просчёты выбранного фреймворка начинают все сильнее и сильнее бить по рукам. Но к тому моменту уже поздно что-то менять — написано куча кода, не отделимого от фреймворка. И приходится либо дальше мириться с ограничениями, либо всё полностью переписывать. Над архитектурой приложения нужно думать сразу и не полагаться на то, что «2000 жлементов хватит каждому».

            В календаре далеко не один месяц. А в дне, далеко не один час.
            • +1
              В календаре далеко не один месяц. А в дне, далеко не один час.


              И это тут случай, когда мы возвращаемся к проектированию UX. А также к вопросу «крайний случай» vs «обыкновенный случай». Никто не спорит, что на страницу можно вывести очень много, только зачем? Чтобы у пользователя глаза в кучку собрались? Или чтобы показать «архитектурные просчеты» фреймворка, которые на самом деле являются осознанным выбором и не скрываются ни от кого?

              С большой вероятностью AngularJS будет выбран потому, что миллион обезьян не может ошибаться

              Ничего глупее нельзя представить. Тем более, что еще неизвестно, у каких фреймворков армии обезьян больше :)
              • +1
                А давайте UX всё же будут заниматься специально обученные UX-еры, а не создатели JS-фреймворка?

                Вы тут шутки шутите, а каждый второй проект сейчас начинается на AngularJS отнюдь не по причине его технологического совершенства.
                • +1
                  А давайте UX всё же будут заниматься специально обученные UX-еры, а не создатели JS-фреймворка?

                  UX конкретного проекта будут проектировать не создатели фреймворка по определению. А вот почему создатели фронтенд-фреймворка не должны задумываться о принципах построения UI, я не понимаю. Кроме того, UX — это только часть того, о чем я говорил.

                  Вы тут шутки шутите, а каждый второй проект сейчас начинается на AngularJS отнюдь не по причине его технологического совершенства.

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

                  Кроме того, я не знаю, что такое «технологическое совершенство». Я знаю, что у каждого инструмента есть своя область применения. Если при выборе инструмента никак не учитываются его ограничения, то при чем тут фреймворк?

                  Со временем архитектурные просчёты выбранного фреймворка начинают все сильнее и сильнее бить по рукам. Но к тому моменту уже поздно что-то менять — написано куча кода, не отделимого от фреймворка.

                  Даже уперевшись в 2000 биндингов (кстати, не факт, что эта цифра на данный момент именно такая, все же AngularJS развивается и оптимизируется), в небольшом количестве мест — это решается, причем изменения легко локализуются, тестируются и т.п. Если оно по-всему приложению так, то тут уж как ни крути, либо надо признать, что инструмент выбран неправильно и переписать. Либо вариант с кривыми руками тоже никто не отменял. С абстрактными рассказами про проблемы с производительностью никогда не поймешь, а точно ли причина там, где описывают.
        • +3
          О чём вы вообще говорите?

          2000 это не жёсткий лимит где-то внутри ангуляра, а один из разработчиков однажды сказал что не очень разумно показывать юзеру больше 2000 элементов одновременно на экране, а потом его уже как только не перефразировали.
          Хотите больше элементов — да добавляйте, ей богу.

          Я писал уже что у меня есть проекты где отображаются тысячи элементов и ничего не тормозит, потому что я знаю что такое bind-once, как прятать методы от $scope и другие особенности.
          • +1
            ещё добавлю:
            тем более это может замедлять когда много элементов внутри одного scope (и это не постоянно тормозит, а при выполнении каких-то действий и/или изменении данных), то есть если грамотно использовать директивы и/или контроллеры + отключать двойной биндинг где не надо (а он на самом деле в большинстве мест не нужен вообще), то никаких проблем вообще нет, будь у вас хоть десятки тысяч элементов.

            Опять же все рассуждают про тысячи элементов, а привести пример навскидку сможете любого сайта, где несколько тысяч однообразных элементов выводятся? Я вот лично затрудняюсь, но зато раздули из мухи слона…
          • +1
            и ещё добавлю:
            я переделывал на ангуляр в одном проекте 2 отчёта, где выводились десятки и сотни тысяч DOM элементов, там странички весили 2-50 мегабайт, так вот при таком количестве DOM элементов браузеры сжирали всю память и умирали в страшных муках, то есть с некоторыми данными отчёты вообще не могли отобразиться. Сначала сделал с ленивой подгрузкой и фильтром и всё залетало, потому что все эти данные стали отображаться частями, потом переделал на пагинацию, потому что была необходимость посмотреть в конце выбранных данных.
            • –1
              1. Выбираешь медленный фреймворк
              2. Пишешь пагинацию и ленивую загрузку, что бы фреймворк не тормозил
              3.…
              4. PROFIT!

              Можно было сразу выбрать что-то, что не тормозит и не насиловать себя.
              • +3
                Причем тут фреймворк если браузер сам по себе умирает при отображении DOM в 100К нод.
                • 0
                  Не знаю, в 2005-м IE 5.0 не умирал при рендеринге всего списка БИК.

                  А в 2014 новомодный браузер от корпорации добра умирает.
                  • 0
                    Полный список БИК это статическая таблица где-нибудь в 10K строк или меньше, нет?

                    А теперь добавьте к этому постоянные reflow/repaint страницы вызванные изменением данных в ней (речь же шла о постоянных изменениях данных и их отображении).
                    • 0
                      нет, это 25 мегабайт чистого текста, без разметки. Разметка туда вставляется автоматически, примерно утраивая объём.
              • +3
                Как можно говорить «медленный», если нет кода? ЛЮБОЙ фреймворк медленнее native кода, любой native код медленнее оптимизированного native кода. Вы пишете на asm.js? Конечно же нет. Почему во всём мире уже почти не пишут на ассемблере? Почему по улицам не ездят на болиде «формула 1»? Скорость это далеко не самое важное, в программировании важно быстро писать работающий код (и тут то что вы записали в минус про то что неиницилизированные переменные не выбрасывают исключений превращается в плюс) + код должен быть легко расширяемым (тут декларативность ангуляра вне сравнений вообще, я тут уже писал что через месяцы я открываю код и быстро его меняю под новые требования) + надёжность/тестируемость (да, код должен быть надёжным и тут у ангуляра тоже всё в порядке).

                У ангуляра нет проблем со скоростью, есть проблемы с руками у программистов, но эти проблемы никаким фреймворком не исправить, я видел сайты где backbone тормозил, хотя он очень лёгкий. Потому предлагаю скинуть код сайта где реально медленно работает и разобраться тормозит сам фреймворк или у программиста рак мозга.
  • +4
    Добавил React.js в местный «хабра-бенчмарк», в этом тесте он себя не важно показывает.

    Это всего лишь 2000 биндингов
    На jsperf есть тест скорости обработки $watch примитивов для Angular — на моем ноутбуке, Chrome обрабатывает 11М $watch'ей в секунду (1ops = 10k watch), поэтому проблем с 2000 биндингов быть не должно, чаще производительность будет упираться в DOM — а это проблема вне зависимости от фреймворка.
    • 0
      В хабра-бенчмарке надо бы до последнего 1.3 обновить, он получше в плане производительности, что впрочем видно и на jsperf.
    • 0
      Я немного поправил ваш пример для React.js, сравните ещё раз. На самом деле, я думаю можно ещё быстрее + было бы неплохо привести какой-нибудь более «толстый» пример (чтобы показать разницу в обновлении данных)
      • 0
        Ваш пример не учитывает время рендеринга — callback вызывается сразу, а не через setTimeout как во всех остальных примерах.
        Тогда для справедливости нужно аналогично переделать все тесты, а некоторые фреймворки не будет возможности протестировать, например Knockout.js часть процесса «откладывает» через setTimeout и без таймера не замерить весь процесс.
        • 0
          А зачем в бенчмарке, в update(), render()? Оно же два раза будет перерисовывать. Хотя, похоже, на результат оно не сильно влияет.
          • +1
            Почему два раза?
            Главное что-бы сравнивалось одинаковое — для одних фреймворков учитывается время рендеринга, значит и для других должно быть так же.
            Так же там есть чекбокс «Take into account rendering time», который скрывает отрисовку.
        • +1
          Согласен, был неправ по поводу setTimeout(callback, 0) -> callback.call(null), однако поменяв этот кусок обратно, и просто убрав jQuery (который там вообще ни туда, ни суда, т.к. React в дефолтной конфигурации никак не зависит от него), у меня всё равно получается у ангуляра 3321мс на filling и 747мс на update для 10000 на раб. машине против 1589мс на filling и 727мс на update у React. И кстати, имеет смысл сравнивать не только время, но и размер памяти, выделяемый при этом сравнении. У меня angular съедает на 50% памяти больше (37,8Мб у React против 57.1Мб у Angular).

          Выводы из этого сравнения:
          В рамках тестирования на моей рабочей машине
          — angular медленнее в первоначальном рендеринге данных на 100%
          — angular и react одинаковы в скорости обновления этих данных
          — angular съедает на 50% больше памяти, чем React

          В заключение хочу сказать, что если бы часть данных оставалась такой же (т.е. не изменялась бы при операции update), то React показал бы более производительный результат за счёт своего diff-алгоритма.
      • +1
        Ну раз такая пьянка, то давайте еще уберем влияние jQuery на Angular (если Angular найдет jQuery он будет использовать его вместо jqLite).

        На моем ноуте результаты примерно такие, с jQuery — filling ~ 960ms, update ~ 140ms. Без jQuery — filling ~500ms, update ~ 140ms. Для сравнение react в вашей версии теста выдает у меня ~ 520 при заполнении и ~ 130 на обновлении.
        • +1
          Хорошее замечание, поправил тест.
          Теперь у меня в Chrome, Angular.js быстрее чем React.js по обеим полям.
        • 0
          Только, чтобы никого не смущать, надо внести правки, о которых указал lega в код React. Я сделал это тут. Действительно, angular выигрывает в производительности на этом тесте. Но было бы неплохо приблизить тест к реальным условиям, а именно:
          — Добавить условие при обновлении (например, обновлять только чётные строки)
          — Изменить дописывание в <li> на что-то более, например на <li><span class="first">{{ first }}</span></li> при заполнении и на <li><span class="first">{{ first }}</span>, <span class="second">{{ second }}</span></li> после обновления
          — Удалять часть DOM-элементов (например, кратных 3)
          — Добавить обработчики на <li> элементы

          Лично мне было бы интересно сравнить выбранные библиотеки/фремворки на таком бенче, как считаете?
          • +2
            как считаете?
            Да, мне тоже интересно, но как минимум этот тест ломать не стоит. Для начала, сделал «набросок» с добавлением DOM.
            Тут у меня Angular.js быстрее в «update» для Chrome и Firefox, а React.js в Firefox быстрее по «filling», добавление DOM примерно одинаково.

            По хорошему нужно добавлять разные тесты, а по текущим результатам можно сказать, что переход на React.js из-за скорости — не имеет смысла (нужны другие причины), тем более что узкие места в Angular.js можно переписать на vanilla JS который имеет наибольшую производительность.
            • 0
              Добавил свою старую либу: plnkr.co/edit/l6Rmz6VeydPjISIBAezZ?p=preview
              Первичная инициализация довольно медленная (создаётся 100500 реактивных переменных с замыканиями, что даёт большую нагрузку на GC), зато потом все шустро — изменения применяются хирургически.
    • +1
      Бестолковый тест. Он фактически измеряет скорость доступа к 3 полям объектов. Конечно это плёвая операция. В реальном приложении $digest будет пропорционален объёму наблюдаемых данных, а их может быть чуть менее, чем дофига. Например, в последнем разрабатываемом мною приложении нужно было следить за данными порядка 50000 значений. Кроме того, $digest повторяется от 2 до 10 раз. Так что 11M можно смело делить на 100K и в результате получить жалкие 110 dps. И это только для того, чтобы узнать «а не изменилось ли чо», без какой-либо полезной нагрузки.
      • +1
        Мне кажется что реализовывать отслеживание 50000 объектов через dirty-checking это как-то слишком в лоб. Я слабо представляю зачем вообще это нужно делать. У вас все 50000 объектов могли измениться в любое время и нужно было на это как-то реагировать? Не могли бы вы конкретизировать пример.
        • 0
          Именно так. Есть список на несколько тысяч элементов, сгруппированный и отсортированный по некоторым правилам. В любой момент модели могли поменяться, от чего требовалась бы пересортировка списка.

          • 0
            Просто если все это происходит из UI то все 50000 одновременно поменяться не могут. 50000 элементов все же тоже не особо шустро отрисовываться будут.

            Короче я просто думаю что если у вас настолько специфичные задачи — расчитывать что стандартные решения справятся с ними так же как и со всем остальным как-то наивно.
            • –1
              Одновременно не могут. Но чтобы узнать что поменялось нужно несколько раз прогнать $digest.
              Отрисовывалось разумеется только то, что попадает в видимую область, а вот чтобы узнать что попадает в эту область и нужно провести пересортировку.

              Именно поэтому Angular не годится для написания контроллеров — только для вьюх и годится. Но на этом поприще его уделывает тот же React.
              • –1
                Но чтобы узнать что поменялось нужно несколько раз прогнать $digest.
                Но на этом поприще его уделывает тот же React.
                А вот и нет, в Angular нужно всего лишь прогнать $digest, когда в React.js нужно заново построить целый virtual-DOM (в render), после чего который пойдет в diff-обработчик — это значительно медленней.
                Вот вам тест где это видно (второй тест update не производит модификаций), в итоге на этом тесте Angular работает в 20 — 25 раз быстрее чем React.js
                • +1
                  это вы фантазируете. А у нас банальная смена ангуляра на реакт помогла решить эту задачу в лоб, без специфичных решений.
                  • +1
                    Ну наверное для подобных задач react.js и подходит лучше, но это крайне нетипичная задача и говорить что «Именно поэтому Angular не годится для написания контроллеров — только для вьюх и годится» как-то непрофессионально, я вот оперирую большим количеством данных и с отображением такого количества объектов в интерфейсе не встречаюсь.

                    P.S. что у вас за задача-то такая можно посмотреть?
                  • +1
                    А не думали не менять а добавить реакт? Или нормально ватчеры сделать? Профит реакта как по мне в том что он заставляет думать а не писать что-то типа $scope.watch(object, fn, true).
                    • +1
                      Вот за «нормально ватчеры сделать» в частности от ангуляра и отказались.

                      Как только его начинаешь оптимизировать, что бы он шевелился, он превращается в обычный jquery.
                      • 0
                        Ну да… обычный такой jQuery… где все изолировано и все можно покрыть тестами. Я не представляю как можно убить все предоставляемые ангуляром фичи «оптимизациями ватчеров». Вот честно…
              • +1
                Именно поэтому Angular не годится для написания контроллеров — только для вьюх и годится.


                У вас $watch(..., ..., true) в контроллере на огромный объект или массив?
                • 0
                  А как же ещё?
                  • 0
                    При передачи третим аргументом true angular при изменении объекта копирует его целиком и затем рекурсивно сравнивает на каждый $digest цикл с текущим значением. Так что сложность цикла $digest увеличивается на порядок, особенно если меняется только одно свойство из десятков тысяч. Можно разделить объект на кучу мелких например и трекать отдельные свойства.

                    Скажем так, 50000 маленьких ватчеров которые будут трекать значения работать будет быстрее чем один по описанной выше схеме. Так же можно эти 50К ватчеров рассовать по маленьким скоупам и вместо жирного $apply делать им $digest.
                  • +1
                    Убить производительность? Ну можно не только количеством или размером наблюдаемого объекта, но и тяжелыми операциями в watchExpression или listenerFn. Да мало ли способов можно придумать.
        • 0
          У меня похожая ситуация. Список из 700 потоков в интерфейсе видеостримингового сервера.

          у каждого стрима порядка 20 свойств, которые меняются во времени. Ангуляр такое вообще прожевать не смог, переделали на реакт, летает пулей.
          • +2
            И как человек может одновременно смотреть эти 700 потоков?
            • +1
              Элементарно. Админ анализирует состояние системы.
          • +1
            А что означает «прожевать не смог»?
            jsfiddle.net/49d84pjq/

            Как и с какой периодичностью изменения моделей происходили?
            Вы вообще определили, где затык то был?
            • 0
              Раз в секунду обновлялась статистика по потокам. Затык в ангуляре. Где конкретно — не скажу, не смогли померять.
              • 0
                А что означает «прожевать не смог»?

                Вис на обновлении? 700 запросов к серверу единомоментно слали? Отвисал в конце концов?
                • 0
                  страница не может отрендериться. Запрос к серверу один, рисуются его результаты.

                  Отвиснуть оно не может, потому что раз в секунду запросы шлются.
                  • +1
                    На основании нижепроведенных исследований, вполне возможно, что вашу проблему мог бы решить track by :-/

                    В этом случае у вас висло все из-за постоянного удаления/добавления большого количества DOM-а. У вас не обновлялись, а пересоздавались элементы.
                    • 0
                      вполне возможно. Но мы уже переписываем на реакт и довольны =)
                    • 0
                      на самом деле скорость была не единственным критичным моментом. Второй момент — ангуляр очень сильно подталкивает к скрытой связности и полуглобальным переменным. Не очень хочется.
                      • 0
                        Это как же? Какие такие «полуглобальные переменные»?