# Xây dựng 1 ứng dụng Angular\_\_\_BestPractice1

### Clean và Performant?&#x20;

Trong năm qua *2018*, nhóm của chúng tôi đang/đã tinh chỉnh ứng dụng cả về các tiêu chuẩn và hiệu suất mã hóa để làm cho nó ở trạng thái tốt nhất có thể.  Bài viết này phác thảo quá trình thực hành của chúng tôi.

Nó có liên quan đến ***Angular***, ***Typescript***, ***RxJs*** và ***@ngrx/store***. Chúng tôi cũng sẽ đi qua một số nguyên tắc mã hóa chung ***(rules render)*** để giúp cho ứng dụng của bạn trong tương lai trở nên sạch & hoạt động chỉn chu hơn.

## **1) Sử dụng trackBy**

Khi sử dụng ***ngFor*** để lặp qua một *mảng(array)* trong các khuôn mẫ&#x75;***(ng-template)***, hãy sử dụng nó với một hàm ***trackBy*** sẽ trả về một mã định danh duy nhấ&#x74;***(unique identifier)*** cho mỗi mụ&#x63;**(item)**.

### **Why?**

Khi một mảng ***(array)*** thay đổi, Angular sẽ render lại ***(re-renders)*** toàn bộ cây DOM. Nhưng nếu bạn sử dụng ***`trackBy`***, Angular  sẽ biết phần t&#x1EED;***(element)*** nào đang/đã được thay đổi và sẽ chỉ thực hiện thay đổi DOM cho phần tử cụ thể đó.  Để có giải thích thêm về điều này có thể xem tại đây: [**@NetanelBasal**](https://medium.com/@NetanelBasal)

**Before:**

```typescript
<li *ngFor="let item of items;">{{ item }}</li>
```

### After:

```typescript
// in the template
<li *ngFor="let item of items; trackBy: trackByFn">{{ item }}</li>
// in the component
trackByFn(index, item) {    
   return item.id; // unique id corresponding to the item
}
```

## **2) Sử dụng const vs let**

&#x20;Khi khai báo biến, hãy sử dụng ***const*** khi giá trị không được gán lại (***reassigned***).

### **Why?**

* Sử dụn&#x67;**`let`** &&**`const`** ở những trường hợp thích hợp nhất sẽ giúp cho việc khai báo các biến rõ ràng hơn.&#x20;
* Nó cũng sẽ giúp xác định các vấn đ&#x1EC1;**(Intifying issues**) khi một giá trị được gán lại vô tình bằng cách ném một lỗi khi ta biên dịch (throwing a compile time error).
* Nó cũng giúp cải thiện(**improve**) khả năng đọc mã (**readability of the code**).

### Before:

```typescript
let car = 'ludicrous car';
let myCar = `My ${car}`;
let yourCar = `Your ${car};
if (iHaveMoreThanOneCar) {
   myCar = `${myCar}s`;
}
if (youHaveMoreThanOneCar) {
   yourCar = `${youCar}s`;
}
```

### After:

```typescript
// the value of car is not reassigned, so we can make it a const
const car = 'ludicrous car';
let myCar = `My ${car}`;
let yourCar = `Your ${car};
if (iHaveMoreThanOneCar) {
   myCar = `${myCar}s`;
}
if (youHaveMoreThanOneCar) {
   yourCar = `${youCar}s`;
}
```

## **3) Sử dụng Pipeable operators**

&#x20;Sử dụng ***pipeable operators*** khi sử dụng ***RxJs operators***.

### Why?

Các toán tử Pipeable là cây có thể thay đổi được (***tree-shakeable***) nghĩa là chỉ có mã chúng ta cần thực thi sẽ được đưa vào khi chúng đã được ***Imported***.

Điều này cũng giúp dễ dàng xác định các toán tử nào không sử dụng (***identify unused operators***) trong các tệp (\*\*.ts).

*Chú ý:*  Điều này hoạt động trên phiên bản Angular version 5.5+.

### Before:

```typescript
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/take';
iAmAnObservable
    .map(value => value.item)
    .take(1);
```

### **After:**

```typescript
import { map, take } from 'rxjs/operators';
iAmAnObservable
    .pipe(
       map(value => value.item),
       take(1)
     );
```

## **4) Isolate API hacks (Hash code để fix issue cho API) :)) có thể hiểu là vậy**&#x20;

Không phải tất cả API đều trả về kết quả ngay ở component khi được gọi (***bullet proof***) — đôi khi chúng ta cần thêm một số logic vào mã để bù đắp lỗi trong các API s. Thay vì gọi api trong các components cần thiết, tốt hơn là cô lập chúng ở một nơi - như trong một ***service***  và sử dụng ***service*** từ ***component***.&#x20;

### **Why?**

Khi sửa lỗi trong các API, việc tìm kiếm chúng dễ dàng hơn trong một tệp thay vì phải tìm kiếm ở trong các **components** có thể được trải rộng ở toàn bộ **code**.&#x20;

Bạn cũng có thể tạo các thẻ tùy chỉnh như API\_FIX tương tự như TODO và gắn thẻ các bản sửa lỗi với thẻ để dễ tìm hơn.

### Before:

```typescript
// component
export class AppComponent {
  data$;
  contructor(private http: HttpClient) {}
  
  this.data$ = this.http.get('/api/todo')
    .pipe(
       map(value => value.items),
       catchError(err => of(err))
     );  
}
```

### After:

```typescript
// component
export class AppComponent {
  data$;
  contructor(private _todoservice: TodoService) {}
  
  this.data$ = _todoservice.getAll()
    .pipe(
       map(value => value.items)
     );  
}
```

## **5) Subscribe in template**

Tránh đăng ký các  subscribing to observables  từ các component và thay vào đó hãy đăng ký các  subscribing to observables từ template

### **Why?**

**async** pipe tự hủy đăng ký tự độn&#x67;**(*****unsubscribe themselves automatically***) và nó làm cho mã đơn giản hơn bằng cách loại bỏ sự cần thiết phải quản lý ***subscriptions*** theo cách thủ công. Nó cũng làm giảm nguy cơ vô tình quên để hủy đăng ký ***unsubscribe***  của một ***subscriptions***  trong component, mà sẽ gây ra một rò rỉ bộ nhớ(***memory leak***). Nguy cơ này cũng có thể được giảm thiểu bằng cách sử dụng quy tắc lint-rule để phát hiện các ***unsubscribed*** chưa được hủy.

Điều này cũng ngăn các ***component*** khỏi trạng thái trạng thái và các lỗi của dữ liệu bị đột biến bên ngoài ***subscriptions***.

### Before:

```typescript
// template
<p>{{ textToDisplay }}</p>
// component
iAmAnObservable
    .pipe(
       map(value => value.item),
       takeUntil(this._destroyed$)
     )
    .subscribe(item => this.textToDisplay = item);
```

### After:

```typescript
// template
<p>{{ textToDisplay$ | async }}</p>
// component
this.textToDisplay$ = iAmAnObservable
    .pipe(
       map(value => value.item)
     );
```

## **6) Clean up subscriptions**

Khi ***subscribing to*** ***observables**,* luôn đảm bảo bạn đã ***unsubscribe*** chúng một cách thích hợp bằng cách sử dụng toán tử như: take, takeUntil, v.v.

### **Why?**

### Before:

### After:

## **7) Use appropriate operators**

### &#x20;**Why?**

### Before: <a href="#before-5" id="before-5"></a>

### After: <a href="#after-5" id="after-5"></a>

## **8) Lazy load**

### **Why?**

### Before: <a href="#before-5" id="before-5"></a>

### After: <a href="#after-5" id="after-5"></a>

## **9) Avoid having subscriptions inside subscriptions**

### &#x20;**Why?** <a href="#why-7" id="why-7"></a>

### Before: <a href="#before-5-2" id="before-5-2"></a>

### After: <a href="#after-5-2" id="after-5-2"></a>

## **10) Avoid any; type everything;**

### &#x20;**Why?** <a href="#why-7" id="why-7"></a>

### Before: <a href="#before-5-2" id="before-5-2"></a>

### After: <a href="#after-5-2" id="after-5-2"></a>

## **11) Make use of lint rules**

### &#x20;**Why?** <a href="#why-7" id="why-7"></a>

### Before: <a href="#before-5-2" id="before-5-2"></a>

### After: <a href="#after-5-2" id="after-5-2"></a>

## **13) Small reusable components**

### &#x20;**Why?** <a href="#why-7" id="why-7"></a>

### Before: <a href="#before-5-2" id="before-5-2"></a>

### After: <a href="#after-5-2" id="after-5-2"></a>

## **14) Components should only deal with display logic**

### &#x20;**Why?** <a href="#why-7" id="why-7"></a>

### Before: <a href="#before-5-2" id="before-5-2"></a>

### After: <a href="#after-5-2" id="after-5-2"></a>

## **15) Avoid long methods**

### &#x20;**Why?** <a href="#why-7" id="why-7"></a>

### Before: <a href="#before-5-2" id="before-5-2"></a>

### After: <a href="#after-5-2" id="after-5-2"></a>

## **16) DRY**

### &#x20;**Why?** <a href="#why-7" id="why-7"></a>

### Before: <a href="#before-5-2" id="before-5-2"></a>

### After: <a href="#after-5-2" id="after-5-2"></a>

## **17) Add caching mechanisms**

### &#x20;**Why?** <a href="#why-7" id="why-7"></a>

### Before: <a href="#before-5-2" id="before-5-2"></a>

### After: <a href="#after-5-2" id="after-5-2"></a>

## **18) Avoid logic in templates**

## &#x20;**19) Strings should be safe**

## **Bigger picture**

*Xem thêm tại đây:* [*best practices for a clean and performant angular application*](https://medium.freecodecamp.org/best-practices-for-a-clean-and-performant-angular-application-288e7b39eb6f)*.*
