What is the difference between module.factory and module.service and how might both be applied?

78760 views
Skip to first unread message

ProLoser

unread,
Apr 19, 2012, 6:02:21 PM4/19/12
to ang...@googlegroups.com
On IRC, a few other individuals and I have been a bit confuzzled by how to properly apply these two items in our code.

I believe the main issue is that NO ONE really understands the fundamental difference and purpose.

After reading the docs, I found them to be both circular in definition (EXAMPLE - quickly: having the attribute of being quick) and more importantly, use an almost convoluted degree of industry terminology. Now I don't consider myself an amateur and get most of these fundamental concepts and patterns, but the underlying issue is I have no bloody idea how they are intended to be used and how to apply them.

What I think would help the most is this: Please give a real-world use-case and (more importantly) an analogy to real-world objects so that people trying to learn Angular can understand.

By analogy I mean take the concept of patterns and code completely out of the equation. EXAMPLE:
Abstract class is like the word 'shape'. You can't simply use a shape, you need to specify exactly what kind of shape you are making in order to understand how it will behave. Extending an abstract class is like how a 'square' falls under the classification of 'shape' but you can specify dimension of a square and how it will behave, such as rolling. You CAN however determine general information, such as how many shapes are on the piece of paper, or that every shape can have a color.

Sorry I realize that's long, but I really think this is a very lacking and a lot of people have been asking these very questions.

Peter Bacon Darwin

unread,
Apr 19, 2012, 6:09:49 PM4/19/12
to ang...@googlegroups.com
You use factory if the function you are providing will be called to build the object that you want.  I.E. Angular will do obj = MyFactory() to get the obj.
You use service if the function you are providing is a constructor for the object that you want. I.E. Angular will do obj = new MyFactory() to instantiate the obj. 

Does that make sense?  One of the reasons that the service was introduced was to make it easy to use "classical" OO techniques, such as defining your service as a coffeescript class:

class MyService
  constructor: ($resource)->
    # Some stuff
  someMethod: ()->
etc.

Then module.service('MyService', ['$resource', MyService]) creates the new instance of MyService correctly.

Pete

--
You received this message because you are subscribed to the Google Groups "AngularJS" group.
To view this discussion on the web visit https://groups.google.com/d/msg/angular/-/iXEGJDcbmHcJ.
To post to this group, send email to ang...@googlegroups.com.
To unsubscribe from this group, send email to angular+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/angular?hl=en.

Nick R

unread,
Apr 19, 2012, 6:10:16 PM4/19/12
to ang...@googlegroups.com
In my code, I use a lot of Module#factory to create injectable models and such.  I almost never use Module#service because when I try to inject it, I get some weird Constructor object and I can't figure out what to do with it.  What is the purpose of Module#service and how are you supposed to use it?  I've never seen a good example.

Also, I find myself writing a lot of small functions.  These functions may have dependencies, may depend on each other, etc.  It would be nice if I could define them all in a single context with dependencies injected in it, and then provide them all.  I think this is possible with $provide, but I can't figure out how you're supposed to use it.  The example on the provide page is kind of confusing because it mixes application behavior into the test case, and doesn't inject any dependencies into the service it provides.

Nick R

unread,
Apr 19, 2012, 6:40:07 PM4/19/12
to ang...@googlegroups.com
What if you wanted to inject dependencies?  Is that injecting a dependency into the constructor there?  What if you wanted it to work on minified code?  Can you give a similar example for factories?
Pete

To unsubscribe from this group, send email to angular+unsubscribe@googlegroups.com.

Igor Minar

unread,
Apr 19, 2012, 7:09:09 PM4/19/12
to ang...@googlegroups.com
factory takes a function which is injected and this function returns the instantiated service instance.

myModule.factory('myService', function(dep1, dep2) {
  //construct the service instance
  return serviceInstance;
});

service will instantiate the service instance using the constructor function provided just as if it was called with the new operator, but the constructor gets injected with dependencies:

