Layered Architecture (N-Tier)
"Layered architecture is the most common architectural pattern and the de facto standard for most business applications." — Mark Richards, Software Architecture Patterns
Layered Architecture (còn gọi là N-Tier Architecture hay Multi-Layer Architecture) là một trong những kiểu kiến trúc lâu đời và phổ biến nhất trong kỹ thuật phần mềm. Nó tổ chức code thành các tầng (layers) xếp chồng lên nhau, mỗi tầng đảm nhận một nhóm trách nhiệm cụ thể. Tầng trên cùng giao tiếp với tầng ngay dưới nó thông qua các interface được định nghĩa trước. Đây là kiến trúc mặc định mà hầu hết developer được học đầu tiên — từ các đồ án đại học cho đến hệ thống enterprise lớn.
Bài toán
Vấn đề: Monolithic spaghetti code
Hãy tưởng tượng bạn là kiến trúc sư chính của một hệ thống ngân hàng số (digital banking platform) — giống như Timo hay VPBank Digital. Hệ thống phải xử lý hàng triệu giao dịch mỗi ngày, tích hợp với nhiều core banking system khác nhau, hỗ trợ nhiều loại tài khoản (saving, checking, credit), và tuân thủ nghiêm ngặt các quy định của Ngân hàng Nhà nước về bảo mật và audit.
Trong một hệ thống không có kiến trúc rõ ràng, mọi thứ nhanh chóng trở thành spaghetti code — code lộn xộn, không có ranh giới rõ ràng giữa các chức năng. Validation logic nằm trong controller, business logic xen lẫn với SQL queries, và database connection được tạo trực tiếp trong view layer. Kết quả là một codebase mà không ai dám động vào vì chỉ cần thay đổi một dòng code cũng có thể gây ra hàng loạt lỗi không lường trước.
Cụ thể hơn, hãy xem xét một use case điển hình: chuyển khoản giữa hai tài khoản (internal transfer). Quy trình này bao gồm:
- Input Validation: Kiểm tra số tài khoản, số dư, hạn mức giao dịch trong ngày
- Business Logic: Tính phí giao dịch, kiểm tra hạn mức theo loại tài khoản (VIP, Standard)
- Data Access: Cập nhật số dư tài khoản gửi và nhận, ghi audit log
- Cross-cutting Concerns: Transaction management, logging, authorization
Khi tất cả logic này được viết trong một hàm duy nhất, nó vi phạm nghiêm trọng Single Responsibility Principle — hàm đó có quá nhiều lý do để thay đổi. Nếu ngân hàng thay đổi biểu phí, bạn phải sửa hàm đó. Nếu database chuyển từ Oracle sang PostgreSQL, bạn lại sửa. Nếu thêm loại tài khoản mới, bạn lại động vào. Mỗi lần sửa là một lần rủi ro.
Hơn nữa, việc kiểm thử trở nên cực kỳ khó khăn. Để test logic tính phí, bạn phải set up toàn bộ hệ thống — database thật, kết nối mạng, authentication — thay vì chỉ đơn giản gọi một hàm với input và kiểm tra output. Điều này làm giảm tốc độ phát triển và tăng chi phí bảo trì lên gấp nhiều lần.
Layered Architecture giải quyết vấn đề này như thế nào?
Layered Architecture giải quyết chaos bằng cách áp đặt một cấu trúc phân tầng rõ ràng. Mỗi tầng chỉ giao tiếp với tầng kế cận, và mỗi tầng chỉ có một lý do duy nhất để thay đổi:
- Presentation Layer thay đổi khi UI thay đổi (web → mobile → desktop)
- Business Layer thay đổi khi business rule thay đổi (biểu phí mới, loại tài khoản mới)
- Persistence Layer thay đổi khi data source thay đổi (Oracle → PostgreSQL, thêm cache layer)
- Database Layer thay đổi khi DB engine thay đổi (schema migration, indexing strategy)
Sự phân tách này cho phép nhiều developer làm việc song song trên các tầng khác nhau, kiểm thử từng tầng độc lập, và thay đổi implementation của một tầng mà không ảnh hưởng đến các tầng khác — miễn là interface giữa chúng được gi ữ nguyên.
Nguyên lý thiết kế
1. Strict Layering vs Relaxed Layering
Có hai biến thể chính:
- Strict Layering: Một tầng chỉ được gọi tầng ngay dưới nó. Presentation gọi Business, Business gọi Persistence, Persistence gọi Database. Đây là dạng thuần khiết nhất, dễ hiểu và dễ maintain nhất.
- Relaxed Layering: Một tầng có thể gọi tầng dưới nó hoặc tầng cách xa hơn. Ví dụ: Presentation có thể gọi trực tiếp Persistence (skip Business layer). Điều này linh hoạt hơn nhưng dễ dẫn đến vi phạm nguyên tắc và làm rối kiến trúc.
Khuyến nghị: Dùng strict layering trong hầu hết trường hợp. Chỉ dùng relaxed khi có lý do chính đáng và được document rõ ràng.
2. Dependency Direction
Nguyên tắc vàng: Dependencies đi từ trên xuống dưới. Tầng trên phụ thuộc vào tầng dưới, không bao giờ ngược lại. Presentation phụ thuộc vào Business, Business phụ thuộc vào Persistence. Nếu tầng dưới thay đổi interface, nó sẽ ảnh hưởng đến tầng trên — nhưng nếu tầng trên thay đổi, tầng dưới không bị ảnh hưởng.
3. Layer Isolation
Mỗi tầng phải hoàn toàn độc lập về mặt triển khai. Bạn phải có thể thay thế Persistence Layer (ví dụ: từ SQLAlchemy sang Django ORM) mà không ảnh hưởng đến Business Layer. Điều này đạt được bằng cách định nghĩa interface trừu tượng giữa các tầng.
4. Cross-cutting Concerns
Một số concern xuyên suốt tất cả các tầng — logging, security, transaction management, error handling. Các concern này không thuộc về bất kỳ tầng cụ thể nào. Chúng được xử lý qua:
- Decorator pattern: Wrap method với logging/security logic
- AOP (Aspect-Oriented Programming): AspectJ, Spring AOP, Python decorators
- Middleware: Trong web framework (Express.js, Django middleware)
- Pipeline pattern: Chain các handler xử lý request/response
5. Layer Supertype
Mỗi tầng thường có một base class chung cung cấp các tiện ích dùng chung: logging, error handling, validation helper. Ví dụ: BaseController, BaseService, BaseRepository. Điều này giảm code duplication trong cùng tầng.
6. Số lượng tầng tối ưu
3 tầng (Three-Tier) là phổ biến nhất: Presentation - Business - Data. Đây là sweet spot giữa độ phức tạp và lợi ích. 4 tầng: Thêm Integration Layer giữa Business và Data cho hệ thống cần tích hợp nhiều hệ thống bên ngoài. 5+ tầng: Hiếm khi cần thiết, thường gây over-engineering và performance overhead.
Cấu trúc chi tiết
Three-Tier Architecture (3 tầng)
┌─────────────────────── ──────────────────────────────────────────┐
│ PRESENTATION LAYER (UI) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Controllers │ │ Views │ │ Serializers │ │ Forms │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
├─────────────────────────────────────────────────────────────────┤
│ BUSINESS LAYER (Logic) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Services │ │ Domain │ │ Validators │ │ Workflows│ │
│ │ │ │ Models │ │ │ │ (Orch.) │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
├─────────────────────────────────────────────────────────────────┤
│ PERSISTENCE LAYER (Data) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │Repositories│ │ ORM │ │ Data Mappers│ │ DAOs │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
└─────────────────────────────────────────────────────────────────┘
Chi tiết từng tầng
1. Presentation Layer
Trách nhiệm: Giao tiếp với user (human hoặc external system). Không chứa business logic.
Thành phần:
- Controllers/Routers: Nhận request, gọi service, trả response
- Views/Templates: Render HTML/JSON response
- Serializers/Formatters: Chuyển đổi dữ liệu giữa internal representation và external format (JSON, XML, Protocol Buffers)
- Middlewares: Xử lý request/response pipeline (auth, logging, CORS)
- Validators: Input validation cơ bản (format, required fields, length)
Quy tắc: Presentation Layer không được:
- Truy cập database trực tiếp
- Chứa business logic
- Import bất kỳ module nào từ Persistence Layer
2. Business Layer (Domain/Service Layer)
Trách nhiệm: Chứa toàn bộ business logic của ứng dụng. Đây là tầng quan trọng nhất — "trái tim" của hệ thống.
Thành phần:
- Services: Các use case của hệ thống (TransferService, AccountService, ReportService)
- Domain Models: Business entities với behavior (Account, Transaction, Customer)
- Business Validators: Validation có business context (không chỉ format)
- Workflows/Orchestrators: Phối hợp nhiều service để thực hiện một business process
- Domain Events/Notifications: Sự kiện business (TransferCompleted, AccountOverdrawn)
Quy tắc:
- Business Layer là tầng quan trọng nhất — cần được test kỹ nhất
- Không phụ thuộc vào framework hay infrastructure
- Sử dụng dependency injection để nhận repository từ bên ngoài
- Có thể throw business exception (InsufficientBalanceError, AccountNotFoundError)
3. Persistence Layer (Data Access Layer)
Trách nhiệm: Quản lý lưu trữ và truy xuất dữ liệu.
Thành phần:
- Repositories: Abstraction trên data source (interface:
save(),find_by_id(),delete()) - ORM Mappers: SQLAlchemy models, Django ORM models
- Data Access Objects (DAOs): Low-level data access cho các query phức tạp
- Connection Managers: Connection pooling, session management
Quy tắc:
- Repository interface được định nghĩa ở Business Layer (Dependency Inversion)
- Implementation cụ thể có thể thay đổi (PostgreSQL, MongoDB, Redis)
- Transaction management thường được kiểm soát ở tầng Service
4. Database Layer (Infrastructure)
Trách nhiệm: Lưu trữ dữ liệu vật lý.
Thành phần:
- Relational Databases: PostgreSQL, MySQL, Oracle
- NoSQL: MongoDB, Cassandra, Redis
- Message Queues: RabbitMQ, Kafka (nếu dùng cho persistence)
Sơ đồ kiến trúc
┌─────────────────────────────────────┐
│ EXTERNAL CLIENTS │
│ (Web Browser, Mobile App, API) │
└──────────┬──────────────────────────┘
│ HTTP/HTTPS
▼
┌────────────────────────────────────────────────────────────────────┐
│ PRESENTATION LAYER │
│ │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ Controllers │ │ Middleware │ │
│ │ ┌────────────┐ │ │ ┌──────────────┐│ │
│ │ │ AuthCtrl │ │ │ │ AuthMiddleware││ │
│ │ │ AccountCtrl│ │ │ │ LogMiddleware ││ │
│ │ │ TransferCt.│ │ │ │ RateLimitMiddl││ │
│ │ └────────────┘ │ │ └──────────────┘│ │
│ └──────────────────┘ └──────────────────┘ │
│ │
│ ┌────────────────────────────────────────────────┐ │
│ │ Serializers / Validators │ │
│ │ { "account": {...}, "amount": number } │ │
│ └────────────────────────────────────────────────┘ │
└──────────────────────────┬─────────────────────────────────────────┘
│ Gọi Service Layer
▼
┌────────────────────────────────────────────────────────────────────┐
│ BUSINESS LAYER │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ AccountService│ │TransferServ. │ │ ReportServ. │ │
│ │ │ │ │ │ │ │
│ │ - create() │ │ - transfer() │ │ - monthly() │ │
│ │ - freeze() │ │ - validate() │ │ - analytics()│ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
│ ┌──────────────┐ ┌──────────────────┐ ┌─────────────────────┐ │
│ │Domain Models │ │Business Validat. │ │ Workflows │ │
│ │ Account │ │ FeeCalculator │ │ TransferWorkflow │ │
│ │ Transaction │ │ LimitChecker │ │ NewAccountWorkflow │ │
│ └──────────────┘ └──────────────────┘ └─────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Repository Interfaces (Ports) │ │
│ │ IAccountRepository, ITransactionRepository, ICustomerRep│ │
│ └────────────── ────────────────────────────────────────────┘ │
└──────────────────────────┬─────────────────────────────────────────┘
│ Gọi Repository Implementation
▼
┌────────────────────────────────────────────────────────────────────┐
│ PERSISTENCE LAYER │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │AccountRepo │ │TransactRepo │ │CustomerRepo │ │
│ │ (SQLAlchemy) │ │ (SQLAlchemy) │ │ (SQLAlchemy) │ │