Avoid these bad practices when you are an Angular developer
Since its first appearance, Angular came with a whole set of new features that made web developers life’s much easier and also reduced the costs of creating apps. Among these features, the framework have a cleaner architecture based on MVC, High Speed and optimized performance that was reinforced with the ivy project, Typescript compatibility, integrated routing system and efficient ways for data binding, etc.…
Because of these elements Angular gained a huge ground in the world of web apps as many enterprises and teams are adopting it for their projects. But like any powerful tool if not used correctly, it can cause some damages to its user. So, in this article we will highlight common mistakes made by developers and we will present solutions to remediate to them.
You should know well the tools you are using
One of the most important advantages of Angular is its architecture that made clean code writing much easier than the classical JQuery spaghettis code that developers used to write in the previous years.
This architecture has a set of building blocks like services (that helps us organize business logic like data manipulation, interaction with external API’s) and components (that displays application’s data and captures user interaction), pipes, directives, etc…
The most common set of bad practices on Angular apps are related to violations of the Separation of concerns principle, maybe this can be due to the lack of knowledge of the framework or the ignorance of clean code or the rush to deliver the project as quick as possible. There are many examples that can illustrate this bad practice but we took one simple case to demonstrate it
Write external system interactions inside component
It’s better to write external API calls and data manipulation in a service because it is designed to do that. Let’s have a look at the code below
This code has 2 major flaws:
- We polluted the constructor with some business logic that is not supposed to be there. In general a constructor should only contains initializations.
- We wrote code that connects to Github API within the component which is the bad place to put such a code. In our example we are simply calling an URL without doing much work for preparing the request but once we want to create a more complex request the problem will be more highlighted. A component is supposed to handle user interaction and displays data without carrying about the request itself (endpoint, headers, etc…). Secondly with such a practice we reduced the reusability of this code by other components that have to recreate this logic for connecting to the API.
So such component should be refactored to something like this:
We created a class called Repository that will contains the serialization of the JSON returned by the API (we will talk about typescript later in the article) and then we moved the API interaction into a specific service and after that we called it from our component.
Misusing or not using some Angular features
As mentioned before Angular ecosystem has many components that helps developers but many of them are not used at all or misused by developers. The most common bad usage practices concerns mainly Directives and Pipes.
Directives: are simply classes that extends HTML elements with new functionalities and apply custom code to them (Documentation).
In many cases developers tend to write Directives that are useless and can be replaced with simply CSS Selector especially the ones that comes with styling enrichments.
In other cases we saw some directives that have a complex logic for retrieving data and manipulating them which violates their purpose of rendering data (in simple or complex ways). So we need to decouple such a logic into separate service.
Pipes: they are defined to be functions that transforms an input to a required format and they are directly applied on the template. Let’s have look at the code below where user has to input a file size in bytes and then our program will convert it to a more readable human format in megabyte
This major problem with this code is that if we want to reuse the logic of file size formatting in any other components then we have to replicate it or we can extract it in a separate function but Fortunately there is more elegant way to refactor this code using pipes :)
At first we have to create our pipe
And then we can call that pipe inside our component in whatever places we want to format file sizes.
We can enhance our pipe by allowing each caller to specify the unit of size (GB, TB, etc…) but we just used the example to demonstrate how to use pipes to refactor our code without entering into pipes details.
Don’t forget to unsubscribe
In Angular applications, we always have to connect to services for fetching data. But if these subscriptions are managed badly they can lead to memory leaks. Let’s take for example a simple application with a service that pushes values at regular interval time and a component who subscribes to it and log the value on the console:
Nothing seems wrong with this code! And we can see the emitted values displayed on the console.
Surprise !! the problem comes when we navigate to another component we can see on the console that the subscription is still alive and emitting values and once we go back to it again a new subscription is created along with the old one which at a given moment can lead to a memory leak problem.
So please don’t forget to unsubscribe when you finished using the Observable. There are many ways to do so:
- By calling manually the unsubscribe() function.
- Using the takeWhile() operator [Documentation].
- - Or with the takeUntil() operator which I personally use in managing those behaviours [Documentation]
Shake your code
One of the most important advantages that were delivered by angular team since its 9th version is ivy that allowed to deliver smaller bundles which means less time to load your application and also it facilitated debugging and testing.
Even Ivy is the only option for rendering angular application since version 12 but you can implement such feature in your application if it is based on Angular 9 or higher by following the official documentation
What about typescript?
One of the most important advantages of typescript is making code cleaner and easier to read and maintain, as it introduced the power of OOP into front-end’s world.
Many developers find the practice of typing their data and writing interfaces code, a time consuming task so they usually use the magic any keyword which in many cases can generate exceptions that cannot be spotted at early development stages. As an example we can take the code below
This code compiles correctly but when we try to run it, we get an undefined displayed on the console as the user variable passed to parameter does not have a property called identifier. But if we change the any keyword with the type of user we will get a compilation error so we can identify the problem earlier and then we will have less undefined in runtime.
Final words
In this article we did a quick tour on some common bad practices on Angular. Please let us know if you spotted other ones in your teams to enrich the list above.
Thanks for reading,
Fadi