myModule.service('myService', function(dep1, dep2) {
  //instantiate "this" just as a constructor would
});

alternatively you might do something like this:

var MyService = function(dep1, dep2) {
}

MyService.prototype.protoMethodA = function() {}
MyService.prototype.protoField = 'some field';

myModule.service('myService', MyService);


So the main difference between factory and service is that factory returns some object, while the service creates new instance and returns "this".

I hope this clears things up.

/i




To view this discussion on the web visit https://groups.google.com/d/msg/angular/-/6acA8cchPqsJ.

To post to this group, send email to ang...@googlegroups.com.
To unsubscribe from this group, send email to angular+u...@googlegroups.com.

numan

unread,
Jul 31, 2012, 1:48:14 PM7/31/12
to ang...@googlegroups.com
Its still not clear to me when you should use one over the other because in the end both techniques result in registering the service singleton.

Can they always be used interchangeably or is there a scenario where you would use factory method over service method? 

Thanks!

Pawel Kozlowski

unread,
Jul 31, 2012, 2:03:47 PM7/31/12
to ang...@googlegroups.com
hi!

Here is the response I've posted a while ago to a very similar
question about service, factories and providers (jsFiddle included!):

In fact $provide.provider, $provide.factory and $provide.service are
more or less the same thing in the sense that all of them are
blueprints / instructions for creating object instances (those
instances are then ready to be injected into collaborators).

$provide.provider is the most spohisticated method of registering
blueprints, it allows you to have a complex creation function and
configuration options.

$provide.factory is a simplified version of $provide.provider when you
don't need to support configuration options but still want to have a
more sophisticated creation logic.

$provide.service is for cases where the whole creation logic boils
down to invoking a constructor function.

So, depending on the complexity of your construction logic you would
choose one of $provide.provider, $provide.factory and $provide.service
but in the end what you are going to get is a new instance.

Here is the jsFiddle showing different ways of constructing objects:
http://jsfiddle.net/pkozlowski_opensource/PxdSP/14/


The angular documentation is quite OK regarding this topic:
http://docs.angularjs.org/api/AUTO.$provide

Cheers,
Pawel
>>>>> angular+u...@googlegroups.com.
>>>>> For more options, visit this group at
>>>>> http://groups.google.com/group/angular?hl=en.
>>>>
>>>>
>>> --
>>> You received this message because you are subscribed to the Google Groups
>>> "AngularJS" group.
>>> To view this discussion on the web visit
>>> https://groups.google.com/d/msg/angular/-/6acA8cchPqsJ.
>>>
>>> To post to this group, send email to ang...@googlegroups.com.
>>> To unsubscribe from this group, send email to
>>> angular+u...@googlegroups.com.
>>> For more options, visit this group at
>>> http://groups.google.com/group/angular?hl=en.
>>
>>
> --
> You received this message because you are subscribed to the Google Groups
> "AngularJS" group.
> To post to this group, send email to ang...@googlegroups.com.
> To unsubscribe from this group, send email to
> angular+u...@googlegroups.com.
> Visit this group at http://groups.google.com/group/angular?hl=en.
>
>

numan....@gmail.com

unread,
Jul 31, 2012, 3:31:13 PM7/31/12
to ang...@googlegroups.com
Thanks for explaining that clearly.

As a beginner I found the docs lacking in this regard. It would be cool to have the docs updated to explain it clearly with examples.

I might be missing something but I didn't see docs on github. How does one contribute to the docs?


>>>>> For more options, visit this group at
>>>>> http://groups.google.com/group/angular?hl=en.
>>>>
>>>>
>>> --
>>> You received this message because you are subscribed to the Google Groups
>>> "AngularJS" group.
>>> To view this discussion on the web visit
>>> https://groups.google.com/d/msg/angular/-/6acA8cchPqsJ.
>>>
>>> To post to this group, send email to ang...@googlegroups.com.
>>> To unsubscribe from this group, send email to
>>> For more options, visit this group at
>>> http://groups.google.com/group/angular?hl=en.
>>
>>
> --
> You received this message because you are subscribed to the Google Groups
> "AngularJS" group.
> To post to this group, send email to ang...@googlegroups.com.
> To unsubscribe from this group, send email to

