Skip to content

Clean Code & Refactoring

Hướng dẫn thực tế về cách chúng tôi áp dụng các nguyên tắc SOLID, DRY và SRP để duy trì một codebase bền vững và dễ mở rộng.

Nguyên tắc Trách nhiệm Đơn lẻ (SRP)

Mỗi class, module hay hook chỉ nên làm một việc duy nhất. Chúng tôi tách biệt rõ ràng giữa Business Logic, Data Access và Presentation.

Đừng lặp lại chính mình (DRY)

Tránh trùng lặp code bằng cách trừu tượng hóa các logic dùng chung vào Services hoặc Utilities. Ví dụ: TokenService và UserUtils.

1. Chiến lược SOLID trong Thực tế

Chúng tôi không chỉ nói về lý thuyết. Trong Data Explorer, SOLID được áp dụng để giải quyết các vấn đề hữu hình về khả năng mở rộng.

Open/Closed & Factory Pattern

Khi thêm một Database Engine mới, chúng tôi không sửa đổi core logic. Thay vào đó, chúng tôi tạo một Adapter mới và đăng ký nó vào Factory.
Database Strategy Factory

# // Tuân thủ nguyên tắc Open/Closed

export class DatabaseFactory {

private static strategies = new Map<string, DatabaseStrategy>();

static register(key: string, strategy: DatabaseStrategy) {

this.strategies.set(key, strategy);

}

static get(key: string): DatabaseStrategy {

return this.strategies.get(key) ?? new DefaultStrategy();

}

}

Interface Segregation (ISP)

Thay vì một Interface khổng lồ, chúng tôi chia nhỏ thành IReadable, IWritable, IMetadataProvider giúp các adapter chỉ cần triển khai những gì nó thực sự hỗ trợ.

2. Tách biệt Trạng thái & Logic (Frontend)

Chúng tôi tránh việc viết logic xử lý dữ liệu trực tiếp trong React Components. Thay vào đó, chúng tôi sử dụng Custom Hooks kết hợp với ApiService.
ApiService (DRY)

Tự động chèn Bearer Token và xử lý lỗi 401 (Logout) một cách tập trung.

Modular Hooks (SRP)

useProfileLogic được chia nhỏ thành useUserProfile, useUserSettings, useAccountSecurity.

3. Kiểm thử với Vitest

Để đảm bảo việc refactor không làm hỏng các tính năng hiện có, chúng tôi áp dụng Unit Testing cho các core services và logic hooks.
Testing ApiService

describe('ApiService', () => {

it('should inject authorization header', async () => {

const response = await ApiService.get('/profile');

expect(global.fetch).toHaveBeenCalledWith(

expect.stringContaining('/profile'),

expect.objectContaining({ headers: { Authorization: 'Bearer mock-token' } })

);

});

});

💡 Mẹo: Sử dụng `vi.stubGlobal('fetch', mock)` và `vi.mock('@/core/services/store')` để giả lập môi trường chạy tests một cách cô lập.

Quy trình Refactoring: Từ Legacy sang Clean

Refactoring là hành trình liên tục. Chúng tôi áp dụng chiến lược "Boy Scout Rule": Luôn để lại codebase sạch hơn lúc bạn mới tìm thấy nó.
  • 1
    Bước 1: Cô lập (Isolation)

    Xác định logic hỗn loạn và bao bọc nó bằng một Interface.

  • 2
    Bước 2: Viết Test (Cover)

    Viết Unit Tests để bảo vệ hành vi hiện tại trước khi thay đổi.

  • 3
    Bước 3: Chia nhỏ (Decomposition)

    Bóc tách logic vào các Service nhỏ hơn tuân thủ SRP.

  • 4
    Bước 4: Bơm phụ thuộc (Injection)

    Thay thế việc khởi tạo trực tiếp (`new`) bằng Dependency Injection.

Sẵn sàng khám phá dữ liệu?

Tham gia cộng đồng trên GitHub để đóng góp cho IDE cơ sở dữ liệu địa phương thông minh nhất.

Mở Ứng dụng