Dao partern và Repository partern

- 5 mins

Trong các hệ thống phần mềm của chúng ta, phần quan trọng nhất luôn là lớp business, trong lớp này thường tồn tại một thành phần đó là data access layer - kết nối các dịch vụ với các thành phần lưu trử dữ liệu. Việc access data tuỳ thuộc vào loại lưu trử, có thể là file system hoặc database thậm chí là các loại database khác nhau trong việc chọn và triển khai. Chúng ta thường có các phương pháp, các mẫu xử lí để thực hiện những thao tác data access nói trên trong đó có thể kể đến DAO partern(Data Access Object) và Repository partern. Qua một vài dự án thực tế được trãi nghiệm với 2 mẫu trên mình chia sẻ một chút về cái nhìn cái nhân đối với hai mẫu phương pháp này.

DAO partern:

Mục tiêu của partern này là trừu tượng hoá và đóng gói tất cả quyền truy cập vào data sau đó cung cấp một interface cho business logic code sài. DAO đóng vai trò như một lớp trung gian giữa domain model logic và data storage. Nó ánh xạ các thao tác với domain model sang các thao tác với table trong database hoặc sang các thao tác với file trong file system. Chúng ta có thể tham khảo một ví dụ triển khai đơn gian như sau:

Domain model của chúng ta có một class User và các behavior với data storage của domain này được định nghĩa sẳn trong UserDAOInterface:

// domain/address.ts
class Address {
    public country : string;
    public city: string;
    public district : string; 
}

// domain/user.ts
class User {
    public id : number;
    public fullName : string;
    public address : Address;
    public email : string;
    public tel : string;
}

// domain/user_dao.ts
interface UserDAOInterface {
    create(user : User) : User;
    getAll() : User[];
    get(id : string) : User;
    update(user : User) : void;
    delete(user : User) : void;
}

Tiếp theo chúng ta sẻ tiến hành implement các interface thông qua các data mapper cho loại data storage đã pick, ở đây là PostgreSQL với typeorm:

// interface/postgres/user.ts
import {Entity, PrimaryGeneratedColumn, Column} from "typeorm";

@Entity()
export class UserDAO implements UserDAOInterface{

    @PrimaryGeneratedColumn()
    id : number;

    @Column()
    full_name : string;

    @Column()
    public country : string;

    @Column()
    city: string;

    @Column()
    district : string; 

    @Column()
    email : string;

    @Column()
    tel : string;

    public fromDomain(user : User) : PgUser{
        return new PgUser({
            user.id,
            user.fullName,
            user.address.country,
            user.address.city,
            user.address.district,
            user.email,
            user.tel,
        })
    }

    public toDomain() : User{
        const address = new Address({
            this.country,
            this.city,
            this.district
        })
        return new User({
            this.id,
            this.fullName,
            address,
            this.email,
            this.tel,
        })
    }

    // Implementations

    public create(user : User) : User {
        ...............
    }

    public getAll() : User[] {
        ...............
    }

    public get(id : string) : User{
        ...............
    }

    public update(user : User) : void{
        ...............
    }

    public delete(user : User) : void{
        ...............
    }
}

Tiếp đó, business logic của chúng ta chỉ việc sử dụng các implementations này thông qua interface UserDAOInterface mà không cần biết bên trong được implement như thế nào.

Nhìn vào đó chúng ta có thể dễ dàng thấy các ưu điểm của DAO là:

comments powered by Disqus
rss facebook twitter github gitlab youtube mail spotify lastfm instagram linkedin google google-plus pinterest medium vimeo stackoverflow reddit quora quora