Pawel Kozlowski

unread,
Jul 31, 2012, 3:40:57 PM7/31/12
to ang...@googlegroups.com
hi!

On Tue, Jul 31, 2012 at 9:31 PM, <numan....@gmail.com> wrote:

> I might be missing something but I didn't see docs on github. How does one
> contribute to the docs?

They are part of the source code so you can simply open PR for the
angular project.

Cheers,
Pawel

Øyvind Nordhagen

unread,
Aug 16, 2012, 5:45:58 PM8/16/12
to ang...@googlegroups.com
I've been struggling with these concepts myself and reading the docs aren't much help. The docs are often pointed to as the weak spot of Angular; they use highly technical lingo in which the author seems to have inserted a slightly personal interpretation of some terms (I.e. the use of the term "service" for what is essentially a decorator). They are also full of spelling mistakes and even code examples containing at times quite horrid spaghetti code. Luckily the Angular team knows this and are working to change it.

Will Kriski

unread,
Aug 16, 2012, 6:26:01 PM8/16/12
to ang...@googlegroups.com
Thanks Øyvind I feel dumb reading those docs so it's not just me :)

ben.clin...@gmail.com

unread,
Aug 17, 2012, 2:00:53 PM8/17/12
to ang...@googlegroups.com
In order to get this straight in my own head I have created a very simple demo which can be viewed at http://jsbin.com/ohamub/1/edit

There are comments in the code illustrating the primary differences but I will expand on them a bit here. As a note, I am just getting my head around this so if I say anything that is wrong please let me know.

Services
Syntax: module.service( 'serviceName', function );
Result: When declaring serviceName as an injectable argument you will be provided the actual function reference passed to module.service.
Usage: Could be useful for sharing utility functions that are useful to invoke by simply appending () to the injected function reference. Could also be run with injectedArg.call( this ) or similar.

Factories
Syntax: module.factory( 'factoryName', function );
Result: When declaring factoryName as an injectable argument you will be provided the value that is returned by invoking the function reference passed to module.factory.
Usage: Could be useful for returning a 'class' function that can then be new'ed to create instances.

Providers
Syntax: module.provider( 'providerName', function );
Result: When declaring providerName as an injectable argument you will be provided the value that is returned by invoking the $get method of the function reference passed to module.provider.
Usage: Could be useful for returning a 'class' function that can then be new'ed to create instances but that requires some sort of configuration before being injected. Perhaps useful for classes that are reusable across projects? Still kind of hazy on this one.

Again, please let me know if I have misspoken here, but hopefully this is accurate and will prove useful to somebody.

Ben

Miško Hevery

unread,
Aug 19, 2012, 12:38:20 AM8/19/12
to ang...@googlegroups.com
Lets look at the simplest scenario

provide.value('a', 123);

function Controller(a) {
  expect(a).toEqual(123);
}

in this case the injector simple returns the value as is. But what if you want to compute the value. Then use a factory

provide.factory('b', function(a) {
  return a*2;
});

function Controller(b) {
  expect(a).toEqual(246);
}

So factory is a function which is responsible for creating the value. Notice that the factory function can ask for other dependencies. But what if you want to be more OO and have a class called Greeter

function Greeter(a) {
  this.greet = function() {
    return 'Hello ' + a;
  }
}

then to instantiate you would have to write

provide.factory('greeter', function(a) {
  return new Greeter(a);
});

Then we could ask for 'greeter' in controller like this

function Controller(greeter) {
  expect(greeter instanceof Greeter).toBe(true);
  expect(greeter.greet()).toEqual('Hello 123');
}


But that is way too wordy a shorter way to write this would be
provider.service('greeter', Greeter);

