MVC (Model-View-Controller) — الگوی معماری است که برنامه را به سه مؤلفه تقسیم میکند: Model مسئول دادهها و منطق تجاری، View مسئول رابط کاربری، Controller مسئول پردازش ورودی و هماهنگی Model و View است. در iOS، MVC از طریق UIViewController و در Android از طریق Activity و Fragment پیادهسازی میشود. MVC الگوی پایهای است که MVVM، MVP و Clean Architecture بر اساس آن ساخته شدهاند. بیشتر — در MVC in Cocoa Core.
نکات اصلی
MVC (Model-View-Controller) — الگوی معماری است که توسط Trygve Reenskaug در سال 1979 برای زبان Smalltalk-80 ارائه شد. الگو برنامه را به سه لایه تقسیم میکند: Model شامل دادهها و منطق تجاری، View مسئول نمایش، Controller ورودی کاربر را پردازش کرده و Model و View را بهروزرسانی میکند. جداسازی مسئولیتها امکان تغییر هر لایه را به طور مستقل فراهم میکند — برای مثال، جایگزینی View از UIKit به SwiftUI بدون تغییر منطق تجاری در Model.
تعامل مؤلفهها در MVC از چرخه پیروی میکند: کاربر با View تعامل میکند → Controller رویداد را دریافت میکند → Controller Model را بهروزرسانی میکند → Model تغییرات را به Controller اطلاع میدهد → Controller View را بهروزرسانی میکند. در پیادهسازی کلاسیک، Model از الگوی Observer استفاده میکند: هنگام تغییر دادهها، Model اعلانها را ارسال میکند، Controller مشترک میشود و View را بهروزرسانی میکند. در پیادهسازی Apple، Key-Value Observing (KVO) یا NotificationCenter این نقش را ایفا میکنند.
| مؤلفه | مسئولیت | مثال در iOS | مثال در Android |
|---|---|---|---|
| Model | دادهها، منطق تجاری، شبکه | Struct User، CoreData | Data class، Repository |
| View | نمایش UI | Storyboard، XIB، UIView | چیدمان XML، Jetpack Compose |
| Controller | پردازش ورودی، هماهنگی | UIViewController | Activity، Fragment |
MVC در توسعه مدرن موبایل کمتر از 10 سال پیش استفاده میشود، اما درک آن ضروری است. Apple MVC را برای صفحات ساده در برنامههای UIKit توصیه میکند. Google MVC خالص را برای Android توصیه نمیکند — مستندات رسمی MVVM را با Jetpack پیشنهاد میدهد. با این حال، دانش MVC برای کار با پروژههای legacy و درک تکامل الگوهای معماری ضروری است.
Apple MVC — پیادهسازی سفارشی الگو که در UIKit تعبیه شده است. UIViewController نقش Controller را ایفا میکند: چرخه عمر صفحه را مدیریت میکند (viewDidLoad، viewWillAppear، viewDidDisappear)، لمسها و اقدامات کاربر را پردازش میکند، View را از طریق IBOutlets بهروزرسانی میکند. View در Interface Builder (storyboard یا XIB) یا برنامهنویسی ایجاد میشود. Model — هر شیء دادهای: سرویسهای شبکه، پشتههای CoreData، ساختارهای Swift.
final class UserViewController: UIViewController {
// View (از طریق خروجی storyboard)
@IBOutlet private var nameLabel: UILabel!
@IBOutlet private var emailLabel: UILabel!
// Model
private let userService = UserService()
override func viewDidLoad() {
super.viewDidLoad()
loadUser()
}
private func loadUser() {
userService.fetchUser { [weak self] user in
// Controller View را بهروزرسانی میکند
self?.nameLabel.text = user.name
self?.emailLabel.text = user.email
}
}
}
مشکل Apple MVC — View و Controller به شدت به هم متصل هستند. UIViewController همزمان هم View و هم منطق را مدیریت میکند. Storyboard View را در XML ذخیره میکند، اما کنترلر از طریق IBOutlets ارجاعات مستقیم به عناصر UI دارد. این اصل مسئولیت واحد را نقض میکند: کنترلر مسئول چرخه عمر، دلیگیتها، datasource، target-action و انیمیشنها است. در نتیجه، صفحه استاندارد یک برنامه iOS شامل 200–500 خط کد در کنترلر است.
چرخه عمر ViewController — Apple 6 روش چرخه عمر ارائه میدهد: loadView (ایجاد دستی View)، viewDidLoad (پس از بارگذاری View در حافظه)، viewWillAppear (قبل از ظاهر شدن روی صفحه)، viewDidAppear (پس از انیمیشن)، viewWillDisappear (قبل از خروج از صفحه)، viewDidDisappear (پس از خروج). هر روش — مکانی برای قرار دادن منطق در MVC. استفاده از این روشها برای منطق تجاری رشد کنترلر را تسریع میکند.
Android MVC — Activity و Fragment نقش Controller را ایفا میکنند، فایلهای چیدمان XML — View، هر کلاس POJO با دادهها — Model. Activity چرخه عمر صفحه را مدیریت میکند: onCreate، onStart، onResume، onPause، onStop، onDestroy. Fragment — زیرصفحه درون Activity با چرخه عمر خود. View (XML) از Controller جدا شده و از طریق setContentView یا LayoutInflater بارگذاری میشود. Model — مخازن، پایگاههای داده، فراخوانیهای شبکه.
class UserActivity : AppCompatActivity() {
// View از طریق چیدمان XML
private lateinit var binding: ActivityUserBinding
// Model
private val userRepository = UserRepository()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityUserBinding.inflate(layoutInflater)
setContentView(binding.root)
loadUser()
}
private fun loadUser() {
userRepository.getUser { user ->
runOnUiThread {
binding.nameText.text = user.name
binding.emailText.text = user.email
}
}
}
}
Android ViewBinding و DataBinding — ابزارهای مدرنی که اتصال Controller و View را کاهش میدهند. ViewBinding کلاسی با ارجاعات مستقیم به View از XML ایجاد میکند و findViewById را حذف میکند. DataBinding امکان اتصال دادهها با UI در نشانهگذاری XML را از طریق @{user.name} اضافه میکند. DataBinding — گامی به سوی MVVM است، زیرا امکان انتقال دادهها از Model به View را بدون کد در Activity فراهم میکند. Google DataBinding را برای همه پروژههای جدید توصیه میکند.
چرخه عمر Android پیچیدهتر از iOS است: Activity ممکن است در هنگام چرخش صفحه، کمبود حافظه یا تغییر پیکربندی نابود و دوباره ایجاد شود. در MVC خالص، کنترلر (Activity) حاوی منطقی است که هنگام نابودی از بین میرود. این نیاز به ذخیره وضعیت از طریق onSaveInstanceState یا ViewModel از Jetpack دارد که فراتر از چارچوب MVC خالص است و معماری را به MVVM نزدیک میکند.
Massive View Controller — اصطلاحی است که مشکل اصلی MVC در توسعه موبایل را توصیف میکند. کنترلر در iOS و Android مسئولیتهای زیادی را بر عهده میگیرد: پردازش ورودی، اعتبارسنجی دادهها، تعامل شبکه، ناوبری، کش کردن، انیمیشنها، مدیریت چرخه عمر. در نتیجه کنترلر به 500–2000 خط کد رشد میکند و خواندن، آزمایش و نگهداری آن دشوار میشود.
دلایل Massive View Controller — معماری UIKit و Android Framework قرار دادن منطق در کنترلر را تشویق میکند. فراخوانیهای شبکه، پردازش JSON، ناوبری — همه اینها به طور طبیعی در Activity یا UIViewController نوشته میشوند، زیرا آنها به چرخه عمر و UI دسترسی دارند. توسعهدهنده باید آگاهانه منطق را به کلاسهای جداگانه (Service، Manager، Interactor) منتقل کند که نیاز به انضباط و درک اصول معماری دارد.
| مشکل MVC | شرح | راهحل |
|---|---|---|
| اتصال قوی | Controller از View و Model آگاه است | MVVM — ViewModel از View آگاه نیست |
| دشواری آزمایش | Controller به UIKit/Android وابسته است | انتقال منطق به سرویسها |
| چرخه عمر | وضعیت در چرخش از بین میرود | ViewModel از Jetpack/SwiftUI |
| عدم ناوبری | Controller انتقالها را مدیریت میکند | الگوی Coordinator، Router |
آزمایش MVC — Model به صورت مجزا با تستهای واحد آزمایش میشود. آزمایش Controller به دلیل وابستگی به UIKit/UIFoundation دشوار است. XCTest اجازه ایجاد UIViewController بدون پنجره نمایش را نمیدهد. برای Android، ActivityTestRule و Robolectric تا حدی مشکل را حل میکنند، اما تستها کند هستند. View معمولاً با تستهای واحد آزمایش نمیشود — برای UI از تستهای اسکرینشات و UI (XCUITest، Espresso) استفاده میشود.
زمانی که MVC توجیهپذیر است — صفحات ساده با یک یا دو عنصر (صفحه ورود، پروفایل، تنظیمات). نمونههای اولیه و MVP برای آزمایش فرضیهها — MVC بدون لایههای اضافی سریعتر نوشته میشود. پروژههایی با پایگاه کد کوچک تا 10–15 صفحه. در پروژههای پیچیده، MVC منجر به انباشت بدهی فنی میشود و هر 6–12 ماه نیاز به بازسازی دارد.
MVC vs MVVM — تفاوت اصلی: در MVVM کنترلر با ViewModel جایگزین میشود که به View ارجاعی ندارد. دادهها از طریق Observable (SwiftUI)، LiveData/StateFlow (Android) یا Combine/RxSwift منتقل میشوند. ViewModel بدون وابستگیهای UI با تستهای واحد آزمایش میشود. Apple از سال 2019 MVVM را با SwiftUI توصیه میکند، Google — MVVM را با LiveData/Flow به عنوان معماری رسمی Android. MVVM برای اتصال به کد بیشتری نیاز دارد، اما قابلیت آزمایش را به طور قابل توجهی بهبود میبخشد.
MVC vs MVP — در MVP (Model-View-Presenter) Presenter یک لایه قابل آزمایش است که View را از طریق رابط دریافت میکند. برخلاف MVC که در آن Controller مستقیماً View را از طریق UIKit مدیریت میکند، Presenter به چارچوب وابسته نیست — از طریق انتزاع ViewInterface کار میکند. MVP در توسعه Android قبل از ظهور Jetpack محبوب بود و در پروژههای قدیمی استفاده میشود. Presenter بیشتر از Activity عمر میکند و وضعیت را در چرخش صفحه حفظ میکند.
MVC vs Clean Architecture — Clean Architecture لایههای Use Cases (Interactors)، Entities، Gateways و Repository را اضافه میکند. MVC در لایه Presentation باقی میماند، اما منطق تجاری به لایه Domain با Use Cases منتقل میشود. Clean Architecture مشکل Massive View Controller را به طور ریشهای حل میکند — Controller فقط شامل فراخوانیهای Use Cases و بهروزرسانی View است. نقطه ضعف — افزایش قابل توجه تعداد کلاسها و فایلها که برای پروژههای با 50+ صفحه توجیهپذیر است.
// MVC در iOS: Controller همه چیز را شامل میشود
class OrderViewController: UIViewController {
func placeOrder() {
// اعتبارسنجی + شبکه + بهروزرسانی UI
guard Validation.isValid(total) else { return }
NetworkService.shared.submit(order) { [weak self] result in
self?.handleResult(result)
}
}
}
// MVVM: منطق در ViewModel
class OrderViewModel: ObservableObject {
@Published var state: OrderState = .idle
func placeOrder() { /* منطق تجاری */ }
}
انتخاب معماری به اندازه تیم، پروژه و قابلیت آزمایش مورد نیاز بستگی دارد. برای تیم 1–2 توسعهدهنده و پروژه تا 20 صفحه، MVVM مناسب است. برای تیم بزرگ از 5 توسعهدهنده و پروژه از 50 صفحه — Clean Architecture با ساختار ماژولار. MVC همچنان مرتبط است برای درک تکامل معماریها، پشتیبانی از پروژههای legacy و برای صفحات ساده در UIKit بدون منطق تجاری پیچیده.
سؤالات متداول
مشکل اصلی — Massive View Controller است. در iOS، کنترلر UIViewController مسئول همه چیز است: پردازش ورودی، بهروزرسانی View، کار با شبکه، ناوبری و چرخه عمر. در Android، Activity/Fragment عملکردهای مشابهی را انجام میدهد. در نتیجه، کنترلر به هزاران خط کد رشد میکند، آزمایش و نگهداری آن دشوار میشود و اصل مسئولیت واحد را نقض میکند.
در MVC، کنترلر مستقیماً View را بهروزرسانی میکند و ورودی کاربر را پردازش میکند. در MVVM، نقش کنترلر توسط ViewModel ایفا میشود که به View ارجاعی ندارد — دادهها از طریق مکانیزمهای اتصال منتقل میشوند. MVVM بهتر آزمایش میشود، زیرا ViewModel به UIKit یا Android Framework وابسته نیست. Apple MVVM را با SwiftUI توصیه میکند، Google — MVVM را با Jetpack Compose.
بله، MVC همچنان یک الگوی کاربردی برای صفحات ساده و نمونههای اولیه است. Apple MVC را برای برنامههای UIKit با صفحات ساده توصیه میکند. برای پروژههای پیچیده با صفحات متعدد، درخواستهای شبکه و کش کردن، بهتر است MVVM، VIPER یا Clean Architecture را انتخاب کنید. به توسعهدهندگان مبتدی توصیه میشود قبل از یادگیری الگوهای پیچیدهتر، MVC را بیاموزند.
Model به صورت مجزا آزمایش میشود — اینها اشیاء داده و منطق تجاری معمولی هستند. آزمایش Controller به دلیل وابستگی به UIKit یا Android Framework دشوار است. توصیه میشود منطق تجاری را از کنترلر به سرویسها یا اینتراکتورهای جداگانه منتقل کنید که با تستهای واحد آزمایش میشوند. View معمولاً با تستهای واحد آزمایش نمیشود — برای آن از تستهای UI و تستهای اسکرینشات استفاده میشود.
در iOS — MVVM با SwiftUI و Combine، استاندارد Apple از سال 2019. در Android — MVVM با LiveData یا StateFlow، به طور رسمی توسط Google توصیه میشود. برای پروژههای بزرگ با تیمهای 5+ توسعهدهنده — Clean Architecture با VIPER در iOS یا Clean Architecture در Android با تقسیم به ماژولهای مبتنی بر ویژگی. برای پروژههای legacy با MVC — بازسازی تدریجی با انتقال منطق به سرویسهای جداگانه.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید