DEV Community

Bruno Pinheiro
Bruno Pinheiro

Posted on

Simplifying Angular components with Facade

On an Angular project, you have your components, managing the interaction with the user, and, quite often they can become massive and complex, making it hard to refactor anything, and for newcomers to understand the code.

One way to improve this situation is to use the design pattern Facade. This pattern is used to mask or hide more complex interactions.

When structuring Angular projects, I like to think like this: the component should worry only about user interaction, showing and receiving information.

If the component needs something, it shouldn't go after it itself, but rather request it from someone else.

For example, the user enters a page with a list of products. The component shouldn't be the one to go after the products list. It should ask the facade service to fetch that instead. When the component receives the list, it can display it to the user. That's the only thing the component should have to worry about, the interaction with the user.

The component should communicate only with the facade, using the facade service to simplify information processing.

Let's see it more visually now.

Think about the product list again.

When the user enters a page with the list you could have something like this.

private findAllProducts() {
    this.productsApiService.findAllProdutcs().pipe(map(response => {
      // transform data
      return transformedData;
    })).subscribe((products: IProducts[]) => {
      this.products = products;
    });
  }
Enter fullscreen mode Exit fullscreen mode

The component needs to know where to get the products and how to transform the response it gets. The component shouldn't be the one doing this as it makes the component unnecessarily complex.

Instead, create a products-facade.service.ts (the name is up to you) and move the above method to it.

Now the component only needs this.

private findAllProducts() {
    this.productsFacadeService.findAllBooks().subscribe((products: IProduct[]) => {
      this.products = products;
    });
}
Enter fullscreen mode Exit fullscreen mode

See how much simpler it is?

With this, the component goes to the facade and requests a list of products. Now, where the facade will get this information and if it will need some transformation are questions that don't concern the component. It's the facade's job to go and get what the component asks. It should deliver it in a way that the component only has to show it to the user.
You can think of the facade like a secretary or a butler (like Alfred and Batman).

If you are using some state service to manage data, it's the same idea.

Remember that the component should communicate only with the facade, so it doesn't have to know how this state service works or what methods it has. The component should go to the facade, and the facade should get the state information.

Only the facade should know where to get the information, the component doesn't have to.

Think of the interaction like this.
Component: Hey, the user typed their username and password. Check if it's a valid user.
Facade: Sure, I'll check and let you know.
Facade: It is a valid user. You can let him in.
Component: Ok, I'll tell him.

That's it. The component reacted to a user's action and asked the facade to verify the information. It got the response and delivered it to the user.

That way, you are separating responsibilities. Component with user interactions and facade with business logic.

Warning

Just be careful not to create a single facade to handle everything, ok? Otherwise, you will end up with a monster that is impossible to manage.

For me, it doesn't really matter how you choose to divide the facades.
For example, you can separate by domain (products, sales, login, etc), or by component, having one smaller facade for each component, or any other way you can think of.

What matters is that it makes sense and you keep to it through the whole project. It's pretty bad when you find that something works in one way in one part of the project and in a different way in another part.

That's the idea of this approach. To separate responsibilities. Component with user interactions and facade with business logic.

Remember this and try it on your next project.

Top comments (1)

Collapse
 
ng10x profile image
NG10x • Edited

You contradicted yourself in the 1st paragraph. Don't you think by adding a facade, you're making your life harder? This is adding an extra step to development in which makes the codebase more complexed and newcomers to get confused, this is exactly what a facade is.

The idea of using a facade is just an over engineered idea that does not apply to majority of projects. Don't know why people keep making post about this dying idea.