But what it we wanted to configure the Greeter class before the injection then we could write

provide.provider('greeter2', function() {
  var salutation = 'Hello';
  this.setSalutation = function(s) {
    salutation = s;
  }

  function Greeter(a) {
    this.greet = function() {
      return salutation + ' ' + a;
    }
  }

  this.$get = function(a) {
    return new Greeter(a);
  };
});

we can then do this

angular.module('abc', []).configure(function(greeter2Provider) {
  greeter2Provider.setSalutation('Halo');
});

function Controller(greeter2) {
  expect(greeter.greet()).toEqual('Halo 123');
}

But it turns out that angular only understands provide.provider, all other ones are derived.

provider.service = function(name, Class) {
  provider.provide(name, function() {
    this.$get = function($injector) {
      return $injector.instantiate(Class);
    };
  });
}

provider.factory = function(name, factory) {
  provider.provide(name, function() {
    this.$get = function($injector) {
      return $injector.invoke(factory);
    };
  });
}

provider.value = function(name, value) {
  provider.factory(name, function() {
    return value;
  });
};


On Thursday, April 19, 2012 3:02:21 PM UTC-7, ProLoser wrote:

Miško Hevery

unread,
Aug 19, 2012, 12:43:09 AM8/19/12
to ang...@googlegroups.com, ben.clin...@gmail.com
See inline


On Friday, August 17, 2012 11:00:53 AM UTC-7, ben.clin...@gmail.com wrote:
In order to get this straight in my own head I have created a very simple demo which can be viewed at http://jsbin.com/ohamub/1/edit

There are comments in the code illustrating the primary differences but I will expand on them a bit here. As a note, I am just getting my head around this so if I say anything that is wrong please let me know.

Services
Syntax: module.service( 'serviceName', function );
Result: When declaring serviceName as an injectable argument you will be provided the actual function reference passed to module.service.

NO, you will get an instance of the function. In other words new FunctionYouPassedToService().
 
Usage: Could be useful for sharing utility functions that are useful to invoke by simply appending () to the injected function reference. Could also be run with injectedArg.call( this ) or similar.

Factories
Syntax: module.factory( 'factoryName', function );
Result: When declaring factoryName as an injectable argument you will be provided the value that is returned by invoking the function reference passed to module.factory.

CORRECT
 
Usage: Could be useful for returning a 'class' function that can then be new'ed to create instances.

Providers
Syntax: module.provider( 'providerName', function );
Result: When declaring providerName as an injectable argument you will be provided the value that is returned by invoking the $get method of the function reference passed to module.provider.
ALMOST
you will be provided with new ProviderFunction().$get(). The constructor function is instantiated before the $get method is called.
 
Usage: Could be useful for returning a 'class' function that can then be new'ed to create instances but that requires some sort of configuration before being injected. Perhaps useful for classes that are reusable across projects? Still kind of hazy on this one.

Providers have the advantage that they can be configured during the module configuration phase.

ben.clin...@gmail.com

unread,
Aug 20, 2012, 3:05:14 PM8/20/12
to ang...@googlegroups.com, ben.clin...@gmail.com
Thanks for the clarifications, Misko. Now that you've pointed it out I am not sure how I missed the fact that they always get new'ed.

cerebr...@gmail.com

unread,
Sep 5, 2012, 6:50:40 PM9/5/12
to ang...@googlegroups.com
First of all, thanks for AngularJS; it has been an absolute dream to use. Secondly, I'd like a little pro advice dealing with services and prototypes. This was suggested as a way to use prototypes with building custom services:

On Thursday, April 19, 2012 6:09:09 PM UTC-5, Igor Minar wrote:

alternatively you might do something like this:

var MyService = function(dep1, dep2) {}

MyService.prototype.protoMethodA = function() {}
MyService.prototype.protoField = 'some field';

