Thiết Kế Dữ Liệu Cho Angular Như Một Hệ Quản Trị Cơ Sở Dữ Liệu: Chìa Khóa Cho Ứng Dụng Khổng Lồ!
Lê Lân
0
Cấu Trúc Dữ Liệu Như Một Hệ Quản Trị Cơ Sở Dữ Liệu Để Đảm Bảo Khả Năng Mở Rộng Cho Ứng Dụng Angular
Mở Đầu
Trong thế giới phát triển ứng dụng Angular phức tạp, việc tổ chức dữ liệu đóng vai trò then chốt để đảm bảo tính bền vững, dễ bảo trì và mở rộng lâu dài cho dự án.
Là đồng sáng lập kiêm CTO của Disign — một phần mềm SaaS chuyển đổi mọi màn hình thành công cụ truyền thông trực quan mạnh mẽ — tôi đã trực tiếp quản lý nhiều ứng dụng Angular với quy mô lớn, như Disign Studio giúp tạo và quản lý nội dung, cùng loạt app trình phát trên các nền tảng đa dạng như Android, Raspberry Pi. Qua đó, tôi nhận thấy rằng dù ứng dụng có tuyệt vời thế nào, nếu cấu trúc dữ liệu không tốt, dự án rất dễ rơi vào trạng thái hỗn loạn dẫn đến lỗi UI, khó khăn khi bảo trì, và hiệu suất kém. Bài viết này sẽ tập trung vào việc thiết kế dữ liệu phía frontend như một cơ sở dữ liệu quan hệ (DBMS) — một “bí quyết” nền tảng đã được khẳng định bởi hàng thập kỷ phát triển công nghệ.
Thiết Kế Dữ Liệu Như Một Hệ Quản Trị Cơ Sở Dữ Liệu
Tại Sao Cấu Trúc Dữ Liệu Lại Quan Trọng?
Một ứng dụng có thể được viết rất tốt, có nhiều thành phần được test kỹ lưỡng, nhưng nếu dữ liệu không được quản lý hợp lý, toàn bộ hệ thống sẽ nhanh chóng bị "lung lay". Ví dụ ở Disign Studio, ứng dụng quản lý hàng nghìn màn hình đặt tại nhiều địa điểm khác nhau, với hơn 175 thực thể dữ liệu kinh doanh (business entities) đã được thiết kế theo chuẩn quan hệ, giúp đảm bảo dễ dàng quản lý và mở rộng.
Dữ liệu tốt là nền tảng để toàn bộ ứng dụng hoạt động mượt mà, hiệu quả và có thể mở rộng.
Nguyên Tắc Cơ Bản Khi Thiết Kế Dữ Liệu
Để đảm bảo dữ liệu sạch và hiệu quả, nhất định phải tuân thủ các nguyên tắc:
✅ Data uniqueness: Không trùng lặp dữ liệu không cần thiết.
✅ Explicit relationships: Mối quan hệ rõ ràng 1-n, n-n thông qua ID.
✅ Không lưu trữ dữ liệu tính toán: Dữ liệu tính toán nên giữ ở phía runtime hoặc view.
✅ Thiết kế phẳng (Flat design): Tránh lồng sâu cấu trúc JSON.
✅ Chỉ lưu trữ giá trị đơn giản: Loại trừ JSON phức tạp, các đối tượng Date.
✅ Nếu cần lưu JSON thì hãy coi đó như một chuỗi (string) theo kiểu JSON.stringify().
Ví Dụ Các Thực Thể TypeScript Chuẩn
exportinterfaceScreen {
id: string;
name: string;
campaignId: string; // quan hệ 1-n
}
exportinterfaceCampaign {
id: string;
name: string;
}
Thay vì nhúng dữ liệu màn hình vào chiến dịch (hay ngược lại), chúng ta tạo hai thực thể riêng biệt được chuẩn hóa, index theo ID, tương tự như bảng trong cơ sở dữ liệu quan hệ.
Những Sai Lầm Cần Tránh
Các Tình Trạng Gây Ra Nợ Kỹ Thuật
Lồng đối tượng dữ liệu (ví dụ campaigns lồng trong screens và ngược lại).
Dữ liệu bị trùng lặp không cần thiết.
Thực thể dữ liệu bị thể hiện không đầy đủ tùy context.
Các vấn đề này dẫn đến:
Lỗi giao diện người dùng pha tạp.
Mức độ phức tạp cao khi quản lý trạng thái ứng dụng.
Khó khăn trong việc bảo trì và phát triển tiếp theo.
Không lưu trữ trạng thái UI như modal, vị trí scroll trong các thực thể kinh doanh. UI state nên được quản lý riêng biệt để tránh lẫn lộn báo động cho dữ liệu doanh nghiệp.
Vì Sao Tiêu Chuẩn Nghiêm Ngặt Về Dữ Liệu Lại Cần Thiết?
Việc tuân thủ nguyên tắc nghiêm ngặt khi thiết kế dữ liệu giúp:
Quản lý trạng thái đơn giản, rõ ràng.
Thành phần trong UI xử lý dữ liệu dễ hiểu và trực quan.
Quá trình bảo trì và mở rộng dự án thuận lợi hơn.
Thực hiện các bản migrate mà không phá vỡ cấu trúc.
Giữ cho code sạch, giảm thiểu các đoạn code phức tạp và hack.
Dữ liệu là nguồn chân lý duy nhất nếu dữ liệu sai thì UI cũng sẽ sai theo.
REST API: Tập Trung Vào Ứng Dụng, Không Phải Public API
Phân Biệt API Riêng Và Public API
REST API của ứng dụng không phải là API công khai hay generic. Ví dụ, không cần thiết tạo URL phức tạp kiểu:
/screens/{screen_id}/campaigns/{campaign_id}
Thông thường, một endpoint chỉ cần một tham số là đủ để:
Lấy dữ liệu đầy đủ.
Quản lý phân quyền, vai trò.
...và nhiều tác vụ khác trong bối cảnh ứng dụng.
Đối với nhu cầu API public hoặc đa mục đích, nên xây dựng một API riêng biệt, kế thừa lại business logic, tránh sự trùng lặp không cần thiết.
Tại Disign
Chúng tôi có REST API được thiết kế riêng để phục vụ Angular app, trả về dữ liệu flat, tối ưu cho state management (ví dụ với NgRx) và theo đúng các thực thể đã định nghĩa phía frontend.
GraphQL không phải lựa chọn phù hợp cho trường hợp này do tính phức tạp và overhead không cần thiết, trong khi REST API thiết kế app-specific lại đơn giản, hiệu quả hơn.