AngularJS Wars: Service, Factory or Provider?
If there is one subject that causes controversy, confusion and gnashing of teeth amongst the AngularJS community, its whether to use a service, factory or a provider. This post is my attempt to rationalise this most controversial of topics.
In order to decide which is “best” to use
- Forget how you access it syntactically
- Forget if it’s a singleton or not
- Instead, simply consider its purpose
And this is where a lot of AngularJS developers come a cropper . If you don’t understand its purpose, how do you know if each one is the best one to use?
Note, I say “best” here because any of the 3 will work if all you want is a service object. The only notable difference that you should really concern yourself with is the keywords used in registering their use.
I think that service is a considerably loaded term within software development (and even more so in IT as whole). While I suspect the use of the term service by the AngularJS team probably has its origins in the Service Layer design pattern, I think it probably serves to confuse developers with the framework more than help them. Taking up the baton and running further with this I’ve read from multiple sources in the AngularJS space, which suggest using services should be analogus to the principles of service-orientation. That is, a service has to be reusable (service reusability) and a utility (service composability).
I personally try to be more pragmatic in my interpretation. Within the realms of the AngularJS framework, I prefer to consider services from the perspective of service abstraction.
Service by its very name suggests a logically separate unit of functionality that provides a “service” to the calling code.
While you can and should use a service if you have established reusability and composability, this can’t and shouldn’t be the exclusive criteria for the choice. If a service can be logically separated from your calling code, then DO IT. Regardless of how often you think you will reuse the code. With MV* frameworks like AngularJS that means any logic that is not purely controller-related (i.e. marshalling and requests and responses) should be in a service-type object. Separation of concerns (which leads to more readable, maintainable and testable code) is just as important to code quality as keeping your code DRY.
Use a service in AngularJS if you have identified logically separate code from your calling controller (or other service for that matter).
A factory comes from the Factory design pattern, which is a common technique for controlling how you create objects. Do not think syntax. Think conceptual. If the construction of an service object is complex and should be tightly controlled, then use a factory to construct it. The complex construction of your object is then encapsulated in the factory and not the concern of your calling code.
A factory is not used in instead of a service. It’s used to create the service on your behalf.
A provider allows you to use service functionality that normally requires configuration. The end results of the use of a provider may change based on the configuration given to it but the basic logic and rationale of the provider should remain consistent.
This allows your provider to be adaptable and used in multiple variant scenarios without having to change its internal logic. Providers can be used in multiple scenarios, including design-time pre-determined situations (e.g. test build vs dev build) but also in situations where re-use of the encapsulated logic across multiple domains may be beneficial (i.e. multiple code bases).
This adaptability is why providers are used regularly within the AngularJS framework itself and other 3rd party libraries.
- If your service object construction is simple, continue to use services and don’t worry about it.
- If its complex and unwiedly, use a factory to create your service. And then don’t worry about it.
- If its a configurable re-usable service then use a provider. And fair play to you for having the foresight to use it.
I’m sure there are people out there who disagree with this explanation, and I’d like to hear from them. In the end, the major takeaway that I have is that they are all notional “services” (which is probably why the AngularJS documentation uses the term interchangeably a lot of the time). Do not procrastinate to the point of paralysis. That is the worst choice of all.