Files
pos-system/apps/app-client-base-swift/docs/vi/architecture.md

235 lines
12 KiB
Markdown

# Hướng Dẫn Kiến Trúc
> Tài liệu kiến trúc chi tiết cho ứng dụng iOS AppClientBaseSwift.
## Tổng Quan
AppClientBaseSwift là ứng dụng iOS native được xây dựng theo mẫu kiến trúc **MVVM (Model-View-ViewModel)** với **SwiftUI** cho UI declarative. Ứng dụng tuân theo các best practices phát triển hiện đại của Apple bao gồm:
- **Swift Concurrency** (async/await)
- **Combine** cho reactive data binding
- **Protocol-oriented programming** để tăng khả năng test
- **Keychain Services** cho lưu trữ bảo mật
## Sơ Đồ Kiến Trúc
```
┌─────────────────────────────────────────────────────────────────────────┐
│ LỚP PRESENTATION │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ SwiftUI Views │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ SplashView │ │ HomeView │ │ ExploreView │ │ ProfileView │ │ │
│ │ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ LoginView │ │RegisterView │ │ForgotPasswd │ │ │
│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ @StateObject / @EnvironmentObject │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ ViewModels (@MainActor) │ │
│ │ ┌────────────────┐ ┌────────────────┐ ┌────────────────┐ │ │
│ │ │ AuthViewModel │ │ HomeViewModel │ │ProfileViewModel│ │ │
│ │ └────────────────┘ └────────────────┘ └────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘
Dependency Injection (dựa trên Protocol)
┌─────────────────────────────────────────────────────────────────────────┐
│ LỚP SERVICE │
│ ┌─────────────────────────────┐ ┌─────────────────────────────┐ │
│ │ APIService │ │ AuthManager │ │
│ │ • request<T>() │ │ • @Published authState │ │
│ │ • get(), post() │ │ • login(), register() │ │
│ │ • URLSession │ │ • Lưu trữ Keychain │ │
│ └─────────────────────────────┘ └─────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│ LỚP DATA │
│ ┌─────────────────────────────┐ ┌─────────────────────────────┐ │
│ │ Models │ │ Constants │ │
│ │ • User (Codable) │ │ • APIConfig │ │
│ │ • HomeItem │ │ • StorageKeys │ │
│ │ • AuthState │ │ • DesignSystem │ │
│ └─────────────────────────────┘ └─────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘
```
## Chi Tiết Component
### 1. Lớp Presentation
#### Views
| Component | Trách nhiệm |
|-----------|-------------|
| `SplashView` | Màn hình splash động, điều hướng trễ |
| `ContentView` | Container TabView gốc, routing theo auth state |
| `AuthContainerView` | Điều hướng luồng Auth (Login/Đăng ký/Quên MK) |
| `HomeView` | Tab Home với lời chào, promo, dịch vụ |
| `ExploreView` | Tính năng khám phá và tìm kiếm |
| `ProfileView` | Hồ sơ người dùng và cài đặt |
#### ViewModels
```swift
@MainActor
final class HomeViewModel: ObservableObject {
@Published var isLoading: Bool = false
@Published var items: [HomeItem] = []
@Published var errorMessage: String?
private let apiService: APIServiceProtocol
func loadData() async { ... }
}
```
### 2. Lớp Service
#### APIService
HTTP client tuân theo nguyên tắc Single Responsibility:
```swift
protocol APIServiceProtocol {
func request<T: Decodable>(
endpoint: String,
method: HTTPMethod,
body: Encodable?,
headers: [String: String]?
) async throws -> T
}
```
**Tính năng:**
- Xử lý request/response generic
- Tự động mã hóa/giải mã JSON (snake_case ↔ camelCase)
- Tự động thêm Bearer token
- Xử lý mã trạng thái HTTP
#### AuthManager
Singleton quản lý trạng thái xác thực:
```swift
final class AuthManager: ObservableObject {
@MainActor static let shared = AuthManager()
@Published var authState: AuthState = .unknown
}
```
**Enum AuthState:**
```swift
enum AuthState {
case unknown // Trng thái khi to
case unauthenticated // Chưa đăng nhp
case authenticated(User) // Đã đăng nhp
}
```
## Luồng Dữ Liệu
```mermaid
sequenceDiagram
participant V as View
participant VM as ViewModel
participant S as Service
participant API as Backend API
V->>VM: Hành động User (tap button)
VM->>VM: Đặt isLoading = true
VM->>S: await service.request()
S->>API: HTTP Request
API-->>S: JSON Response
S-->>VM: Model đã giải mã
VM->>VM: Cập nhật @Published
VM-->>V: SwiftUI render lại
```
## Luồng Xác Thực
```mermaid
stateDiagram-v2
[*] --> Unknown: Khởi động App
Unknown --> Authenticated: Token hợp lệ
Unknown --> Unauthenticated: Không có Token
Unauthenticated --> Login
Login --> Authenticated: Thành công
Login --> Register: Điều hướng
Register --> Authenticated: Thành công
Authenticated --> HomeScreen
HomeScreen --> Unauthenticated: Đăng xuất
```
## Quyết Định Thiết Kế
### 1. Tại sao MVVM?
| Lợi ích | Mô tả |
|---------|-------|
| Khả năng test | ViewModel có thể test độc lập không cần UI |
| Phân tách trách nhiệm | View chỉ hiển thị, logic nằm ở ViewModel |
| Tương thích SwiftUI | `@ObservableObject` + `@Published` native |
| Cập nhật reactive | UI tự động làm mới dựa trên Combine |
### 2. Tại sao DI dựa trên Protocol?
```swift
// Protocol cho phép mock khi test
protocol APIServiceProtocol { ... }
// Production
final class APIService: APIServiceProtocol { ... }
// Test mock
final class MockAPIService: APIServiceProtocol { ... }
```
### 3. Tại sao Keychain thay vì UserDefaults?
| Keychain | UserDefaults |
|----------|--------------|
| ✅ Mã hóa khi lưu trữ | ❌ Text thuần |
| ✅ Secure enclave | ❌ Có thể truy cập |
| ✅ Riêng cho app | ❌ Shared prefs |
### 4. Tại sao @MainActor trên ViewModels?
- Đảm bảo tất cả cập nhật `@Published` xảy ra trên main thread
- Ngăn chặn vấn đề concurrency với SwiftUI
- Contract an toàn thread rõ ràng
## Kiến Trúc Bảo Mật
```
┌────────────────────────────────────────────────────────────┐
│ CÁC LỚP BẢO MẬT │
├────────────────────────────────────────────────────────────┤
│ Lớp 1: Bảo mật Transport (HTTPS/TLS) │
│ • Tất cả API calls sử dụng HTTPS │
├────────────────────────────────────────────────────────────┤
│ Lớp 2: Bảo mật Token (Keychain) │
│ • Access token lưu trong Keychain │
│ • Refresh token lưu trong Keychain │
├────────────────────────────────────────────────────────────┤
│ Lớp 3: Bảo mật Session │
│ • Kiểm tra hết hạn token │
│ • Tự động refresh token │
├────────────────────────────────────────────────────────────┤
│ Lớp 4: Validation Input │
│ • Kiểm tra định dạng email │
│ • Kiểm tra độ mạnh mật khẩu │
└────────────────────────────────────────────────────────────┘
```
## Hướng Phát Triển
| Tính năng | Ưu tiên | Mô tả |
|-----------|---------|-------|
| Certificate Pinning | Cao | Xác thực chứng chỉ TLS |
| Xác thực sinh trắc | Cao | Đăng nhập Face ID / Touch ID |
| Chế độ Offline | Trung bình | Cache local với SwiftData |
| Push Notifications | Trung bình | Tích hợp APNs |
## Tài Liệu Liên Quan
- [README.md](./README.md) - Hướng dẫn bắt đầu nhanh