Swiftのプロジェクト設計：MVVM, VIPER, Clean Architectureの違い

# Swiftのプロジェクト設計：MVVM, VIPER, Clean Architectureの違い

Swiftを使ってアプリを開発する際、プロジェクトの設計をどうするかは非常に重要です。
設計を適切に行うことで、可読性が向上し、保守しやすいコードを書くことができます。


- **MVCでは限界を感じているけれど、他のアーキテクチャがよくわからない**
- **MVVM、VIPER、Clean Architectureといった設計パターンの違いを知りたい**
- **どのアーキテクチャを選べばいいのか判断に迷っている**

自分の学習内容の整理も兼ねて、それぞれのアーキテクチャの特徴や違いを解説し、サンプルコードを交えて理解を深めていきます。

---

## MVVMとは？

MVVM（Model-View-ViewModel）は、UIロジックとビジネスロジックを分離するためのアーキテクチャです。

### **構成要素**
- **Model**（データ層）: APIやデータベースから情報を取得。
- **View**（UI層）: 画面の表示を担当。
- **ViewModel**（UIロジック層）: ViewとModelの仲介役。

```swift
import Foundation

// Model
struct User {
    let id: Int
    let name: String
}

// ViewModel
class UserViewModel: ObservableObject {
    @Published var userName: String = ""
    
    func fetchUser() {
        let user = User(id: 1, name: "Taro")
        self.userName = user.name
    }
}
```

```swift
import SwiftUI

// View
struct ContentView: View {
    @StateObject private var viewModel = UserViewModel()
    
    var body: some View {
        VStack {
            Text(viewModel.userName)
            Button("Fetch User") {
                viewModel.fetchUser()
            }
        }
    }
}
```

### **MVVMのメリット・デメリット**
- UIとロジックの分離がしやすく、テストしやすい  
- SwiftUIとの相性が良い  
- 小規模なプロジェクトではオーバーヘッドが大きくなる可能性がある 

---

## VIPERとは？

VIPERは、責務を明確に分けることで、コードの可読性や再利用性を高める設計パターンです。

### **構成要素**
- **View**（画面表示）
- **Interactor**（ビジネスロジック担当）
- **Presenter**（ViewとInteractorを橋渡し）
- **Entity**（データの定義）
- **Router**（画面遷移）

### **VIPERのサンプルコード**

```swift
protocol UserInteractorProtocol {
    func fetchUser() -> User
}

class UserInteractor: UserInteractorProtocol {
    func fetchUser() -> User {
        return User(id: 1, name: "Taro")
    }
}
```

```swift
protocol UserPresenterProtocol {
    func loadUser()
}

class UserPresenter: UserPresenterProtocol {
    private let interactor: UserInteractorProtocol
    private weak var view: UserViewProtocol?
    
    init(view: UserViewProtocol, interactor: UserInteractorProtocol) {
        self.view = view
        self.interactor = interactor
    }
    
    func loadUser() {
        let user = interactor.fetchUser()
        view?.displayUserName(user.name)
    }
}
```

```swift
protocol UserViewProtocol: AnyObject {
    func displayUserName(_ name: String)
}

class UserViewController: UIViewController, UserViewProtocol {
    var presenter: UserPresenterProtocol!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        presenter.loadUser()
    }
    
    func displayUserName(_ name: String) {
        print("User Name: \(name)")
    }
}
```

### **VIPERのメリット・デメリット**
- 各コンポーネントの責務が明確で、拡張しやすい  
- テストしやすい  
- ファイル数が増え、小規模プロジェクトでは管理が難しくなることがある  

---

## Clean Architectureとは？

Clean Architectureは、アプリの依存関係を明確にし、テスト可能なコードを書くことを目的としています。

### **層の構成**
1. **Entities**（ビジネスルール）
2. **Use Cases**（アプリケーション固有のロジック）
3. **Interface Adapters**（データ変換やView）
4. **Frameworks & Drivers**（iOSフレームワークや外部ライブラリ）

```swift
// Entity
struct User {
    let id: Int
    let name: String
}
```

```swift
// Use Case
protocol UserRepository {
    func getUser() -> User
}

class GetUserUseCase {
    private let repository: UserRepository
    
    init(repository: UserRepository) {
        self.repository = repository
    }
    
    func execute() -> User {
        return repository.getUser()
    }
}
```

```swift
// Adapter
class UserPresenter {
    private let useCase: GetUserUseCase
    
    init(useCase: GetUserUseCase) {
        self.useCase = useCase
    }
    
    func fetchUserName() -> String {
        return useCase.execute().name
    }
}
```

### **Clean Architectureのメリット・デメリット**
- 高いテスト容易性と拡張性  
- 依存関係が整理され、スケーラブルな設計が可能  
- 設計が複雑になり、小規模プロジェクトには不向き 

---

## まとめ
| アーキテクチャ | 特徴 | 適用ケース |
|-------------|------------|------------|
| MVVM | シンプルでSwiftUI向き | 小～中規模のアプリ |
| VIPER | 責務分離が明確 | 大規模アプリ・長期運用アプリ |
| Clean Architecture | 依存関係が整理される | 超大規模アプリ |

プロジェクトの規模や目的に応じて、最適なアーキテクチャを選択した方がより良い雪渓と言えるのかも知れません。