Elizaveta Borisova
JS development
Published in
3 min readAug 11, 2014

--

Как не надо писать код на Angular

Angular.js не терпит грубого обращения. Прежде, чем начать использовать фреймворк в своих проектах, нужно настроиться на его волну и понять тонкую архитектуру. В этой заметке я расскажу, что особенно плохо сочетается с идеологией Angular.

  1. Манипулирование элементами DOM в контроллерах.

Многие из вас работали раньше с проектами на jQuery или Backbone, отсюда проистекает тяга изменять внешний вид объектов внутри кода, обращаясь напрямую к свойствам. Например, так:

var a = $( ‘button.a’ ),
b = $( ‘input[data-role="b"]’ ),
b2 = $( ‘div.status’ ),
flag = true;
some.click( function () {
if ( flag ) {
b.hide();
b2.addClass( 'done' );
}
} );

Такой код обычно даст ожидаемый результат, но является стойким анти-паттерном. Смысл Angular заключается как раз в четком разделении представления и бизнес-логики. HTML является представлением, включая структуру элементов и их стили, контроллер же должен отвечать только за поведение. И ничего больше. Он ничего не знает о DOM, CSS-классах и логики обработки событий. В идеале, в контроллере не должно быть обращений к $ или angular.element. Контроллер просто прикрепляет методы к scope, которые затем привязываются к конкретным элементам DOM, c помощью директив (ng-click и тп)

Разделение представления и поведения в Angular существенно облегчит написание unit-тестов ( не потребуется писать тесты для view, проверяющие бизнес-логику).

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

2. Слишком сложная логика контроллеров

Иногда код в контроллере становится очень запутанным не из-за прямых обращений к DOM, а из-за многочисленных функций в контроллере. Это Тоже очень плохо с точки зрения тестирования: число тестов растет экспоненциально с каждой новой фичей. Это также значит, что легко пропустить много граничных значений. А каждое изменение кода будет нетривиальной задачей.

Если контроллеры слишком перегружены, стоит рассмотреть выделение под-контроллеров. И вообще придерживаться правила одного функционала на контроллер.

Пример такого решения https://github.com/angular-ui/ui-router/wiki/Nested-States-%26-Nested-Views

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

Часть логики также можно делегировать сервисам.

3. Отсутствие очистки использованных объектов

Контроллеры часто используют сервисы, такие как $interval (для привязки к времени). Необходимо помнить, что объекты сервисов живут также долго, каки все приложение, а время жизни контроллеров ограничено в общем случае.

Таким образом, когда Angular очищает в памяти объект контроллера, он оставляет все объекты-зависимости. Например, если вы установили таймер в одном из контроллеров, он продолжит “работать” после завершения работы контроллера. Это классика жанра не только для трудно устранимых багов, но и утечек памяти.

4. Засорение $rootScope

Побочный эффект от разделения контроллеров на подконтроллеры — это необходимость решать проблему взаимодействия между ними. И самый простой “способ” решить эту проблему — вынос данных и методов в $rootScope.

Чем это плохо? Когда число объектов и контроллеров, манипулирующих данными в rootScope возрастает, отладка становится невыносимой.

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

--

--

Elizaveta Borisova
JS development

Как построить маленький IT-бизнес. Заметки о разработке, менеджменте проектов и продуктов.