Angular Services
Angular services concept always confuses newbies with server side REST services. If you are still not sure what it is, I will recommend you to read Angular documentation
Angular Services have responsibility to provide application data/business logic to components. Components should take/provide data to service and function as glue between view and service. It is service who can decide whether to provide mock data or go to server and fetch data from database/file/another service(s) etc.
Ideally, services should be feature oriented. You have choice to build a giant service class or micro services collections. In first approach, there shall be only one service which shall contain all business logic and shall be provided via Angular Dependency Injection in all components within system. Issue with this approach is, giant service class shall get bloated eventually leading performance issue. Every component shall get injected with service and functionality which is not required to consumer component at all. Do you think it is good?
In second approach (followed widely), feature specific micro service gets built. For example, if your system have Login, SignUp, Dashboard components then you shall build LoginService, SignUpService, DashboardService and so on. Each service shall contain functionality required for specific targeted component. Now this design looks good, isn’t it?
Angular services concept always confuses newbies with server side REST services. If you are still not sure what it is, I will recommend you to read Angular documentation
Angular Services have responsibility to provide application data/business logic to components. Components should take/provide data to service and function as glue between view and service. It is service who can decide whether to provide mock data or go to server and fetch data from database/file/another service(s) etc.
Ideally, services should be feature oriented. You have choice to build a giant service class or micro services collections. In first approach, there shall be only one service which shall contain all business logic and shall be provided via Angular Dependency Injection in all components within system. Issue with this approach is, giant service class shall get bloated eventually leading performance issue. Every component shall get injected with service and functionality which is not required to consumer component at all. Do you think it is good?
In second approach (followed widely), feature specific micro service gets built. For example, if your system have Login, SignUp, Dashboard components then you shall build LoginService, SignUpService, DashboardService and so on. Each service shall contain functionality required for specific targeted component. Now this design looks good, isn’t it?
Problem?
While building big and complex Single Page Application using Angular, you shall soon end up with hundreds and thousands of component classes. Having said so, you shall have similar number of Angular services injected. What is the problem here?
No matter how good naming convention you have followed for building components and services, there shall be time required to figure out specific name of service for specific class. Also you may end up writing duplicate service class with slightly different name for same component than other team built. If you are working in Extreme Programming model, your frontend developers are supposed to keep switching between modules/components/features. It should not take much time for them to figure out components and services associated.
While building big and complex Single Page Application using Angular, you shall soon end up with hundreds and thousands of component classes. Having said so, you shall have similar number of Angular services injected. What is the problem here?
No matter how good naming convention you have followed for building components and services, there shall be time required to figure out specific name of service for specific class. Also you may end up writing duplicate service class with slightly different name for same component than other team built. If you are working in Extreme Programming model, your frontend developers are supposed to keep switching between modules/components/features. It should not take much time for them to figure out components and services associated.
Solution
We can solve this problem using Facade design pattern.
Facade Design Pattern
Facade discusses encapsulating a complex subsystem within a single interface object. This reduces the learning curve necessary to successfully leverage the subsystem. It also promotes decoupling the subsystem from its potentially many clients.
The Facade object should be a fairly simple advocate or facilitator. It should not become an all-knowing oracle or “god” object.
Here is the good read for Facade design pattern in details
Facade in action with Angular Services
I would recommend following steps to build Angular services using Facade pattern:
Define all your Angular services as per your business requirement and/or keep adding more as needed.
Create a service called “FacadeService” (feel free to use any other name here)
Create a shared NgModule and provide all Angular services
Facade Service implementation
Our main discussion shall be around “FacadeService
” service only.
We have discussed about two approaches giant service versus micro service. We have seen their pros and cons. Best solution is to merge both of them to create service Facade. Now, FacadeService
class shall be a God class but won’t have actual functionality but a wrapper over actual services.
FacadeService
shall aggregate all Angular services within the said system. One easy approach is to inject all services inside FacadeService
in constructor. But if we do so, we shall end up with similar problem as of giant service class.
Smarter way would be to aggregate all Angular services inside FacadeService
and resolve their instances from Angular DI inside “property” access.
Let’s discuss AccountService
usage.
We have a property defined called accountService
inside FacadeService. getOrderList()
and getAddress()
functions of FacadeService
works as wrappers for actual methods of accountService.
Whenever accountService
member is accessed, its get
property block shall be executed. Inside get
block, we check if backing field _accountService
is instantiated. If not, we asks Angular Dependency Injector to resolve an instance for us.
To access Angular DI engine, we need to inject Inejctor
Angular’s built-in service inside FacadeService
constructor. injector.get()
shall query Angular’s DI engine to resolve requested service instance if it is provided. (Remember SharedModule where we have provided all services?)
If you have observed carefully, we have implemented Singleton design pattern as well inside get
property section of accountService
property.
Consuming FacadeService inside component(s)
We have AccountService
aggregated inside FacadeService
and it is ready to be consumed inside OrderComponent
and AddressComponent.
Finishing up remaining system
On the similar note of accountService
implementation, you can finish implementation of other Angular services inside FacadeService.
We can solve this problem using Facade design pattern.
Facade Design Pattern
Facade discusses encapsulating a complex subsystem within a single interface object. This reduces the learning curve necessary to successfully leverage the subsystem. It also promotes decoupling the subsystem from its potentially many clients.
The Facade object should be a fairly simple advocate or facilitator. It should not become an all-knowing oracle or “god” object.
Here is the good read for Facade design pattern in details
Facade in action with Angular Services
I would recommend following steps to build Angular services using Facade pattern:
Define all your Angular services as per your business requirement and/or keep adding more as needed.
Create a service called “FacadeService” (feel free to use any other name here)
Create a shared NgModule and provide all Angular services
Facade Service implementation
Our main discussion shall be around “
FacadeService
” service only.
We have discussed about two approaches giant service versus micro service. We have seen their pros and cons. Best solution is to merge both of them to create service Facade. Now,
FacadeService
class shall be a God class but won’t have actual functionality but a wrapper over actual services.FacadeService
shall aggregate all Angular services within the said system. One easy approach is to inject all services inside FacadeService
in constructor. But if we do so, we shall end up with similar problem as of giant service class.
Smarter way would be to aggregate all Angular services inside
FacadeService
and resolve their instances from Angular DI inside “property” access.
Let’s discuss
AccountService
usage.
We have a property defined called
accountService
inside FacadeService. getOrderList()
and getAddress()
functions of FacadeService
works as wrappers for actual methods of accountService.
Whenever
accountService
member is accessed, its get
property block shall be executed. Inside get
block, we check if backing field _accountService
is instantiated. If not, we asks Angular Dependency Injector to resolve an instance for us.
To access Angular DI engine, we need to inject
Inejctor
Angular’s built-in service inside FacadeService
constructor. injector.get()
shall query Angular’s DI engine to resolve requested service instance if it is provided. (Remember SharedModule where we have provided all services?)
If you have observed carefully, we have implemented Singleton design pattern as well inside
get
property section of accountService
property.
Consuming FacadeService inside component(s)
We have
AccountService
aggregated inside FacadeService
and it is ready to be consumed inside OrderComponent
and AddressComponent.
Finishing up remaining system
On the similar note of
accountService
implementation, you can finish implementation of other Angular services inside FacadeService.
No comments:
Post a Comment