【SwiftUI】ワンオペ屋台から魔法の厨房へ:MVVMとは
【脱・ワンオペ】MVCの店長が「魔法の厨房(MVVM)」に救われるまで
なぜ、僕らのアプリはすぐにスパゲッティになるのか?
「あれ? 変数の数字は増えているのに、画面の表示が 0 のままだ……」
プログラミングを始めたばかりの頃、こんな経験はないだろうか。
原因は単純。
「変数を更新した後、ラベルの書き換え(text = ...)を忘れていたから」だ。
一つならまだいい。でも、機能が増えるとどうなるか。
「読み込み中はローディングを出して、成功したら消して、リストを表示して、あ、失敗した時はアラートを出して……」
気付けばコードは、「もし〇〇なら、××を表示しろ」という 大量の「命令」 で埋め尽くされている。どこか一箇所でも命令を書き忘れたら、アプリは動かないか、古い情報を表示し続ける。
これは例えるなら、「超・完璧主義のワンオペ店長」が支配するお店だ。
店長(あなた)は、厨房で料理を作りながら、ホールの状況を全て記憶し、「A卓に水! B卓は片付け! C卓へ料理運んで!」と、一瞬も休まず叫び続けなければならない。
これでは、客(機能)が増えた瞬間に店がパンクするのは当たり前だ。
もしあなたが、そんな「命令し続けること」に疲れ果てているなら、少しだけ店(アーキテクチャ)の改装の話を聞いてほしい。
これは、ワンオペで叫び続ける店長が、「魔法の仕組み」によって解放されるまでの物語だ。
1. 悲劇のワンオペ時代(MVC: Imperative)
UIKit時代のMVC、特にその実装が肥大化してしまった現場を思い出してみよう。
これは例えるなら、「伝説のスーパー店長(Controller)」が支配するワンオペ屋台だ。
店長(Controller)の仕事
厨房(Model)と客席(View)の間に立ち、全ての動きを命令する。
- 客が来る(Event)。
- 店長がシェフに「ハンバーグ作れ!」と叫ぶ。
- シェフがハンバーグを作る。
- ここが重要: 店長はハンバーグが出来たことを確認し、自分でホールスタッフに「おい!A卓にこれを運べ!」と命令しなければならない。
コードで書くと、こういうことだ。
// 典型的なMVCの悲劇
func updateView() {
// 店長が全てを把握し、一つ一つ指示(代入)する
titleLabel.text = user.name
descriptionLabel.text = user.profile
iconImageView.image = user.icon
// もしここで priceLabel.text の更新を書き忘れたら?
// → 画面は古い価格のまま(バグ)
}
店が繁盛する(機能が増える)につれ、店長は「A卓に水!B卓は会計!C卓のハンバーグまだか!」と叫び続けることになる。
これが 「命令型(Imperative)」 の限界だ。店長の記憶力と体力が尽きた瞬間、店(アプリ)は崩壊する。
2. 革命的システムの導入(MVVM: Declarative)
SwiftUI時代のMVVMは、この店長をクビにすることから始まる。
代わりに導入されたのが、 「魔法の受け渡しカウンター(ViewModel)」と「監視カメラ(Binding)」 だ。
この新しい店(ハイテク定食屋)には、もう叫ぶ人はいない。
シェフの意識改革(ViewModel)
シェフ(ロジック担当)は、もう客席(View)のことなんて気にしない。
「今、客席がどうなっているか」を知る必要すらないのだ。
彼がやることはただ一つ。料理ができたら、決まった 「魔法のカウンター(@Published)」 に置くことだけ。
class OrderViewModel: ObservableObject {
// これが「魔法のカウンター」
@Published var currentDish: String = "準備中"
func cook() {
// シェフは料理を作ってカウンターに置くだけ。
// 「客席に運べ」とは言わない。
self.currentDish = "特製オムライス"
}
}
ホールスタッフの自動化(View)
ホールスタッフ(View)も、誰かの指示を待ったりしない。
カウンターには「監視カメラ」が設置されており、 「カウンターに料理が置かれた瞬間、ホールのテーブルにも同じものが転送される」 という仕組み(データバインディング)が出来上がっている。
struct OrderView: View {
// カウンターを監視する
@StateObject var viewModel = OrderViewModel()
var body: some View {
// 料理が置かれたら、勝手に画面に出る
// 「表示しろ」という命令は存在しない
Text(viewModel.currentDish)
}
}
これが 「宣言的(Declarative)」 な世界だ。
「シェフがカウンターの状態を変える」=「客席の見た目が変わる」。
そこにタイムラグも、命令の伝達ミスも、店長の過労も存在しない。直結しているのだ。
3. 制御を手放す勇気
MVCからMVVMへの移行、それは単なるコードの書き換えではない。
「全てをコントロールしたい」というエンジニアの強迫観念からの脱却だ。
かつての私たちは、すべての変数を監視し、すべてのタイミングで setText を呼ばなければ気が済まなかった。それは「安全設計」のつもりで、その実、自分自身(Controller)をボトルネックにする行為だったのだ。
MVVM + SwiftUIの世界では、私たちはシステムを信頼し、制御を手放すことになる。
「状態(State)」さえ正しく定義すれば、結果(View)は約束される。
このアーキテクチャが教えてくれるのは、「個々の役割(関心事の分離)を尊重し、過干渉をやめる」という、チーム開発においても、人生においても重要なスタンスなのかもしれない。
さあ、あなたのコードから、叫び続ける店長を解放してあげよう。
魔法のカウンターは、もう準備できている。
Discussion