Architecture Characteristics là gì? Các đặc tính kiến trúc trong phần mềm (Phần 3): Trade-off và Least Worst Architecture
Một trong những hiểu lầm
phổ biến trong kiến trúc phần mềm là tin rằng luôn tồn tại một thiết
kế có thể tối ưu mọi khía cạnh cùng lúc: vừa nhanh, vừa bảo mật, vừa dễ sử dụng,
vừa dễ mở rộng, vừa dễ bảo trì. Thực tế hoàn toàn ngược lại. Mỗi quyết định kiến
trúc đều mang theo những sự đánh đổi (trade-off), nghĩa là khi cải thiện một đặc tính
thì thường phải chấp nhận đánh đổi ở một đặc tính khác.
Đây cũng chính là tư duy quan trọng nhất của một Software Architect. Thay vì tìm kiếm một kiến trúc "hoàn hảo", mục tiêu là xây dựng một kiến trúc phù hợp nhất với mục tiêu kinh doanh, đồng thời chấp nhận những đánh đổi hợp lý. Trong bài viết này, chúng ta sẽ phân tích những cặp đặc tính thường xung đột với nhau và tìm hiểu khái niệm Least Worst Architecture — một trong những tư tưởng cốt lõi của kiến trúc phần mềm hiện đại.
Architecture Quantum là gì? Giải thích Lượng tử Kiến trúc trong Software Architecture
Architecture Quantum (Lượng tử kiến trúc) qua 8 ví dụ thực tế
6. Các đặc tính kiến trúc có sự tương khắc lẫn nhau
Trong kiến trúc phần mềm,
các đặc tính kiến trúc (architecture characteristics) thường không thể
được tối ưu đồng thời. Khi tăng cường một đặc tính, một hoặc nhiều đặc tính
khác có thể bị ảnh hưởng tiêu cực. Đây được gọi là trade-off – sự đánh đổi
trong thiết kế kiến trúc. Không có kiến trúc nào là hoàn hảo cho mọi mục tiêu;
nhiệm vụ của kiến trúc sư là cân bằng các đặc tính phù hợp với yêu cầu của hệ
thống.
Security ↔ Usability
Đây là cặp mâu thuẫn phổ
biến nhất.
Hệ thống càng được bảo vệ
nghiêm ngặt thì người dùng càng phải thực hiện nhiều bước để sử dụng. Ngược lại,
nếu mọi thao tác đều được đơn giản hóa nhằm nâng cao trải nghiệm người dùng thì
nguy cơ mất an toàn cũng tăng lên.
Ví dụ, một ứng dụng ngân
hàng yêu cầu đăng nhập bằng mật khẩu mạnh, xác thực hai yếu tố (2FA), OTP và
xác minh thiết bị mới. Những biện pháp này giúp bảo vệ tài khoản nhưng cũng khiến
quá trình đăng nhập mất nhiều thời gian hơn. Nếu bỏ toàn bộ các bước xác thực
này để người dùng đăng nhập chỉ bằng một lần chạm, trải nghiệm sẽ tốt hơn nhưng
rủi ro bị chiếm đoạt tài khoản sẽ tăng đáng kể.
Accessibility ↔ Security
Để tăng khả năng tiếp cận,
hệ thống thường giảm bớt các rào cản sử dụng. Tuy nhiên, nhiều cơ chế bảo mật lại
vô tình tạo ra rào cản cho người khuyết tật.
Ví dụ, CAPTCHA bằng hình ảnh
giúp ngăn bot nhưng người khiếm thị không thể vượt qua nếu không có phiên bản
âm thanh. Một số phương thức xác thực sinh trắc học cũng không phù hợp với tất
cả người dùng.
Do đó, khi thiết kế hệ thống
cần tìm giải pháp vừa đảm bảo bảo mật vừa hỗ trợ các nhóm người dùng đặc biệt.
Privacy ↔ Supportability
Để hỗ trợ vận hành, hệ thống
cần ghi log càng nhiều thông tin càng tốt nhằm phục vụ điều tra sự cố.
Tuy nhiên, việc ghi quá
nhiều dữ liệu người dùng có thể vi phạm quyền riêng tư.
Ví dụ, log ghi đầy đủ họ
tên, email, số điện thoại, địa chỉ và nội dung giao dịch sẽ giúp đội vận hành dễ
dàng điều tra lỗi nhưng lại làm tăng nguy cơ rò rỉ dữ liệu cá nhân.
Vì vậy, nhiều hệ thống hiện
đại chỉ ghi những thông tin thật sự cần thiết hoặc che (mask) các dữ liệu nhạy
cảm trong log.
Security ↔ Performance
Nhiều cơ chế bảo mật tiêu
tốn tài nguyên tính toán.
Mã hóa dữ liệu, xác minh
chữ ký số, quét virus, kiểm tra quyền truy cập hoặc kiểm tra token đều làm tăng
thời gian xử lý.
Ví dụ, một API phải xác
minh JWT, giải mã dữ liệu và kiểm tra quyền trên mỗi yêu cầu sẽ phản hồi chậm
hơn một API không thực hiện các bước này.
Đây là lý do nhiều hệ thống
phải tối ưu giữa mức độ bảo mật và hiệu năng.
Security ↔
Interoperability
Khả năng tích hợp thường
yêu cầu hệ thống mở nhiều giao diện giao tiếp với bên ngoài.
Trong khi đó, bảo mật lại
muốn giới hạn càng ít điểm truy cập càng tốt.
Ví dụ, một doanh nghiệp
muốn cho phép hàng chục đối tác truy cập API của mình. Điều này làm tăng khả
năng tích hợp nhưng đồng thời cũng mở rộng "bề mặt tấn công" (attack
surface), khiến việc bảo mật trở nên khó khăn hơn.
Maintainability ↔
Performance
Một hệ thống dễ bảo trì
thường được chia thành nhiều module độc lập.
Tuy nhiên, việc chia nhỏ
này có thể làm giảm hiệu năng do tăng số lần giao tiếp giữa các thành phần.
Ví dụ, trong kiến trúc
microservices, một yêu cầu của người dùng có thể phải đi qua nhiều dịch vụ khác
nhau trước khi trả kết quả. Điều này giúp từng dịch vụ dễ bảo trì và phát triển
độc lập nhưng thường chậm hơn so với một ứng dụng nguyên khối (monolithic) thực
hiện toàn bộ xử lý trong cùng một tiến trình.
Interoperability ↔
Performance
Để nhiều hệ thống khác
nhau có thể giao tiếp, dữ liệu thường phải được chuyển đổi sang các định dạng
chuẩn như JSON hoặc XML.
Quá trình tuần tự hóa
(serialization), giải tuần tự hóa (deserialization) và truyền dữ liệu qua mạng
đều làm tăng độ trễ.
Ví dụ, lời gọi hàm giữa
hai module trong cùng một tiến trình chỉ mất vài micro giây, trong khi lời gọi
REST API giữa hai hệ thống có thể mất hàng chục đến hàng trăm mili giây.
Archivability ↔
Performance
Lưu trữ lâu dài thường
yêu cầu ghi dữ liệu đến nhiều vị trí, tạo bản sao lưu hoặc lưu nhiều phiên bản
lịch sử.
Những hoạt động này làm
tăng chi phí ghi dữ liệu.
Ví dụ, hệ thống ngân hàng
phải lưu toàn bộ lịch sử giao dịch và ghi thêm bản sao vào kho lưu trữ dự
phòng. Điều này giúp đáp ứng yêu cầu kiểm toán nhưng tốc độ ghi giao dịch sẽ chậm
hơn so với việc chỉ lưu dữ liệu vào một cơ sở dữ liệu duy nhất.
Supportability ↔
Performance
Một hệ thống dễ vận hành
thường thu thập rất nhiều thông tin giám sát như log, metrics và traces.
Tuy nhiên, việc ghi log
hoặc thu thập telemetry liên tục cũng tiêu tốn CPU, bộ nhớ và băng thông.
Ví dụ, bật distributed
tracing cho mọi request sẽ giúp xác định nguyên nhân sự cố rất nhanh nhưng cũng
làm tăng độ trễ và dung lượng lưu trữ.
7. Đánh đổi và Kiến trúc Ít tệ nhất
Đừng tìm kiến trúc "tốt nhất", hãy tìm kiến trúc "ít tệ nhất (Least Worst Architecture)"
- Tại sao lại là "ít tệ nhất"?
Bởi vì một kiến trúc cố gắng thỏa mãn tất cả mọi người, hỗ trợ mọi đặc
tính (cái gì cũng muốn tốt) sẽ trở thành một giải pháp chung chung, cồng
kềnh và cực kỳ phức tạp. Kết quả là nó thường không giải quyết tốt được
vấn đề cốt lõi nào cả và rất khó vận hành.
- Kiến trúc sư giỏi là người biết hy sinh những đặc tính ít quan trọng hơn để bảo vệ những đặc tính sống còn của hệ thống.
Điểm quan trọng nhất trong kiến trúc phần mềm là không tồn tại một kiến trúc tối ưu cho mọi đặc tính cùng lúc. Mỗi quyết định thiết kế đều là một sự đánh đổi. Kiến trúc sư cần xác định đâu là các đặc tính ưu tiên của hệ thống dựa trên mục tiêu kinh doanh và bối cảnh sử dụng, sau đó chấp nhận đánh đổi ở những đặc tính ít quan trọng hơn. Chính khả năng nhận diện, phân tích và cân bằng các trade-off này là một trong những kỹ năng cốt lõi của một kiến trúc sư phần mềm.
Comments
Post a Comment