MVC (Model-View-Controller), bir uygulamayı üç bileşene ayıran mimari bir desendir: Model verilerden ve iş mantığından sorumludur, View kullanıcı arayüzünden sorumludur, Controller giriş işleme ve Model ile View arasındaki koordinasyondan sorumludur. iOS'ta MVC, UIViewController aracılığıyla uygulanır, Android'de — Activity ve Fragment aracılığıyla. MVC, MVVM, MVP ve Clean Architecture'ın üzerine inşa edildiği temel desen olmaya devam etmektedir. Daha fazla bilgi için MVC in Cocoa Core sayfasını ziyaret edin.
Önemli Noktalar
MVC (Model-View-Controller), 1979 yılında Trygve Reenskaug tarafından Smalltalk-80 dili için önerilen mimari bir desendir. Desen, bir uygulamayı üç katmana ayırır: Model verileri ve iş mantığını içerir, View görüntülemeden sorumludur, Controller kullanıcı girişini işler ve Model ile View'ı günceller. Sorumlulukların ayrılması, her katmanın bağımsız olarak değiştirilmesine olanak tanır — örneğin, Model'deki iş mantığını değiştirmeden View'ı UIKit'ten SwiftUI'ye değiştirmek.
Bileşen etkileşimi MVC'de bir döngüyü izler: kullanıcı View ile etkileşime girer → Controller olayı alır → Controller Model'i günceller → Model Controller'a değişiklikleri bildirir → Controller View'ı günceller. Klasik uygulamada, Model Observer desenini kullanır: veriler değiştiğinde, Model bildirimler gönderir, Controller abone olur ve View'ı günceller. Apple'ın uygulamasında, Key-Value Observing (KVO) veya NotificationCenter bu rolü üstlenir.
| Bileşen | Sorumluluk | iOS'ta Örnek | Android'de Örnek |
|---|---|---|---|
| Model | Veri, iş mantığı, ağ | Struct User, CoreData | Data class, Repository |
| View | UI görüntüleme | Storyboard, XIB, UIView | XML layout, Jetpack Compose |
| Controller | Giriş işleme, koordinasyon | UIViewController | Activity, Fragment |
Modern mobil geliştirmede MVC 10 yıl öncesine göre daha az kullanılıyor, ancak anlaşılması hala önemlidir. Apple, UIKit uygulamalarında basit ekranlar için MVC'yi önerir. Google, Android için saf MVC'yi önermez — resmi belgeler Jetpack ile MVVM'yi önerir. Ancak, eski projelerle çalışmak ve mimari desenlerin evrimini anlamak için MVC bilgisi gereklidir.
Apple MVC, UIKit'e yerleşik desenin özel bir uygulamasıdır. UIViewController, Controller olarak işlev görür: ekran yaşam döngüsünü (viewDidLoad, viewWillAppear, viewDidDisappear) yönetir, dokunmaları ve kullanıcı eylemlerini işler, IBOutlets aracılığıyla View'ı günceller. View, Interface Builder'da (storyboard veya XIB) veya programlı olarak oluşturulur. Model — herhangi bir veri nesnesi: ağ servisleri, CoreData yığınları, Swift yapıları.
final class UserViewController: UIViewController {
// View (storyboard outlet aracılığıyla)
@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'ı günceller
self?.nameLabel.text = user.name
self?.emailLabel.text = user.email
}
}
}
Apple MVC'nin sorunu — View ve Controller sıkı sıkıya bağlıdır. UIViewController aynı anda hem View'ı hem de mantığı yönetir. Storyboard, View'ı XML'de depolar, ancak denetleyicinin IBOutlets aracılığıyla UI öğelerine doğrudan referansları vardır. Bu, tek sorumluluk ilkesini ihlal eder: denetleyici yaşam döngüsü, delegeler, veri kaynağı, target-action ve animasyonlardan sorumludur. Sonuç olarak, standart bir iOS uygulama ekranı, denetleyicide 200–500 satır içerir.
ViewController yaşam döngüsü — Apple, 6 yaşam döngüsü yöntemi sağlar: loadView (manuel View oluşturma), viewDidLoad (View belleğe yüklendikten sonra), viewWillAppear (ekranda görünmeden önce), viewDidAppear (animasyondan sonra), viewWillDisappear (ekrandan ayrılmadan önce), viewDidDisappear (ayrıldıktan sonra). Her yöntem, MVC'de mantık yerleştirme yeridir. Bu yöntemleri iş mantığı için kullanmak, denetleyicinin büyümesini hızlandırır.
Android MVC — Activity ve Fragment Controller olarak işlev görür, XML layout dosyaları View olarak, veri içeren herhangi bir POJO sınıfı Model olarak. Activity ekran yaşam döngüsünü yönetir: onCreate, onStart, onResume, onPause, onStop, onDestroy. Fragment, kendi yaşam döngüsüne sahip Activity içindeki bir alt ekrandır. View (XML), Controller'dan ayrıdır ve setContentView veya LayoutInflater aracılığıyla yüklenir. Model — depolar, veritabanları, ağ çağrıları.
class UserActivity : AppCompatActivity() {
// View (XML layout aracılığıyla)
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 ve DataBinding — Controller ve View arasındaki bağlılığı azaltan modern araçlardır. ViewBinding, XML'den Views'a doğrudan referanslarla bir sınıf oluşturur ve findViewById'i ortadan kaldırır. DataBinding, @{user.name} aracılığıyla XML işaretlemesinde verileri UI'ya bağlama yeteneği ekler. DataBinding, MVVM'ye doğru bir adımdır çünkü Activity'de kod olmadan Model'den View'a veri aktarımına izin verir. Google, tüm yeni projeler için DataBinding'i önerir.
Android yaşam döngüsü iOS'tan daha karmaşıktır: ekran döndürme, bellek yetersizliği veya yapılandırma değişikliğinde Activity yok edilebilir ve yeniden oluşturulabilir. Saf MVC'de, denetleyici (Activity), yok edildiğinde kaybolan mantığı içerir. Bu, onSaveInstanceState veya Jetpack'ten ViewModel aracılığıyla durum kaydetmeyi gerektirir, bu da saf MVC'nin ötesine geçer ve mimariyi MVVM'ye yaklaştırır.
Massive View Controller, mobil geliştirmede MVC'nin ana sorununu tanımlayan bir terimdir. iOS ve Android'deki denetleyici çok fazla sorumluluk üstlenir: giriş işleme, veri doğrulama, ağ etkileşimi, navigasyon, önbellekleme, animasyonlar, yaşam döngüsü yönetimi. Sonuç olarak, denetleyici 500–2000 satır koda büyür, okunması, test edilmesi ve bakımı zorlaşır.
Massive View Controller'ın nedenleri — UIKit ve Android Framework'ün mimarisi, mantığı denetleyiciye yerleştirmeyi teşvik eder. Ağ çağrıları, JSON işleme, navigasyon — tüm bunlar doğal olarak Activity veya UIViewController'a gider çünkü bunlar yaşam döngüsüne ve UI'ya erişime sahiptir. Geliştirici, bilinçli olarak mantığı ayrı sınıflara (Service, Manager, Interactor) çıkarmalıdır, bu da disiplin ve mimari ilkelerin anlaşılmasını gerektirir.
| MVC Sorunu | Açıklama | Çözüm |
|---|---|---|
| Güçlü bağlılık | Controller, View ve Model'i bilir | MVVM — ViewModel, View'ı bilmez |
| Test karmaşıklığı | Controller, UIKit/Android'e bağımlıdır | Mantığı hizmetlere çıkarma |
| Yaşam döngüsü | Döndürmede durum kaybolur | Jetpack/SwiftUI'den ViewModel |
| Navigasyon eksikliği | Controller geçişleri yönetir | Coordinator deseni, Router |
MVC testi — Model, birim testlerle izole olarak test edilir. Controller, UIKit/UIFoundation'a bağımlılık nedeniyle test edilmesi zordur. XCTest, görünüm penceresi olmadan UIViewController oluşturmaya izin vermez. Android için, ActivityTestRule ve Robolectric sorunu kısmen çözer, ancak testler yavaştır. View genellikle birim testlerle test edilmez — UI için ekran görüntüsü testleri ve UI testleri (XCUITest, Espresso) kullanılır.
MVC ne zaman haklıdır — bir veya iki öğeli basit ekranlar (giriş ekranı, profil, ayarlar). Hipotez doğrulama için prototipler ve MVP — MVC ek katmanlar olmadan daha hızlı yazılır. 10–15 ekrana kadar küçük kod tabanlı projeler. Karmaşık projelerde, MVC teknik borç birikimine yol açar ve her 6–12 ayda bir yeniden düzenleme gerektirir.
MVC vs MVVM — temel fark: MVVM'de, denetleyici View'a referansı olmayan ViewModel ile değiştirilir. Veriler, Observable (SwiftUI), LiveData/StateFlow (Android) veya Combine/RxSwift aracılığıyla iletilir. ViewModel, UI bağımlılıkları olmadan birim testlerle test edilebilir. Apple, 2019'dan beri SwiftUI ile MVVM'yi önerir, Google — LiveData/Flow ile MVVM'yi resmi Android mimarisi olarak önerir. MVVM, bağlama için daha fazla kod gerektirir ancak test edilebilirliği önemli ölçüde artırır.
MVC vs MVP — MVP'de (Model-View-Presenter), Presenter, View'ı bir arayüz aracılığıyla alan test edilebilir bir katmandır. Controller'ın UIKit aracılığıyla doğrudan View'ı yönettiği MVC'nin aksine, Presenter çerçeveye bağımlı değildir — ViewInterface soyutlaması aracılığıyla çalışır. MVP, Jetpack'ten önce Android geliştirmede popülerdi ve eski projelerde kullanılır. Presenter, Activity'den daha uzun yaşar ve ekran döndürmede durumu korur.
MVC vs Clean Architecture — Clean Architecture katmanlar ekler: Use Cases (Interactors), Entities, Gateways ve Repository. MVC, Presentation katmanında kalır, ancak iş mantığı, Use Cases ile Domain katmanına taşınır. Clean Architecture, Massive View Controller sorununu kökten çözer — Controller yalnızca Use Cases çağrıları ve View güncellemelerini içerir. Dezavantajı, sınıf ve dosya sayısında önemli bir artıştır, bu da 50+ ekranlı projeler için haklıdır.
// iOS'ta MVC: Controller her şeyi içerir
class OrderViewController: UIViewController {
func placeOrder() {
// Doğrulama + ağ + UI güncelleme
guard Validation.isValid(total) else { return }
NetworkService.shared.submit(order) { [weak self] result in
self?.handleResult(result)
}
}
}
// MVVM: mantık ViewModel'de
class OrderViewModel: ObservableObject {
@Published var state: OrderState = .idle
func placeOrder() { /* iş mantığı */ }
}
Mimari seçimi ekip büyüklüğüne, proje kapsamına ve gereken test edilebilirliğe bağlıdır. 1–2 geliştiriciden oluşan bir ekip ve 20 ekrana kadar bir proje için MVVM iyi çalışır. 5+ geliştiriciden oluşan büyük bir ekip ve 50+ ekranlı bir proje için — modüler yapılı Clean Architecture. MVC hala geçerlidir mimarilerin evrimini anlamak, eski projeleri sürdürmek ve karmaşık iş mantığı olmayan basit UIKit ekranları için.
Sıkça Sorulan Sorular
Ana sorun Massive View Controller'dır. iOS'ta UIViewController her şeyi halleder: giriş işleme, View güncelleme, ağ, navigasyon ve yaşam döngüsü. Android'de Activity/Fragment benzer işlevleri yerine getirir. Sonuç olarak, denetleyici binlerce satır koda büyür, test edilmesi ve bakımı zorlaşır ve tek sorumluluk ilkesini ihlal eder.
MVC'de denetleyici doğrudan View'ı günceller ve kullanıcı girişini işler. MVVM'de denetleyici rolü, View'a referansı olmayan ViewModel tarafından gerçekleştirilir — veriler bağlama mekanizmaları aracılığıyla iletilir. ViewModel, UIKit veya Android Framework'e bağlı olmadığı için MVVM'yi test etmek daha kolaydır. Apple, SwiftUI ile MVVM'yi önerir, Google, Jetpack Compose ile MVVM'yi önerir.
Evet, MVC basit ekranlar ve prototipler için çalışan bir desen olmaya devam ediyor. Apple, basit ekranlı UIKit uygulamaları için MVC'yi önerir. Birçok ekran, ağ isteği ve önbellekleme içeren karmaşık projeler için MVVM, VIPER veya Clean Architecture seçmek daha iyidir. Yeni başlayan geliştiricilerin daha karmaşık desenleri öğrenmeden önce MVC'de ustalaşmaları önerilir.
Model izole olarak test edilir — bunlar normal veri nesneleri ve iş mantığıdır. Controller, UIKit veya Android Framework'e bağımlılık nedeniyle test edilmesi zordur. Denetleyiciden iş mantığını ayrı hizmetlere veya interactor'lara çıkarmanız önerilir, bunlar birim testlerle test edilir. View genellikle birim testlerle test edilmez — bunun için UI testleri ve ekran görüntüsü testleri kullanılır.
iOS'ta — SwiftUI ve Combine ile MVVM, 2019'dan beri Apple'ın standardı. Android'de — LiveData veya StateFlow ile MVVM, Google tarafından resmen önerilir. 5+ geliştiricili ekiplerle büyük projeler için — iOS'ta VIPER ile Clean Architecture veya Android'de özellik tabanlı modül ayrımı ile Clean Architecture. MVC'li eski projeler için — mantığı ayrı hizmetlere çıkarma ile kademeli yeniden düzenleme.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun