# MVVM Pattern — To'liq Darslik

## Mundarija
1. [Nega arxitektura kerak? (Motivatsiya)](#motivatsiya)
2. [MVC nima va uning muammolari](#mvc-muammolari)
3. [MVVM tushunchasi (Model-View-ViewModel)](#mvvm-tushunchasi)
4. [MVVM + UIKit (Closure-based)](#mvvm-uikit)
5. [MVVM + SwiftUI (@StateObject)](#mvvm-swiftui)
6. [MVVM + Combine](#mvvm-combine)
7. [Data Binding usullari](#data-binding)
8. [Dependency Injection (DI)](#dependency-injection)
9. [Unit Testing ViewModel](#testing)
10. [MVVM vs MVC vs VIPER](#mvvm-vs-others)
11. [Real loyiha: Login ekrani](#real-loyiha)
12. [Xulosa va keyingi qadamlar](#xulosa)

---

## 1. Nega arxitektura kerak? (Motivatsiya) {#motivatsiya}

Ko'pgina yangi boshlovchi dasturchilar barcha kodni (UI, API so'rovlar, ma'lumotlarni qayta ishlash) bitta `ViewController` ichiga yozishadi. Bu **"Massive View Controller"** muammosiga olib keladi:
- Kodni tushunish qiyinlashadi.
- Test yozib bo'lmaydi.
- Biror joyni o'zgartirsangiz, boshqa joy buzilib ketadi.

Arxitekturaning maqsadi — kodni qismlarga (modullarga) bo'lish va har biriga aniq mas'uliyat berishdir.

---

## 2. MVC nima va uning muammolari {#mvc-muammolari}

Apple tavsiya qilgan an'anaviy model: **Model-View-Controller**.
- **Model:** Ma'lumotlar.
- **View:** Interfeys.
- **Controller:** Oradagi "ko'prik".

**Muammo:** Controller juda "semirib" ketadi. U ham UI'ni boshqaradi, ham networking qiladi, ham biznes logikani bajaradi. Natijada kodni testlash imkonsiz bo'lib qoladi.

---

## 3. MVVM tushunchasi (Model-View-ViewModel) {#mvvm-tushunchasi}

MVVM bu muammoni hal qilish uchun **ViewModel** qatlamini qo'shadi.

- **Model:** Ma'lumot strukturasi (masalan, `User` struct).
- **View:** Faqat UI va foydalanuvchi harakatlarini qabul qilish. U "aqlsiz" bo'lishi kerak.
- **ViewModel:** Ilovaning "miyasi". U Modelni oladi, qayta ishlaydi va View'ga "tayyor" holatda beradi.

---

## 4. MVVM + UIKit (Closure-based) {#mvvm-uikit}

UIKit'da reactive tizim yo'qligi sababli, biz closure'lar orqali "Binding" qilamiz.

```swift
// ViewModel
class UserViewModel {
    var onDataUpdate: ((String) -> Void)?
    
    var name: String = "" {
        didSet { onDataUpdate?(name) }
    }
    
    func fetchUser() {
        self.name = "Azimjon" // API dan keldi deb tasavvur qilamiz
    }
}

// ViewController (View)
class UserViewController: UIViewController {
    let viewModel = UserViewModel()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Binding
        viewModel.onDataUpdate = { [weak self] name in
            self?.nameLabel.text = name
        }
        
        viewModel.fetchUser()
    }
}
```

---

## 5. MVVM + SwiftUI (@StateObject) {#mvvm-swiftui}

SwiftUI'da MVVM va Binding tabiiy (native) holatda ishlaydi.

```swift
class CounterViewModel: ObservableObject {
    @Published var count = 0
    
    func increment() {
        count += 1
    }
}

struct CounterView: View {
    @StateObject var viewModel = CounterViewModel()
    
    var body: some View {
        VStack {
            Text("Son: \(viewModel.count)")
            Button("Qo'shish") {
                viewModel.increment()
            }
        }
    }
}
```

---

## 6. MVVM + Combine {#mvvm-combine}

Combine yordamida ViewModel'dagi o'zgarishlarni reactive tarzda kuzatish mumkin. Senior darajasidagi loyihalarda ko'p ishlatiladi.

---

## 7. Data Binding usullari {#data-binding}

Binding — bu View va ViewModel o'rtasidagi aloqa:
1. **Closures:** Eng oddiy usul.
2. **Delegate:** Klassik UIKit usuli.
3. **Combine / RxSwift:** Reaktiv va professional usul.
4. **SwiftUI Property Wrappers:** @Published, @State.

---

## 8. Dependency Injection (DI) {#dependency-injection}

ViewModel ma'lumotni qayerdan (API danmi yoki Local DB danmi) olayotganini o'zi hal qilmasligi kerak. Uni tashqaridan berish kerak:

```swift
class ProductViewModel {
    private let service: NetworkService
    
    init(service: NetworkService) {
        self.service = service
    }
}
```

---

## 9. Unit Testing ViewModel {#testing}

MVVM'ning eng katta foydasi — **Testlash**. ViewModel'da UI (UIKit/SwiftUI) yo'qligi uchun uni osongina testlash mumkin.

```swift
func testCounterIncrement() {
    let vm = CounterViewModel()
    vm.increment()
    XCTAssertEqual(vm.count, 1)
}
```

---

## 10. MVVM vs MVC vs VIPER {#mvvm-vs-others}

- **MVC:** Kichik loyihalar uchun.
- **MVVM:** O'rta va katta loyihalar uchun (Eng ko'p ishlatiladigan).
- **VIPER:** Juda katta, ko'p dasturchi ishlaydigan loyihalar uchun (Murakkab).

---

## 11. Real loyiha: Login ekrani {#real-loyiha}

Tasavvur qiling, login tugmasi faqat email va parol to'g'ri bo'lsagina aktiv bo'lishi kerak. Bu logikani biz `LoginViewModel` ichida yozamiz. View faqat natijani ko'rsatadi.

---

## 12. Xulosa va keyingi qadamlar {#xulosa}

MVVM — bu bugungi kunda iOS development standartidir. Uni o'rganish sizga:
- Toza kod yozishni.
- Testlashni osonlashtirishni.
- Jamoada ishlashni qulaylashtirishni o'rgatadi.

**Vazifa:** O'zingizning kichik loyihangizni MVVM ga o'tkazib ko'ring! 🏗️
