+10 clean code rules from Angular developer

Hi, Habr!

Today I wanted to touch on the topic of correct code in working with Angular. These recommendations will make your code more effective in practical application, as well as allow me to be less demanding on code from juniors.

1. Avoid logic in patterns

And the first thing I want to mention is the logic in patterns. If you have some kind of logic in your templates, even if it's simple &&, it is useful to extract it into your component. The presence of logic in the template means that it is impossible to test it, and therefore it is more prone to errors when changing the template code.

<p *ngIf="isShow"> Example </p>

publicngOnInit(): void {
    this.isShow = true;

2. "Safe" strings

Suppose you have a variable of type string, which can only have a specific set of values. Instead of declaring it as a string type, you can declare this list of possible values ​​as a type.

privatevalue: 'One' | 'Two';
if (isShow) { 
   value = 'One'; 
} else { 
   value = 'Two' 

By declaring the type of a variable in this way, we can avoid errors when writing code at compile time, rather than at run time.

3. The rule of long methods.

Here, the demonstration of the code is unnecessary. It is important to understand that no one likes long methods.
Long methods usually indicate that they do too many things. Perhaps the method itself does one thing, but inside it there are several other operations that can be put into another own method with a logical purpose. Long methods are difficult to read, understand and maintain. They are also error prone, as changing one thing can affect many other things in this method. Sure, not for me alone, such methods make refactoring (which is key in any application) more difficult than it could be.

4. Duplication of code

If you have a code that is repeated in different places in the project. Extract the duplicate code into a separate method and use it instead of duplicate code.

The problem with code duplication is that if we want to make changes to the logic of this code, we have to do it in several places. This makes it difficult to maintain the code, which in turn increases the risk of bugs. It also takes more time to make changes to the logic. With less duplicate code, the application will be faster.

5. trackBy

Let's dilute the list of the subtleties of working with Angular.

Often used by ngFor to iterate through an array in templates, often in practice it is deprived of such a function as trackBy. Use it with ngFor. Thanks to such trifles you will receive a unique identifier for each element.

<li *ngFor="let item of items; trackBy: trackByFn">{{ item }}</li>

trackByFn(index, item) {    
   return item.id; // уникальный идентификатор, соответствующий элементу

When the array is changed, Angular re-displays the entire DOM tree. But if you use trackBy, Angular will know which element has changed and will only change the DOM for that particular element.

6. Subscribe in the template

Pay attention to the example of the subscription to the observed component:

<p>{{ text }}</p>

       map(value => value.item),
    .subscribe(item =>this.text = item);

Now you see how not to do it. Not that I urged you to strictly follow my recommendations, but often the developers do not understand what is happening in their code. So why is it bad and how to do well? The fact is that we risk getting a random subscription from a subscription to a component, which can lead to a memory leak. The best option is to use a subscription in the template itself:

<p>{{ text$ | async }}</p>

this.text$ = blablaObservable
       map(value => value.item)

Thanks to async, we can not care about unsubscribing, because it does it automatically, and this simplifies the code, eliminating the need to manually manage subscriptions. It also reduces the risk of accidentally canceling a subscription to a subscription in the component I mentioned above.

7. Lazy loading

Whenever possible, use lazy loading of modules in your Angular application. Lazy loading is when you load something only when it is used, for example, loading a component only when you need to see it. This will reduce the size of the loaded application and can improve the loading time of the application without loading modules that are not used.

// app.routing.ts

  path: 'dashboard',
  loadChildren: 'lazy-load.module#DashboardModule' 

8. Subscription within a subscription

Sometimes you may need values ​​from more than one observable to perform an action. In this case, avoid subscribing to one observable in the subscription block of another observable. Instead, use the appropriate chaining operators. Chaining operators are run on observables from the operator in front of them. Some chain operators, such as withLatestFrom, combineLatest, etc ...


.subscribe(oneValue => {
    .subscribe(twoValue => {
        console.log([oneValue, twoValue].join(', '));


.subscribe(([oneValue, twoValue]) => {
    console.log([oneValue, twoValue].join(', '));

9. Caching

When making requests to the API, the responses from some of them often do not change. In these cases, you can add a caching mechanism and save the value from the API. When the request should be repeated to the same API, check if the value in the cache is in it, and if so, use it. Otherwise, make an API call and cache the result. If necessary, you can enter the cache time, where you can check when it was last, and decide whether to call the API. The presence of a caching mechanism allows you to avoid unwanted requests to the API. Thanks to this avoidance of duplicate request, the speed of the application improves, since we do not need to wait for a response and thereby download the same information again and again.

10. Crushing on reusable components

Divide large components into smaller ones. Simplify such components and make them as stupid as possible, as this will make them work in more scenarios. The creation of such a component means that the component has no special logic in itself and works solely on the basis of the inputs and outputs provided to it. As a rule, the last child in the component tree will be the simplest of all. This is done on the basis of the ease of use of such components, such components have less chance of getting errors. Also, reusable components reduce code duplication, which makes it easier to maintain and make changes.

Do you want to continue this column?

Also popular now: