Decorators trong Typescript

Các bạn dev nào từng làm Angular chắc sẽ khá quen thuộc với Decorators đúng không? Nhưng bạn thật sự đã hiểu rõ về nó hay chưa? Chúng ta hãy cùng nhau ôn bài một tí nhé ^_^
Decorators trong Typescript
Decorators trong Typescript

TypeScript là một ngôn ngữ lập trình tuyệt vời. Nó cho phép bạn viết code tốt hơn trong hầu hết mọi trường hợp. Nó giúp chúng ta giảm thiểu được các lỗi mắc phải trong lúc viết code thay vì quăng lỗi vào mặt chúng ta trong lúc chạy =)).

Tuy nhiên, để trở thành một lập trình viên xịn xò và mạnh mẽ, chúng ta vẫn nên dành trọn trái tim của mình cho việc fix bug nhé <3.

Fix Bug

Hôm nay mình muốn chia sẻ với các bạn một tính năng có thể cải thiện rất nhiều quy trình code của chúng ta.

Let's start!

 

Decorators - nó là cái gì?

Decorator là một cách khai báo đặc biệt để có thể được đính kèm một số metadata khi khai báo các class, method, accessor, property hoặc các parameter. Decorator sử dụng từ khóa @expression, trong đó expression là tên một function sẽ được gọi khi runtime với thông tin được khai báo trong decorator.

Decorator không phải là một tính năng mới của TypeScript, mà thực sự nó đến từ JavaScript, là một đề xuất trong giai đoạn 2. Khi code được dịch bởi TypeScript, decorator sẽ wrap các thứ này lại và thêm vào các metadata.

Trong JavaScript thuần từ trước phiên bản ES6, khái niệm decorator cũng đã xuất hiện dưới dạng "functional composition" - wrap một function bằng một function khác.

Ví dụ: khi ta cần ghi log lại hoạt động của một function , ta có thể tạo 1 decorator function bao bọc lấy function cần thực hiện.

function doBusinessJob() {
    console.log('do my job')
}

function logDecorator(job) {
    return function () {
        console.log('start my job')
        var result = job.apply(this, arguments)
        return result
    }
}

var logWrapper = logDecorator(doBusinessJob)

Bản chất của decorators chỉ là các hàm JavaScript, có thể được “hook” vào các class, method, accessor, properties hoặc parameters.

Nếu bạn từng làm việc với React JS, chắc chắn bạn cũng đã nghe tới khái niệm Higher-Order Component, thì thực tế nó cũng hoạt động theo cách tương tự.

Làm nhẹ vài cái ví dụ nhé.

 

Không sử dụng decorators:

interface InitArguments {
    fuel: number;
}

class Rocket {
    fuel: number

    constructor(args: InitArguments) {
        this.fuel = args.fuel || 0
    }
}

class Falcon9 extends Rocket {}

class Starship extends Rocket {}

const falcon = new Falcon9({fuel: 100})

const starship = new Starship({fuel: 250})

 

Có sử dụng decorators:

function Init(args: InitArguments) {
    return <T extends { new (...args: any[]): {} }>(constructor: T) => {
        return class extends constructor {
            fuel = args.fuel || 0
        }
    }
}

interface InitArguments {
    fuel: number;
}

class Rocket {
    fuel: number
}

@Init({fuel: 100})
class Falcon9 extends Rocket {}

@Init({fuel: 250})
class Starship extends Rocket {}

const falcon = new Falcon9()
const starship = new Starship()

console.log(`Fueled Falcon9 with ${falcon9.fuel}T.`)
//Fueled Falcon9 with 100T.

console.log(`Fueled Starship with ${starship.fuel}T.`)
//Fueled Starship with 250T.

Phía bên dưới là đoạn code Javascript đã được Typescript transpiled. Constructor được wrap bởi hàm decorator, đó là cách mà thuộc tính fuel được thiết lập. 

Nếu bạn đã từng sử dụng Angular, đó chính xác là những gì xảy ra bên dưới với decorator @component@inject.

"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
function Init(args) {
    return (constructor) => {
        return class extends constructor {
            constructor() {
                super(...arguments);
                this.fuel = args.fuel || 0;
            }
        };
    };
}
class Rocket {
}
let Falcon9 = class Falcon9 extends Rocket {
};
Falcon9 = __decorate([
    Init({ fuel: 100 })
], Falcon9);
let Starship = class Starship extends Rocket {
};
Starship = __decorate([
    Init({ fuel: 250 })
], Starship);
const falcon = new Falcon9();
const starship = new Starship();
console.log(`Fueled Falcon9 with ${falcon9.fuel}T.`);
//Fueled Falcon9 with 100T.
console.log(`Fueled Starship with ${starship.fuel}T.`);
//Fueled Starship with 250T.

 

Multiple decorators

Chúng ta có thể khai báo multiple decorators cho đối tượng. Có 2 cách để triển khai như sau:

  • Trên cùng một hàng. Các decorator sẽ được dịch tuần tự từ trái qua phải. Các kết quả (results) sau đó sẽ là các functions được gọi tuần tự từ phải qua trái.
@foo @bar myFunction() {}

//foo(bar(myFunction))
  • Trên nhiều hàng. Các decorator sẽ được dịch tuần tự từ trên xuống dưới. Các kết quả (results) sau đó sẽ là các functions được gọi tuần tự từ dưới lên trên.
@foo 
@bar 
myFunction() {

}

//foo(bar(myFunction))

 

Các loại Decorator

Trong Typescript, có 5 loại decorator:

  • Class decorator
  • Method decorator
  • Property decorator
  • Accessor decorator
  • Parameter decorator

Có một thứ tự được xác định rõ ràng về cách áp dụng cho các kiểu khai báo decorator khác nhau bên trong một class:

  • Parameter Decorators, sau đó là Method Decorators, Accessor Decorators, hoặc Property Decorators:
    • Áp dụng cho từng instance member.
    • Áp dụng cho từng static member.
  • Parameter Decorators
    • Áp dụng cho constructor.
  • Class Decorators
    • Áp dụng cho class.

 

Class decorators

Class decorators được khai báo ngay trước đoạn khai báo class.

Class decorators được áp dụng cho constructor của class và có thể được sử dụng để observe, sửa đổi hoặc thay thế định nghĩa của class đó.

Không thể được khai báo trong tập tin declaration (thường là index.d.ts của một số packages) cũng như một vài context khác xung quanh (chẳng hạn khi bạn khai báo declare class).

@foo()
declare class Foo {} //Incorrect

Class decorators sẽ được gọi như một function lúc runtime, với constructor của class là parameter duy nhất.

Nếu Class decorators trả về một giá trị, nó sẽ thay thế định nghĩa class bằng hàm constructor được cung cấp.

Chú ý: Nếu bạn lựa chọn trả về một hàm constructor mới, bạn phải chú ý duy trì prototype ban đầu. Các logic áp dụng decorators sẽ không làm điều này cho bạn lúc runtime.

Sau đây là một ví dụ về class decorator (@sealed) được áp dụng cho class Greeter:

function sealed(constructor: Function) {
  Object.seal(constructor);
  Object.seal(constructor.prototype);
}

@sealed
class Greeter {
  greeting: string;
  constructor(message: string) {
    this.greeting = message;
  }
  greet() {
    return "Hello, " + this.greeting;
  }
}

Khi @sealed được thực thi, nó sẽ seal cả constructor và prototype của nó.

Còn đây là ví dụ về cách override constructor của class:

function classDecorator<T extends { new(...args: any[]): {} }>(constructor: T) {
    return class extends constructor {
        newProperty = "new property"
        hello = "override"
    }
}

@classDecorator
class Greeter {
    property = "property"
    hello: string
    constructor(m: string) {
        this.hello = m
    }
}

console.log(new Greeter("world"))

 

Method Decorators

Một Method Decorator được khai báo ngay trước khi khai báo method của class. Method Decorator được áp dụng cho Property Descriptor và có thể được sử dụng để observe, sửa đổi hoặc thay thế định nghĩa của method.

Không thể được khai báo trong tập tin declaration (thường là index.d.ts của một số packages), khi thực hiện overload cũng như một vài context khác xung quanh (chẳng hạn khi bạn khai báo declare class).

Biểu thức của method decorator sẽ được chạy bằng một function lúc runtime, với 3 tham số như sau:

  1. Hàm constructor của class cho static member, hoặc prototype của class cho instance member.
  2. Tên của member.
  3. Property Descriptor của member.

Chú ý: Property Descriptor sẽ là undefined nếu script target nhỏ hơn ES5.

Nếu method decorator trả về một giá trị, nó sẽ được sử dụng làm Property Descriptor cho method đó.

Chú ý: Giá trị trả về sẽ bị bỏ qua nếu script target nhỏ hơn ES5.

Sau đây là một ví dụ về method decorator (@enumerable) được áp dụng cho một method trên class Greeter:

function enumerable(value: boolean) {
    return function (
        target: any,
        propertyKey: string,
        descriptor: PropertyDescriptor
    ) {
        descriptor.enumerable = value;
    }
}

class Greeter {
    greeting: string;
    constructor(message: string) {
        this.greeting = message
    }

    @enumerable(false)
    greet() {
        return "Hello, " + this.greeting
    }
}

Decorator @enumerable(false) ở đây là một decorator factory. Khi decorator @enumerable(false) được gọi, nó sẽ sửa đổi property enumerable của property descriptor.

 

Accessor Decorators

Một Accessor Decorator được khai báo ngay trước một khai báo accessor. Accessor Decorator được áp dụng cho Property Descriptor của accessor và có thể được sử dụng để observe, sửa đổi hoặc thay thế các định nghĩa của accessor.

Không thể được khai báo trong tập tin declaration (thường là index.d.ts của một số packages) cũng như một vài context khác xung quanh (chẳng hạn khi bạn khai báo declare class).

Chú ý: TypeScript không cho phép decorating cả hai bộ accessor getset của một member duy nhất. Thay vào đó, tất cả các decorators cho member phải được áp dụng cho accessor đầu tiên được chỉ định trong thứ tự tài liệu. Điều này là do decorators áp dụng cho Property Descriptor, bộ này kết hợp cả hai accessor getset, mà không phải khai báo riêng biệt cho mỗi thứ.

Biểu thức của accessor decorator sẽ được chạy bằng một function lúc runtime, với 3 tham số như sau:

  1. Hàm constructor của class cho static member, hoặc prototype của class cho instance member.
  2. Tên của member.
  3. Property Descriptor của member.

Chú ý: Property Descriptor sẽ là undefined nếu script target nhỏ hơn ES5.

Nếu accessor decorator trả về một giá trị, nó sẽ được sử dụng làm Property Descriptor cho member đó.

Chú ý: Giá trị trả về sẽ bị bỏ qua nếu script target nhỏ hơn ES5.

Sau đây là ví dụ về accessor decorator (@configurable) được áp dụng cho một member của class Point:

function configurable(value: boolean) {
    return function (
        target: any,
        propertyKey: string,
        descriptor: PropertyDescriptor
    ) {
        descriptor.configurable = value;
    };
}

class Point {
    private _x: number;
    private _y: number;
    constructor(x: number, y: number) {
        this._x = x;
        this._y = y;
    }

    @configurable(false)
    get x() {
        return this._x;
    }

    @configurable(false)
    get y() {
        return this._y;
    }
}

 

Property Decorators

Property Decorator được khai báo ngay trước khi khai báo property.

Không thể được khai báo trong tập tin declaration (thường là index.d.ts của một số packages) cũng như một vài context khác xung quanh (chẳng hạn khi bạn khai báo declare class).

Biểu thức của property decorator sẽ được chạy bằng một function lúc runtime, với 2 tham số như sau:

  1. Hàm constructor của class cho static member, hoặc prototype của class cho instance member.
  2. Tên của member.

Chú ý: Property Descriptor không được cung cấp làm tham số cho Property Decorator do cách Property Decorator được khởi tạo trong TypeScript.

Điều này là do hiện tại không có cơ chế để mô tả thuộc tính của một instance khi khai báo các members của một prototype và không có cách nào để observe hoặc sửa đổi giá trị khởi tạo của một property. Giá trị trả về cũng bị bỏ qua. Do đó, một Property Decorator chỉ có thể được sử dụng để observe rằng một property của một name cụ thể đã được khai báo cho một class.

Chúng ta có thể sử dụng thông tin này để ghi lại metadata cho property, như trong ví dụ sau đây:

import "reflect-metadata";

const formatMetadataKey = Symbol("format");

function format(formatString: string) {
    return Reflect.metadata(formatMetadataKey, formatString);
}

function getFormat(target: any, propertyKey: string) {
    return Reflect.getMetadata(formatMetadataKey, target, propertyKey);
}

class Greeter {
    @format("Hello, %s")
    greeting: string;

    constructor(message: string) {
        this.greeting = message;
    }
    greet() {
        let formatString = getFormat(this, "greeting");
        return formatString.replace("%s", this.greeting);
    }
}

Decorator @format("Hello, %s") ở đây là một decorator factory. Khi @format("Hello, %s") được gọi, nó sẽ thêm một metadata cho property bằng cách sử dụng hàm Reflect.metadata từ thư viện reflect-metadata. Khi getFormat được gọi, nó sẽ đọc giá trị metadata cho việc format.

 

Parameter Decorators

Parameter Decorator được khai báo ngay trước khi khai báo tham số. Parameter Decorator được áp dụng cho function để khai báo parameter hoặc class constructor.

Không thể được khai báo trong tập tin declaration (thường là index.d.ts của một số packages), khi thực hiện overload cũng như một vài context khác xung quanh (chẳng hạn khi bạn khai báo declare class).

Biểu thức của Parameter Decorator sẽ được chạy bằng một function lúc runtime, với 3 tham số như sau:

  1. Hàm constructor của class cho static member, hoặc prototype của class cho instance member.
  2. Tên của member.
  3. Số thứ tự của parameter trong danh sách parameter của function.

Chú ý: Chỉ có thể sử dụng Parameter Decorator để observe rằng một parameter đã được khai báo trên một method.

Giá trị trả về của Parameter Decorator bị bỏ qua.

Sau đây là một ví dụ về Parameter Decorator (@required) được áp dụng cho parameter của member class Greeter:

import "reflect-metadata";

const requiredMetadataKey = Symbol("required");

function required(
    target: Object,
    propertyKey: string | symbol,
    parameterIndex: number
) {
    let existingRequiredParameters: number[] =
        Reflect.getOwnMetadata(requiredMetadataKey, target, propertyKey) || [];
    existingRequiredParameters.push(parameterIndex);
    Reflect.defineMetadata(
        requiredMetadataKey,
        existingRequiredParameters,
        target,
        propertyKey
    );
}

function validate(
    target: any,
    propertyName: string,
    descriptor: TypedPropertyDescriptor<Function>
) {
    let method = descriptor.value;
    descriptor.value = function () {
        let requiredParameters: number[] = Reflect.getOwnMetadata(
            requiredMetadataKey,
            target,
            propertyName
        );
        if (requiredParameters) {
            for (let parameterIndex of requiredParameters) {
                if (
                    parameterIndex >= arguments.length ||
                    arguments[parameterIndex] === undefined
                ) {
                    throw new Error("Missing required argument.");
                }
            }
        }

        return method.apply(this, arguments);
    };
}

class Greeter {
    greeting: string;

    constructor(message: string) {
        this.greeting = message;
    }

    @validate
    greet(@required name: string) {
        return "Hello " + name + ", " + this.greeting;
    }
}

Decorator @required thêm một metadata đánh dấu parameter name là bắt buộc. Sau đó, decorator @validate wrap method greet() trong một function để validate các tham số trước khi gọi method ban đầu.

 

Metadata

Một số ví dụ phía trên sử dụng thư viện reflect-metadata để thêm một polyfill cho experimental metadata API. Thư viện này chưa phải là một phần của tiêu chuẩn ECMAScript (JavaScript). Tuy nhiên, khi các decorators được chính thức chấp nhận như một phần của tiêu chuẩn ECMAScript, các phần mở rộng này sẽ được đề xuất áp dụng.

Cài đặt nó qua command line:

npm i reflect-metadata --save

TypeScript hỗ trợ một số tính năng thử nghiệm để tạo ra một số loại metadata nhất định cho các khai báo có decorators. Bạn có 2 cách để bật hỗ trợ tính năng thử nghiệm này.

Chạy command line:

tsc --target ES5 --experimentalDecorators --emitDecoratorMetadata

Hoặc cập nhật tsconfig.json:

{
  "compilerOptions": {
    "target": "ES5",
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  }
}

 

Tổng kết

Decorator, Metadata là các tính năng thử nghiệm và có thể dẫn đến các breaking changes trong tương lai.

Tuy nhiên, đây đều là các tính năng đã được xác nhận là đang (và sẽ) được implement vào JavaScript trong tương lai, nên ta có thể yên tâm sử dụng nó thông qua cách mà TypeScript cung cấp mà không phải quá lo lắng.

Nếu chết thì cùng chết cả đám thôi ấy mà =)))

 

Comments

Bài viết nổi bật

Dạo gần đây đi đâu cũng nghe nói về microservices, người người nhà nhà rục rịch chuyển dịch hệ thống sang microservices. Trước khi đưa ra sự so sánh, mình sẽ khái quát một chút về Monolith Application và MicroServices một chút cho các bạn chưa biết nắm rõ hơn nhé.
PHP là ngôn ngữ được sử dụng rộng rãi nhất trên thế giới trong lập trình web. Nó cũng bị ghét nhất. Nhưng tại sao nhiều developer lại ghét nó đến vậy? Hôm nay chúng ta hãy cùng tìm hiểu lý do xem chúng có thuyết phục không nhé ^_^
Lúc trước mình hay sử dụng cách này trên laptop phụ của mình, giờ mua license luôn rồi. Hôm nay mình xin chia sẻ cho bạn nào cần nhé.
JWT Tokens là một cách thức lưu trữ thông tin xác thực hiệu quả, nhưng làm cách nào để chúng ta có thể giúp chúng an toàn hơn? Có 2 cách thường dùng để lưu trữ JWT Tokens là LocalStorage và Cookies. Bây giờ chúng ta sẽ bắt đầu "mổ xẻ" các ưu - nhược điểm của mỗi loại nhé.
Có khá nhiều bạn đã yêu cầu mình một bài viết về Repository Design Pattern. Vậy mục đích của nó là gì? Nó có thực sự cần thiết cho ứng dụng của bạn hay không? Những điểm mạnh, điểm yếu của nó là gì? Chúng ta cùng đi sâu tìm hiểu qua bài viết này nhé.

Mục lục

Related posts

Triển khai Saga Pattern trong microservices với NodeJS và Choreography-Based Saga
Mô hình Saga đưa ra một giải pháp có cấu trúc để giải quyết thách thức này. Nó cung cấp một phương pháp có hệ thống để quản lý transaction qua nhiều microservices. Điều này giải quyết những phức tạp của các transaction phân tán và hoàn toàn tương thích với các nguyên tắc của kiến trúc microservices, được đặc trưng bởi sự kết nối lỏng lẻo và khả năng triển khai độc lập của các service.
Một API cho phép giao tiếp hai chiều giữa các ứng dụng phần mềm thông qua các requests. Một Webhook là một API nhẹ, hỗ trợ chia sẻ dữ liệu một chiều được kích hoạt bởi các events.
Một trong những câu hỏi được đặt thường xuyên nhất về TypeScript là liệu chúng ta nên sử dụng interface hay type. Câu trả lời cho câu hỏi này, giống như nhiều câu hỏi lập trình khác, là nó phụ thuộc vào tình hình cụ thể. Trong một số trường hợp, một cái có lợi thế rõ rệt hơn cái kia, nhưng trong nhiều trường hợp, chúng có thể thay thế cho nhau.
Đây là các types cơ bản nhưng cũng phổ biến nhất trong Typescript. Một số types khác phức tạp hơn cũng được xây dựng dựa trên những types cơ bản này.
Trong thế giới lập trình, trách nhiệm lớn nhất của chúng ta không phải chỉ làm cho code chạy được, mà còn phải đảm bảo rằng các đoạn code mà chúng ta viết có thể dễ dàng kiểm tra và bảo trì trong một khoảng thời gian dài.
Phân trang - một thành phần không thể thiếu trong các ứng dụng có lượng dữ liệu lớn. Tuy nhiên, bạn hiểu được bao nhiêu về nó?
Javascript là một thành phần không thể thiếu đối với frontend developers. Tuy nhiên, ngay từ lúc ra đời, nó đã tồn tại khá nhiều vấn đề cần khắc phục. Đó là lý do tại sao từ 2015 (ES6) tới 2021 (ES12) ra đời nhằm giúp Javascript trở nên tốt hơn.
Dạo này mình làm việc với mấy bạn trên github, thấy hay xài mấy từ viết tắt mà mình không hiểu lắm. Thôi thì tổng hợp lại một list các từ viết tắt hay dùng trong github luôn cho ai cần :D
Dạo gần đây đi đâu cũng nghe nói về microservices, người người nhà nhà rục rịch chuyển dịch hệ thống sang microservices. Trước khi đưa ra sự so sánh, mình sẽ khái quát một chút về Monolith Application và MicroServices một chút cho các bạn chưa biết nắm rõ hơn nhé.
Cách bỏ qua câu lệnh --set-upstream quen thuộc cho các con lười
Mình sẽ giới thiệu 2 cách để xóa một property trong Javascript Object. Một cách sử dụng mutable - toán tử delete, một cách còn lại là immutable - tính năng Object Restructuring.

Tin mới nhất

Triển khai Saga Pattern trong microservices với NodeJS và Choreography-Based Saga
Mô hình Saga đưa ra một giải pháp có cấu trúc để giải quyết thách thức này. Nó cung cấp một phương pháp có hệ thống để quản lý transaction qua nhiều microservices. Điều này giải quyết những phức tạp của các transaction phân tán và hoàn toàn tương thích với các nguyên tắc của kiến trúc microservices, được đặc trưng bởi sự kết nối lỏng lẻo và khả năng triển khai độc lập của các service.
Một API cho phép giao tiếp hai chiều giữa các ứng dụng phần mềm thông qua các requests. Một Webhook là một API nhẹ, hỗ trợ chia sẻ dữ liệu một chiều được kích hoạt bởi các events.
Một trong những câu hỏi được đặt thường xuyên nhất về TypeScript là liệu chúng ta nên sử dụng interface hay type. Câu trả lời cho câu hỏi này, giống như nhiều câu hỏi lập trình khác, là nó phụ thuộc vào tình hình cụ thể. Trong một số trường hợp, một cái có lợi thế rõ rệt hơn cái kia, nhưng trong nhiều trường hợp, chúng có thể thay thế cho nhau.
Trong phần này, chúng ta sẽ tìm hiểu một số khái niệm cơ bản nhất về AWS là gì và một số lợi ích khi sử dụng AWS.
Trở thành một software developer hiệu suất cao không phải là điều dễ dàng. Điều này đòi hỏi bạn phải có kỹ năng và kiến thức về lập trình, cũng như cách tiếp cận và giải quyết các vấn đề phức tạp. Tuy nhiên, nếu bạn có chút kiên nhẫn và sự nỗ lực, bạn hoàn toàn có thể trở thành một developer tài năng và thành công.
Đây là các types cơ bản nhưng cũng phổ biến nhất trong Typescript. Một số types khác phức tạp hơn cũng được xây dựng dựa trên những types cơ bản này.
Trong thế giới lập trình, trách nhiệm lớn nhất của chúng ta không phải chỉ làm cho code chạy được, mà còn phải đảm bảo rằng các đoạn code mà chúng ta viết có thể dễ dàng kiểm tra và bảo trì trong một khoảng thời gian dài.
Thông tin được định nghĩa dưới dạng dữ liệu, kiến thức về thông tin, và trí tuệ về tri thức.
Phân trang - một thành phần không thể thiếu trong các ứng dụng có lượng dữ liệu lớn. Tuy nhiên, bạn hiểu được bao nhiêu về nó?
Javascript là một thành phần không thể thiếu đối với frontend developers. Tuy nhiên, ngay từ lúc ra đời, nó đã tồn tại khá nhiều vấn đề cần khắc phục. Đó là lý do tại sao từ 2015 (ES6) tới 2021 (ES12) ra đời nhằm giúp Javascript trở nên tốt hơn.
Dạo này mình làm việc với mấy bạn trên github, thấy hay xài mấy từ viết tắt mà mình không hiểu lắm. Thôi thì tổng hợp lại một list các từ viết tắt hay dùng trong github luôn cho ai cần :D
Triển khai Saga Pattern trong microservices với NodeJS và Choreography-Based Saga
Mô hình Saga đưa ra một giải pháp có cấu trúc để giải quyết thách thức này. Nó cung cấp một phương pháp có hệ thống để quản lý transaction qua nhiều microservices. Điều này giải quyết những phức tạp của các transaction phân tán và hoàn toàn tương thích với các nguyên tắc của kiến trúc microservices, được đặc trưng bởi sự kết nối lỏng lẻo và khả năng triển khai độc lập của các service.
Một API cho phép giao tiếp hai chiều giữa các ứng dụng phần mềm thông qua các requests. Một Webhook là một API nhẹ, hỗ trợ chia sẻ dữ liệu một chiều được kích hoạt bởi các events.
Một trong những câu hỏi được đặt thường xuyên nhất về TypeScript là liệu chúng ta nên sử dụng interface hay type. Câu trả lời cho câu hỏi này, giống như nhiều câu hỏi lập trình khác, là nó phụ thuộc vào tình hình cụ thể. Trong một số trường hợp, một cái có lợi thế rõ rệt hơn cái kia, nhưng trong nhiều trường hợp, chúng có thể thay thế cho nhau.
Đây là các types cơ bản nhưng cũng phổ biến nhất trong Typescript. Một số types khác phức tạp hơn cũng được xây dựng dựa trên những types cơ bản này.