12 KiB
12 KiB
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
@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:
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:
final class AuthManager: ObservableObject {
@MainActor static let shared = AuthManager()
@Published var authState: AuthState = .unknown
}
Enum AuthState:
enum AuthState {
case unknown // Trạng thái khởi tạo
case unauthenticated // Chưa đăng nhập
case authenticated(User) // Đã đăng nhập
}
Luồng Dữ Liệu
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
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?
// 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
@Publishedxả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 - Hướng dẫn bắt đầu nhanh