myModule.service('myService', MyService);

 
What is the suggested way to do exactly this, use prototypes for generic functions, but also take advantage of Angular's built in services, like $http? Since the constructor function and prototype are defined outside of myModule, how do you inject the $http service into the MyService function? I ended up doing this, which works, but it feels a little off because I'm calling new redundantly, aren't I?

myModule.service('myService', function ($http) {

var MyService = function () { // constructor stuff };

MyService.prototype = { // generic functions that uses $http service };

this.fn = new MyService();
}

Now, doesn't then myService get new'ed when injected into the controller? So, I'm new'ing a new'ed object? Any advice?

the...@gmail.com

unread,
Sep 17, 2012, 7:26:18 AM9/17/12
to ang...@googlegroups.com, cerebr...@gmail.com
Second example does not new anyting as you dont return anyting. you should return MyService if i understand it right. not an instance, instances are created then by angular

cerebr...@gmail.com

unread,
Sep 18, 2012, 1:10:13 AM9/18/12
to ang...@googlegroups.com, cerebr...@gmail.com, the...@gmail.com
Thanks for the feedback! So, instead of using the service() style, use the factory() style and return the new'ed Constructor function? Like this:

myModule.factory('myService', function ($http) {

var MyService = function () { // constructor stuff };

MyService.prototype = { // generic functions that uses $http service };

return new MyService();
};

I guess that works for me. Is that what you meant?

rw3...@gmail.com

unread,
Sep 21, 2012, 10:43:27 AM9/21/12
to ang...@googlegroups.com, cerebr...@gmail.com, the...@gmail.com
No I think he meant this:

myModule.factory('myService', function ($http) {

var MyService = function () { // constructor stuff };

MyService.prototype = { // generic functions that uses $http service };

return MyService;
};

....

unread,
Sep 29, 2012, 12:24:03 AM9/29/12
to ang...@googlegroups.com, cerebr...@gmail.com, the...@gmail.com, rw3...@gmail.com
Shouldn't that be: 

myModule.service('myService', function ($http) {

var MyService = function () { // constructor stuff };

MyService.prototype = { // generic functions that uses $http service };

return MyService;
};

Justin L.

unread,
Sep 29, 2012, 12:58:44 AM9/29/12
to ang...@googlegroups.com, cerebr...@gmail.com, the...@gmail.com, rw3...@gmail.com, martje...@gmail.com
That's what I thought. Unfortunately, it's still not new'ing the constructor function. I have to — return new MyService — or the prototype doesn't get bound to the returned object. I just can't seem to get around having to new the constructor function within the service/factory function. 

Which is fine, if that's the intended design, but then all the explanations I've read about how Angular treats the service method seems inaccurate. Unless I'm just completely missing something here, which could be possible. Thanks for the help :)

Pawel Kozlowski

unread,
Sep 30, 2012, 5:44:10 PM9/30/12
to ang...@googlegroups.com
Hi!

On Sat, Sep 29, 2012 at 6:58 AM, Justin L. <cerebr...@gmail.com> wrote:

> Which is fine, if that's the intended design, but then all the explanations
> I've read about how Angular treats the service method seems inaccurate.
> Unless I'm just completely missing something here, which could be possible.

What gets registered a service is a _constructor function_ (which
AngularJS will just new to create service instances). If you are
passing an anonymous constructor function (like in the examples) you
don't have many chances to extend the prototype. This is why your
approach with factories is the good, don't get confused :-)

In short: if you want to mess with prototype - use factories. Using
service style would be possible provided that your constructor
function is defined outside of AngularJS and you simply register and
existing constructor function with a prototype modified, sth like:

http://jsfiddle.net/pkozlowski_opensource/PnMWx/2/

but this is ugly IMHO compared to the factory approach...

Cheers,
Pawel

--
Question? Send a fiddle
(http://jsfiddle.net/pkozlowski_opensource/Q2NpJ/) or a plunk
(http://plnkr.co/)
Need help with jsFiddle? Check this:
http://pkozlowskios.wordpress.com/2012/08/12/using-jsfiddle-with-angularjs/

Looking for UI widget library for AngularJS? Here you go:
http://angular-ui.github.com/

Peter Bacon Darwin

unread,
Oct 1, 2012, 1:20:51 AM10/1/12
to ang...@googlegroups.com

The original driver for the 'service' version was to support things like coffee script classes, which do need to be instantiated rather than simply called.

Pete
...from my mobile.

--
You received this message because you are subscribed to the Google Groups "AngularJS" group.
To post to this group, send email to ang...@googlegroups.com.
To unsubscribe from this group, send email to angular+u...@googlegroups.com.

thomas.l...@gmail.com

unread,
Oct 12, 2012, 12:20:18 PM10/12/12
to ang...@googlegroups.com
I've made a helper to expose a class as a Factory, it supports angular dependency injection and class constructor with custom parameters.

I've made this because i need to have my classes (MyObject and MyObjectWithParam) defined like this and not in the factory declaration like it is usually done in angular projects.

You can view it working in this fiddle: http://jsfiddle.net/tomsdev/aC25a/

What do you think about it?

Peter, maybe it's something that solve your problem with using coffee script classes?

Peter Bacon Darwin

unread,
Oct 12, 2012, 2:26:15 PM10/12/12
to ang...@googlegroups.com
Isn't this what service does?

thomas.l...@gmail.com

unread,
Oct 12, 2012, 2:30:06 PM10/12/12
to ang...@googlegroups.com
If i understand well, service just provide singleton object and doesn't support calling class constructors with custom parameters, doesn't it?

Peter Bacon Darwin

unread,
Oct 14, 2012, 4:03:59 PM10/14/12
to ang...@googlegroups.com
Hi Thomas,
It took me a while to get my head around what your code was actually doing.  What you want is a factory that returns a function that will create instances of your class with the constructor's dependencies automatically injected?
This can be done with $injector.instantiate.  See this plnkr: http://plnkr.co/edit/GKnhIN?p=preview.

The key piece is this factory:

App.factory('MyObjectWithParam', function ($injector) {
    return function(name) { return $injector.instantiate(MyObjectWithParam, { name: name }); };
});

I have to say, though, that the more I use Angular, the less interest I have in creating classes.  Classes are not where javascript is at!  You can do pretty much everything you need with pure functions and closures and then you don't have to worry about the troublesome "this" and "that".

Pete

Prateek Agrawal

unread,
Jul 8, 2013, 2:33:22 AM7/8/13
to ang...@googlegroups.com
I have just started learning AngularJS and its been very confusing in the docs.
But this post has helped me a lot to understand service, factory and provider.
Thanks Guys :)
Any suggestions from where I should read to get the core knowledge in less confusing way ?

Peter Bacon Darwin

unread,
Jul 8, 2013, 6:50:00 AM7/8/13
to ang...@googlegroups.com
I would start by reading every page in this section of the docs: http://docs.angularjs.org/guide/


To unsubscribe from this group and stop receiving emails from it, send an email to angular+u...@googlegroups.com.

To post to this group, send email to ang...@googlegroups.com.
Visit this group at http://groups.google.com/group/angular.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Prateek Agrawal

unread,
Jul 8, 2013, 6:52:35 AM7/8/13
to ang...@googlegroups.com
Ok ''ll do that ..thnx a lot buddy :)


--
You received this message because you are subscribed to a topic in the Google Groups "AngularJS" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/angular/56sdORWEoqg/unsubscribe.
To unsubscribe from this group and all its topics, send an email to angular+u...@googlegroups.com.

To post to this group, send email to ang...@googlegroups.com.
Visit this group at http://groups.google.com/group/angular.
For more options, visit https://groups.google.com/groups/opt_out.
 
 



--
Prateek Agrawal

avax nguyen

unread,
Aug 9, 2013, 4:02:33 AM8/9/13
to ang...@googlegroups.com
Not sure below is that you mean, but it works for my problem
I use module.service() and return return {MyService:MyService}; and in other module I refer to this function constructor by myService.MyService.call(...)
Details of my problem on SO

Danny Eck

unread,
Nov 22, 2013, 10:39:54 PM11/22/13
to ang...@googlegroups.com
Almost wrapped my head around this... Pete's plunkr from 10/14/12 helped alot (this might be because the meaning of 'factory' is confusing me...) But I'm still struggling with how best to do aggregation with a service: Here's a Plnkr. I have to use 'new' or $injector.instantiate() somewhere...

If I want lots of instances of the same class or do some other encapsulation, I personally will tend towards OO. How would one accomplish this with closures?

Daniel Tabuenca

unread,
Nov 25, 2013, 12:03:20 AM11/25/13
to ang...@googlegroups.com

Factories, and services in angular are singleton by definition. If you want to create a new instance you could always just do something like:

module.factory('myIntanceCreator', function(){
      return {
           create: function(){
                // create your instance here
            }
      };

});

Keep in mind that, contrary to popular belief you don’t need ‘class’ for true object-oriented-programming. If you get a chance, take a look at this talk:

http://www.infoq.com/presentations/It-Is-Possible-to-Do-OOP-in-Java

One of it’s main points is that Javascript’s closures are actually offer a much purer form of encapsulation and OOP than even other class-based OOP languages.

In a nutshell, variables and functions defined inside of a closure are strictly private, while variables or functions that are attached to via this.myVariable = value are public.

Danny Eck

unread,
Nov 25, 2013, 10:09:51 PM11/25/13
to ang...@googlegroups.com

Great talk! I dl'd the mp3 and listened on my reverse commute.

I had gotten so wrapped up in how to create an instance-making service to guarantee all objects in my collection were homogenous (or at least shared a common prototype), that I overlooked the fact that the aggregator shouldn't be prescriptive about types. In my contrived chorus/choirboy example, the instance types don't matter as long as they implement .start() and .stop().

myModule.service('chorus', function(){
   this.members = [];
   this.addMember = function(){ 
      // check for .start() and .stop() methods
   }
   this.commence = function(){
      // loop members, member.start()
   }
   this.halt = function(){
      // loop members, member.stop()
   }
});

This seems like the least presumptuous. Thanks!

gno...@gmail.com

unread,
Dec 28, 2013, 2:42:44 AM12/28/13
to ang...@googlegroups.com
the instance types don't matter as long as they implement .start() and .stop().

Having quite enjoyed the talk, I'm still a bit troubled by this notion. The notion that I can trust an object to implement the correct interface simply because it has methods whose names I care about is not the same as the notion that I can trust an object to implement the correct interface because it successfully meets the criteria of implementing that interface. Granted, this is quite possibly the closest approximation available in JavaScript.

To illustrate in an absurd way: suppose I want to add a Person member to a Group list. It's easy enough to assume that an object called "group" (because it was passed as an argument) is Array-like because it has a push() method, but suppose that object is an instance of Person! Person#push is not the same as List#push. Now I've instructed a Person to push another Person, which was absolutely not what I meant to do. I doubt either of those Persons will be members of my Group.

Daniel Tabuenca

unread,
Dec 28, 2013, 5:01:13 PM12/28/13
to ang...@googlegroups.com

There’s two notions at play here, one is object-oriented programming (which javascript handles quite well), the other is a static typing system (which javascript being a dynamic language doesn’t natively support).

It’s important to understand that you can do object-oriented programming without static typing, classes, explicit interfaces, or inheritance. Similarly, just because you are using classes, interfaces, or inheritance doesn’t mean your code is object-oriented.

I understand why you are troubled by the notion that you shouldn’t just be able to trust an object implements the correct interface simply because it has methods with the right names. Technically speaking, you are absolutely correct. The push method of an object I pass in might very well just do a window.alert('I'm not pushing').

However, what you have to realize is that there is always an implicit contract between methods and API’s you write, and the people who use those API’s. When you write a function, you have to document or show examples of what it does, what parameters it expects and what it will return. A statically typed language provides some tools to help document and enforce some of that contract at compile time. However, static typing can only go so far to enforce a contract, so you still have to trust the caller. For example, even with static typing I can create a group and have it implement a “List” interface but there is nothing preventing me from implementing the list interface incorrectly, or even purposefully not behaving as a faithful implementation of a list contract (i.e. I can still “push” persons off a cliff rather than add them to my group).

Duck-typing can be a useful tool in dynamically typed languages, as long as your contracts is documented. For example, in your method you would say: “if the first parameter proviides a push method it will be interpreted as an array-like object and the method used to add items to it”. While this contract is not enforced by the language itself or the compiler, it is still a contract nonetheless. If the user of your method chooses to pass in an object with a push that does something other than what the contract requires, they should not expect it to work correctly. 

We use these kind of contracts all the time in angular and don’t think much of them. Take for example controller definitions, they take a string and a constructor, but the constructor could be a function, or it could be an array where where each element is a string and the last element is a function (for dependency injection). So the following two are valid ways of defining a controller:

app.controller('myController', function($scope){
});

app.controller('myController', ['$scope', function($scope){ 
}]);

This is a contract we are all familiar with, but it’s not enforced by the language, I could pass an array of integers as the second parameters but it would not really work because I’m violating the contract in the documentation. I could pass a list of strings that don’t actually match any services in my module and angular would throw me an exception because the contract states that these strings should be the names of valid services.

My point is that the contract is between a method and those who use the method. Static typing can only help partially document and enforce some aspects of the contract, but often not the entire contract, so there will always be a level of trust that the objects passed in to your function behave as specified in the contract (even when using static typing).

Mike Alsup

unread,
Jan 17, 2014, 9:52:34 PM1/17/14
to ang...@googlegroups.com
Well said, Daniel.


--

Ovi Wan-Kenobi

unread,
Apr 24, 2015, 3:11:53 AM4/24/15
to ang...@googlegroups.com
thanks, this was helpful to me
I have put together a demo app which is showing the use of most angular concepts


On Friday, 17 August 2012 20:00:53 UTC+2, Ben Clinkinbeard wrote:
In order to get this straight in my own head I have created a very simple demo which can be viewed at http://jsbin.com/ohamub/1/edit

There are comments in the code illustrating the primary differences but I will expand on them a bit here. As a note, I am just getting my head around this so if I say anything that is wrong please let me know.

Services
Syntax: module.service( 'serviceName', function );
Result: When declaring serviceName as an injectable argument you will be provided the actual function reference passed to module.service.
Usage: Could be useful for sharing utility functions that are useful to invoke by simply appending () to the injected function reference. Could also be run with injectedArg.call( this ) or similar.

Factories
Syntax: module.factory( 'factoryName', function );
Result: When declaring factoryName as an injectable argument you will be provided the value that is returned by invoking the function reference passed to module.factory.
Usage: Could be useful for returning a 'class' function that can then be new'ed to create instances.

Providers
Syntax: module.provider( 'providerName', function );
Result: When declaring providerName as an injectable argument you will be provided the value that is returned by invoking the $get method of the function reference passed to module.provider.
Usage: Could be useful for returning a 'class' function that can then be new'ed to create instances but that requires some sort of configuration before being injected. Perhaps useful for classes that are reusable across projects? Still kind of hazy on this one.

Luis Perez

unread,
Nov 19, 2015, 9:11:58 AM11/19/15
to AngularJS

As mentioned here provider, service, and factory are the same things. In fact so is value() and constant(). They are all specialized more succinct versions of provider. You can see it broken down in this image:



Choosing comes down to which one results in you accomplishing what you want in the last amount of code. And the additional question of whether you want to be able to access the provider during the configuration phase. I break it down in more detail on at: http://www.simplygoodcode.com/2015/11/the-difference-between-service-provider-and-factory-in-angularjs/

Reply all
Reply to author
Forward
0 new messages