Comments 37
Я недавно начал использовать Angular, зачастую пишу на CoffeeScript так:

angular.module('my-app.models').factory 'MyModel', ->
  class MyModel
    name: null
    setName: (@name) ->
    getName: -> @name


Имеет ли такой подход право на жизнь, или лучше заменить фабрикой, без прямого достпа к модели?
Интуиция мне подсказывает, что вы хотите нечто вроде Resource: http://docs.angularjs.org/api/ngResource.$resource
А если для тестирования локально, то HttpBackend: http://docs.angularjs.org/api/ngMockE2E.$httpBackend

А, вообще, подход, конечно, имеет право на жизнь. Но мне кажется он концептуально не в духе Angular. Энгьюла все-таки сделан не в духе ООП, который нам пытается подсовывать Кофискрипт.
Немного уточню: модель здесь в первую очередь реализует бизнес-логику, она не обязательно обменивается данными с сервером напрямую.
Имеет ли такой подход право на жизнь, или лучше заменить фабрикой, без прямого достпа к модели?

Как душе удобно.

Насчёт моделей в целом:
Я реализовывал нормальную модель, которая наследовалась от Model, которая в свою очередь имела 2 реализации: серверная и клиентская. Клиентская отправляла данные на сервер, серверная — формировала sql запрос и отправляла запрос бд. Валидация моделей осуществлялась через фильтры, таким образом разработка клиент-сервер приложения сильно упростилась — данные на сервере валидировались прозрачно.
На мой взгляд, тут не везде правильно расставлены акценты.
Constant не означает, что ее нельзя изменять. Особенность константы, что ее можно использовать на config стадии модуля. Value же сможет быть использована только на стадии run и далее. Т.е. тут больше семантики, чем реальных ограничений на изменение.
Помимо этого константы позволяют добавлять в кэш любые объекты, а не только провайдеры ( со всеми вытекающими ).

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

Непонятно почему статья глупая.

Потому что она не несёт ничего нового, всё это написано в документации.
Да почти все написано либо в документации, либо в исходниках. API-документация хороша, когда уже точно знаешь, что искать. Здесь материал по-другому структурирован и приведены примеры.

Возьмем в пример, provider. Смотрим на документацию angular.Module#provider:
See $provide.provider().


Хмм, ок. Смотрим $provide.provider():
Register a provider for a service. The providers can be retrieved and can have additional configuration methods.


Когда это все использовал, знаешь, в голове все уже хорошо уложено и структурировано, в принципе, и достаточно. Когда, только разбираешься со всем этим. Лучше бы примеры, да сравнения рядом разных подходов. Что и есть в данной статье.
Ну нужно знать что такое провайдер вообще ( что интересно многие не понимают именно этого ), а потом залезть в исходник и понять что вские factory это лишь обёртки.
Это тоже полезный путь. Для понимания сути реализации. И одно другому не мешает, а только помогает структурировать знания с разных точек зрения.
Потому что на русском даже таких статей нет. Надо же с основ начинать. В документации, к сожалению, не сказано как и зачем применять разные типы сервисов и человек не знакомый с паттернами проектирования просто не поймет зачем они нужны.

И в чем, по вашему, сложность Ангуляра?
Потому что на русском даже таких статей нет.

angular.ru

разные типы сервисов

Какие типы?

И в чем, по вашему, сложность Ангуляра?

Например связь директив
Какие типы?

constant, value, factory, service, provider — типы сервисов.

Представьте строительную технику, машины с ковшами, подъемниками и проч. и техническую документацию для нее, где указаны: ход ковша 2,2 м, угол разворота 270°, грузоподъемность 1,8 т. Эти данные ничего не говорят о том, для чего эта техника нужна. Поэтому в документации всегда есть пункт «назначение», где указано: применяется для рытья канав, глубиной до 1 м. Вот с «назначением» в ангуляровской документации не очень хорошо.

Например связь директив


А в чем там проблемы? На одном и том же элементы директивы связываются так: www.egghead.io/video/rzMrBIVuxgM, на разных — по событиям или через область видимости.
А в чем там проблемы?

А, т.е. связь директив со всякими функциями линковки, scope связей и т. д. для Вас раз плюнуть, а работа сервисов, где, по сути, value == factory == service == provider это сверх трудно для понимания, и нужно писать по 100 статей на эту тему?
Обычно перевожу статьи, объясняющие какие-то сложные моменты, которые меня интересуют (всё равно ковыряюсь в теме, так чего бы не потратить 2 часа и не порадовать Хабр). Или статьи (как эту) объясняющие как и в каких ситуациях пользоваться тем или иным функционалом.

Про связь между директивами у меня нет никакого представления зачем это нужно. Один раз была необходимость сообщать о том, что происходит внутри директивы и просто эмитил событие до корневой области видимости, а в другом месте внедрял $rootScope и вешал на него обработчик нужного события. Не писать же статью, основываясь на одном случае использования, не рассмотрев другие варианты.

value == factory == service == provider — это очень трудно для понимания! Возьмите пример из моей соседней статьи habrahabr.ru/post/190370/. Правильно ли там использовать фабрику? Может быть провайдер? Может вовсе в директиву запихнуть?
Ну как бы, по-крайней мере семантически, value != factory != service != provider — в этом и смысл. Тут бы впору, либо создателей поругать, зачем наплодили методов для одного и того же, либо все же разницу разъяснить.
Вы имеете в виду особенности поведения scope внутри директивы (isolate, child и scope контроллера, внутри которого эта директива используется)?
Обычно перевожу статьи, объясняющие какие-то сложные моменты, которые меня интересуют (всё равно ковыряюсь в теме, так чего бы не потратить 2 часа и не порадовать Хабр). Или статьи (как эту) объясняющие как и в каких ситуациях пользоваться тем или иным функционалом.

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

