Kiến trúc ứng dụng là cách tổ chức mã để dễ dàng phát triển, kiểm thử và sửa đổi. Các mẫu thiết kế là giải pháp đã được kiểm chứng cho các vấn đề điển hình. Theo JetBrains Developer Ecosystem (2025), MVVM được sử dụng trong 45% dự án Android, MVC trong 28% và Clean Architecture trong 22%. Hiểu về kiến trúc phân biệt một nhà phát triển mới bắt đầu với một chuyên gia.
Các điểm chính
Mẫu kiến trúc xác định cách phân bổ trách nhiệm giữa các lớp của ứng dụng. Việc chọn mẫu ảnh hưởng đến mức độ dễ dàng thêm màn hình mới và kiểm thử mã.
MVC là mẫu cổ điển trong đó Model xử lý dữ liệu, View xử lý hiển thị và Controller xử lý logic. Trên iOS, MVC là mặc định (UIViewController); trên Android, Activity. Nhược điểm là Controller thường trở nên "khổng lồ" (Massive View Controller). Theo khảo sát nhà phát triển iOS (Reddit, 2025), 62% cho rằng MVC là nguyên nhân chính dẫn đến mã khó đọc trong các dự án cũ.
MVP khác ở chỗ Presenter quản lý View thông qua giao diện, cải thiện khả năng kiểm thử. MVP phổ biến trên Android trước Jetpack, nhưng kém tiện lợi hơn MVVM.
MVVM là mẫu được Google khuyến nghị cho Android và Apple cho iOS. ViewModel lưu trữ trạng thái, và View đăng ký thay đổi thông qua Data Binding hoặc @Published. ViewModel không phụ thuộc vào View và dễ kiểm thử. Tại IT Sectr, chúng tôi sử dụng MVVM làm mẫu chính trong tất cả các dự án.
MVI là mẫu phản ứng nơi mọi hành động đều theo chu trình Intent → Model → View. MVI đảm bảo trạng thái có thể dự đoán được. VIPER là mẫu iOS với năm lớp (View, Interactor, Presenter, Entity, Router), cung cấp sự cô lập tối đa nhưng yêu cầu nhiều mã boilerplate.
Clean Architecture là khái niệm của Robert Martin chia ứng dụng thành các lớp: các lớp bên ngoài (UI, DB, mạng) phụ thuộc vào các lớp bên trong (logic nghiệp vụ, thực thể). Trong phát triển di động, Clean Architecture bao gồm ba lớp: data (kho lưu trữ), domain (Use Cases) và presentation (ViewModels, UI).
Repository Pattern là thành phần chính của Clean Architecture, trừu tượng hóa nguồn dữ liệu. Kho lưu trữ quyết định lấy dữ liệu từ mạng hay bộ nhớ cục bộ (Room, Core Data) và trả về định dạng thống nhất. Theo Google (Architecture Guide, 2025), Repository Pattern được khuyến nghị cho bất kỳ ứng dụng nào có yêu cầu mạng. Clean Architecture phù hợp cho các dự án từ 3–5 màn hình trở lên — đối với ứng dụng đơn giản, hãy bắt đầu với MVVM.
Singleton là mẫu kiến trúc đảm bảo một phiên bản duy nhất của một lớp và cung cấp điểm truy cập toàn cục đến nó. Nó được sử dụng cho cơ sở dữ liệu, trình quản lý cài đặt và bộ nhớ đệm. Trong Kotlin, nó được tạo qua object. Nhược điểm là nó làm phức tạp việc kiểm thử do trạng thái toàn cục.
Factory ủy quyền việc tạo đối tượng cho phương thức nhà máy — thay vì new, bạn gọi nhà máy. Builder là mẫu xây dựng từng bước cho các đối tượng phức tạp với nhiều tham số (AlertDialog.Builder, NotificationCompat.Builder). Builder cải thiện khả năng đọc và cho phép đối tượng giữ nguyên bất biến sau khi lắp ráp.
Adapter là mẫu kiến trúc chuyển đổi giao diện của một lớp thành giao diện mà máy khách mong đợi. Trên Android, đó là RecyclerView.Adapter. Facade cung cấp giao diện đơn giản hóa cho một hệ thống phức tạp — ví dụ, mặt tiền cho API che giấu chi tiết xác thực. Delegate là mẫu iOS nơi một đối tượng ủy quyền một nhiệm vụ (UITableViewDelegate). Protocol là tương đương của giao diện trong Swift.
Observer là mẫu đăng ký thay đổi: chủ thể thông báo cho người đăng ký về các cập nhật. Trong phát triển di động, Observer là nền tảng của LiveData, StateFlow, RxJava và Combine. Strategy là mẫu của các thuật toán có thể hoán đổi: bạn cắm một chiến lược khác (sắp xếp, xác thực) mà không cần nhiều câu lệnh if-else.
Dependency Injection là mẫu kiến trúc nơi một đối tượng nhận các phụ thuộc từ bên ngoài thay vì tự tạo chúng. Thay vì new Database(), bạn truyền cơ sở dữ liệu qua hàm tạo. DI đơn giản hóa việc kiểm thử — bạn có thể sử dụng Mock thay vì cơ sở dữ liệu thực — và dễ dàng hoán đổi triển khai. Framework DI phổ biến: Dagger và Hilt (Android), Swinject (iOS), Koin (Kotlin). Hilt — một lớp bọc quanh Dagger được Google khuyến nghị — giảm thiết lập DI xuống 3 lần.
Service Locator là một thay thế cho DI với đăng ký trung tâm các phụ thuộc. Dễ triển khai hơn, nhưng nó ẩn các phụ thuộc của lớp, gây khó khăn cho việc kiểm thử. Các dự án hiện đại ưa thích DI qua Hilt hoặc Koin.
Trong Flutter, quản lý trạng thái là một hệ sinh thái riêng. Redux — một Store duy nhất với các thay đổi qua Actions → Reducer → State. BLoC của Google phân tách sự kiện và trạng thái qua Stream. Provider — một container DI đơn giản được Google khuyến nghị cho Flutter đến năm 2023. Riverpod — một Provider cải tiến giải quyết các vấn đề biên dịch và kiểm thử. GetX — một micro-framework với định tuyến, DI và quản lý trạng thái. Đối với nhà phát triển Flutter mới bắt đầu, chúng tôi khuyến nghị Provider hoặc Riverpod là các giải pháp được tài liệu hóa tốt nhất.
Ngoài các mẫu cụ thể, có những nguyên lý thiết kế kiến trúc chung áp dụng được trong mọi ngôn ngữ và framework.
SOLID — năm nguyên lý thiết kế hướng đối tượng: Single Responsibility (một lớp — một nhiệm vụ), Open-Closed (mở cho mở rộng, đóng cho sửa đổi), Liskov Substitution (lớp con thay thế được lớp cha), Interface Segregation (giao diện nhỏ), Dependency Inversion (phụ thuộc vào trừu tượng). Trong phát triển di động, SRP là nguyên lý hữu ích nhất: mỗi lớp chỉ làm một việc. Theo kinh nghiệm của IT Sectr, vi phạm SRP là nguyên nhân của 70% vấn đề kiểm thử trong các dự án thương mại.
// Пример: нарушение SRP
class UserManager {
fun saveUser(user: User) { /* сохранение */ }
fun validateEmail(email: String): Boolean { /* валидация */ }
fun sendEmail(user: User) { /* отправка */ }
fun formatUser(user: User): String { /* форматирование */ }
}
// Исправление: разделяем на отдельные классы
class UserRepository { fun save(user: User) {} }
class EmailValidator { fun isValid(email: String): Boolean {} }
class EmailService { fun send(user: User) {} }
class UserFormatter { fun format(user: User): String {} }
Ví dụ Kotlin cho thấy cách chúng ta biến một lớp UserManager với bốn trách nhiệm thành bốn lớp với mỗi lớp một trách nhiệm. Mã như vậy dễ kiểm thử, sửa đổi và tái sử dụng hơn.
DRY (Don't Repeat Yourself) — tránh trùng lặp mã. Trích xuất logic lặp lại vào các phương thức hoặc lớp dùng chung. KISS (Keep It Simple, Stupid) — sự đơn giản quan trọng hơn sự thanh lịch. YAGNI (You Aren't Gonna Need It) — đừng viết mã cho thứ có thể không cần thiết. Những nguyên lý này giúp viết mã sạch, dễ bảo trì mà không dư thừa.
ViewModel (Android) là thành phần kiến trúc Jetpack để lưu trữ trạng thái UI, chịu được xoay màn hình. ViewModel không chứa tham chiếu đến Activity và tự động được dọn dẹp. LiveData — một container dữ liệu có thể quan sát với nhận thức về vòng đời. StateFlow — sự thay thế hiện đại cho LiveData dựa trên Kotlin Flow. SharedFlow — Hot Flow cho các sự kiện một lần (điều hướng, toast).
Data Binding và Two-Way Binding — cơ chế liên kết UI và dữ liệu trong Android. Data Binding khai báo kết nối trong XML; Two-Way Binding tự động cập nhật trường trong ViewModel. Unidirectional Data Flow — nguyên lý nơi dữ liệu chảy theo một hướng: State → UI → Event → State. Tại IT Sectr, chúng tôi sử dụng Unidirectional Data Flow trong tất cả các dự án mới — nó giảm số lượng lỗi do thay đổi trạng thái bất ngờ.
| Thành phần | Mục đích | Thay thế |
|---|---|---|
| ViewModel | Lưu trữ trạng thái, chịu xoay | — |
| LiveData | Có thể quan sát với nhận thức vòng đời | StateFlow |
| StateFlow | Kotlin Flow cho trạng thái UI | LiveData |
| SharedFlow | Sự kiện một lần | LiveData Event |
Câu hỏi Thường gặp
Người mới bắt đầu nên dùng MVVM — được Google và Apple hỗ trợ, có sự phân tách rõ ràng. MVC cho màn hình đơn giản. Clean Architecture cho dự án từ 3–5 màn hình trở lên.
Dependency Injection — một đối tượng nhận phụ thuộc từ bên ngoài thay vì tự tạo. Thay vì new Database(), bạn truyền cơ sở dữ liệu qua hàm tạo. Công cụ: Hilt (Android), Swinject (iOS), Koin (Kotlin).
Singleton — một phiên bản cho toàn bộ ứng dụng. Factory — một đối tượng mới mỗi lần. Singleton cho tài nguyên, Factory khi cần các cấu hình khác nhau của cùng một lớp.
State Management — cách dữ liệu được truyền giữa các thành phần và UI phản ứng với thay đổi. Trong Flutter: Provider, Riverpod, BLoC. Trong Android: LiveData, StateFlow, ViewModel.
Tổng kết
Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay
IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.