--
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.
Pete
To unsubscribe from this group, send email to angular+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msg/angular/-/6acA8cchPqsJ.
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 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
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/editThere 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.ServicesSyntax: 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.FactoriesSyntax: 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.ProvidersSyntax: 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.
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);
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.
Visit this group at http://groups.google.com/group/angular?hl=en.
To unsubscribe from this group and stop receiving emails from it, send an email to angular+u...@googlegroups.com.
Visit this group at http://groups.google.com/group/angular.
For more options, visit https://groups.google.com/groups/opt_out.
--
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.
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.
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!
the instance types don't matter as long as they implement .start() and .stop().
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).
--
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/editThere 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.ServicesSyntax: 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.
FactoriesSyntax: 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.
ProvidersSyntax: 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.
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/