Не писать же статью, основываясь на одном случае использования, не рассмотрев другие варианты.

Как раз такое довольно интересно читать.

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

Тут нужно просто понимать что такое провайдер, и зачем он вообще нужен.
Как раз такое довольно интересно читать.

Попробую как нибудь, проверю сколько плюсов соберет)

Тут нужно просто понимать что такое провайдер, и зачем он вообще нужен.

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

app.provider( 'foo', function()
{
	var scale = 1;

	// Методы для конфигурирования сервиса.
	this.setScale = function( scale_ ) { scale = scale_; };
	// ...

	// Сам сервис.
	this.$get = {

		getScale : function() { return scale; },

		scale : function( n ) { return n * scale }
	};
} );

app.config(function(fooProvider)
{	
	// Конфигурируем сервис.
	fooProvider.setScale(2);
});


factory, service — объявления сервиса, их используем когда сервис конфигурировать не нужно.

Про value, constant рассказал aav, добавлю что объект добавленный через constant не имеет провайдера и его нельзя декорировать ( вот в этом плане говорят про его «неизменность» ).
Ну это смотря, конечно, что подразумевать под провайдером. У константы просто название провайдера без суффикса «Provider», поэтому decorator просто не сможет ее получить. Да и смысла в декорировании константы особого нет. Ее и так можно проинжектить в config и сделать с ней все что хочешь.
Стандартный пример настройки провайдера:
$routeProvider.
when('/phones', {templateUrl: 'partials/phone-list.html', controller: PhoneListCtrl}).
when('/phones/:phoneId', {templateUrl: 'partials/phone-detail.html', controller: PhoneDetailCtrl}).
otherwise({redirectTo: '/phones'});

Почему бы не задавать настройки через переменную, например? Внедряешь и настраиваешь все что хочешь
value('$config', {
$route: {
when: [
{url: '/phones', templateUrl: 'partials/phone-list.html', controller: PhoneListCtrl},
{url: '/phones/:phoneId', templateUrl: 'partials/phone-detail.html', controller: PhoneDetailCtrl}
],
otherwise: {redirectTo: '/phones'}
}
}})

Зачем ввели новую сущность: провайдер?
Зачем ввели новую сущность: провайдер?

Потому что у сервиса, сделанного через factory, нет доступа к секции config.

Как я думаю, это сделано ради легкого конфигурирования и разделения кода.

Нужно использовать только дефолтные настройки? Пожалуйста.
Нужно в данном конкретном приложении настроить этот провайдер вот таким образом? На здоровье.

Почему бы не задавать настройки через переменную, например? Внедряешь и настраиваешь все что хочешь

В данном конкретном случае fluent предпочтительней такого монструозного конфига. Код более структурирован и понятен.
Т.е. константа — это не провайдер в том, смысле, что она не предоставляет тот же интерфейс с методом $get. Но константа — провайдер с той точки зрения, что лежит в providerCache.
Ну с точки зрения AngularJS — провайдер это интерфейс с обязательным методом $get.
Но в providerCache рядом с такими провайдерами лежат и объекты, не реализующие такой интерфейс, как ни крути :)
Ну это уже к разработчикам, я вообще против этих провайдеров.
Провайдер это фабрика, настроенная особым образом

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

и вот в дополнение табличка что куда можно инжектить:
image
вы сейчас говорите о нативных провайдерах или кастомных?

если нативных — полностью согласен.
если о кастомных — покажите пожалуйста пример кода.
Таблица может вызвать некоторую путаницу. Она про сервисы, создаваемые с помощью разных способов? Просто провайдер сервиса то в .config заинжектится, иначе в чем бы был смысл. Сам инстанс сервиса, естественно, нет.

Под инъекцией в провайдер тут не очень понятно, что подразумевается — инъекции в $get? Там же инъекции в providerFn вобщем-то возможны.
Изучаю AngularJS и не смог понять сути, что такое фабрика, сервис и провайдеры, читая эту статью.
Разобрался почему — вещи названы не своими именами, примеры:

«Фабрика это сервис...»

Это не так.
.factory — это не сервис.
.factory — это рецепт (синтаксический сахар), который создает новый сервис из переданной функции.
Источник: docs.angularjs.org/guide/providers

Почему это очень путает новичка? Потому что он видит утверждение «Фабрика — это сервис».
Запоминает.
И потом по ходу вникания в примеры не может сопоставить информацию, обнаруживая противоречия —
так фабрика это сервис или это метод, который создает для нас сервис (привычное понимание фабрики в ООП)

«Провайдер это фабрика, настроенная особым образом.»

Это уже радикальное искажение информации.

Провайдер — это объект, который поставляет экземпляр сервиса:
Providers are objects that provide (create) instances of services and expose configuration APIs that can be used to control the creation and runtime behavior of a service. In case of the $route service, the $routeProvider exposes APIs that allow you to define routes for your application.

Источник: docs.angularjs.org/tutorial/step_07

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

Упрощать информацию — это благая цель. Но не искажайте ее, пожалуйста.
Во имя тех, кто верит хабру и будет пытаться разобраться по вашим статьям,
а не по оригинальной длиной документации.
Only those users with full accounts are able to leave comments. Log in, please.