まえがき
昨日書いた記事の反響をいただき、返信を考えていたら急に自信がなくなってきた。
思い切ってMVVMとして書いたコードだが、このViewManagerの解釈はひとりよがりなものではないだろうか…。
そこでいくつか技術記事を調べたものの、どうもViewModelとは何かがしっくりこない。
そもそも、皆さんMVVMってどう解釈しているのだろう…?!
しらべてみた
実務の場でSwiftに全く触れておらず、肌感覚が自分には全くわからない。
そこで、相棒ぐろ君(Grok)にお願いして、DeepResearchで各企業の採用アーキテクチャを調べてもらい、一覧化してもらった。
その結果が以下の通り。
※引用元のURLについて、このあとのMVVMのものも同様ですが、リンクが正しくないようです。
余裕のある時に、修正をお願いしてリンクを修正いたします。
申し訳ありません。
調査結果
◎調査依頼開始時に「MVVMやTCAなどのアーキテクチャ…」と伝えたため、ぐろ君はMVVMとTCAで当初検索したようです。追加で他のアーキテクチャは何があるかを示させた上で検索をしてもらい、MVやCleanArchitectureが出てきています。
表の印象ではMVVMかSwiftUIならTCA一択か?!となりそうですが、実態としてはMVやCleanArchitectureがもっと多くありそうです。
会社名 | UI | アーキテクチャ | 備考 | 出典 |
---|---|---|---|---|
株式会社カウシェ | SwiftUI + UIKit | MVVM | SwiftUIを主に使用しつつ、一部UIKitを併用。ViewModelを分割しテスト容易性を確保。 | カウシェ技術ブログ(2023年) |
株式会社ミンネ | SwiftUI + UIKit | MVVM(一部TCA検討) | SwiftUIとUIKit混在。Repository層でデータ管理を集中化。 | ミンネテックブログ(2023年) |
OpenWork株式会社 | UIKit(SwiftUI予定) | MVVM → TCA | TCAへ移行中。UIKit+Combineを使用し、1画面ずつTCA化を進行。 | OpenWorkテックブログ(2023年) |
freee株式会社 | SwiftUI | TCA | 新規アプリでSwiftUI+TCAを採用。Reducerをセクション単位で分割。 | freee技術ブログ(2023年) |
株式会社ニューズピックス | SwiftUI + UIKit | TCA | UIKitからSwiftUI+TCAへ移行中。XIB廃止しセルをSwiftUI化。 | NewsPicksテックブログ(2023年) |
コネヒト株式会社 | SwiftUI + UIKit | MVVM | SwiftUI導入もiOS 13サポートのためUIKit併用。RxSwiftを継続使用。 | コネヒト技術ブログ(2023年) |
リクルート株式会社 | UIKit(SwiftUI移行検討) | MVVM + Layered | UIKit中心だがSwiftUI移行を計画。Embedded Frameworkでコード共有。 | リクルート技術ブログ(2019年) |
株式会社LayerX | SwiftUI(一部UIKit) | MVVM + 独自アレンジ | 新規機能はSwiftUIで実装。View分割とCombineで最適化。 | LayerXテックブログ(2023年) |
株式会社リモートワークス | SwiftUI | TCA | 新規アプリでSwiftUI+TCAをフル採用。Reducerをモジュール化。 | 技術勉強会資料(2024年) |
株式会社FiNC Technologies | SwiftUI + UIKit | MVVM | ヘルスケアアプリでSwiftUI導入。プレビュー機能でデザイナー連携を強化。 | FiNCテックブログ(2023年) |
株式会社SmartHR | SwiftUI(新規のみ) | MVVM | 新機能でSwiftUIを試験導入。プロトタイピングを迅速化。 | SmartHRブログ(2024年) |
株式会社Drecom | SwiftUI | TCA | ゲーム関連ツールでSwiftUI+TCAを採用。ゲームロジックにReducerを適用。 | Drecomテックブログ(2023年) |
株式会社HERMES | SwiftUI | MVVM | 受託開発でSwiftUIをフル採用。コード量削減を重視。 | インタビュー記事(2024年) |
株式会社LegalOn Technologies | SwiftUI + UIKit | MVVM | 法務支援アプリでSwiftUI導入。NavigationStackをカスタマイズ。 | LegalOnテックブログ(2023年) |
株式会社カミナシ | SwiftUI | MVVM | 現場管理アプリでSwiftUI採用。Combineでリアルタイム更新を効率化。 | カミナシブログ(2024年) |
株式会社マネーフォワード | SwiftUI + UIKit | MVVM | 一部画面をSwiftUIで再構築。モジュラー化を推進。 | マネーフォワードブログ(2023年) |
株式会社ANDPAD | SwiftUI + UIKit | MVVM | 建築現場管理アプリでSwiftUI試験導入。プレビューでUI調整を効率化。 | ANDPAD技術ブログ(2024年) |
株式会社Luup | SwiftUI | TCA | 電動キックボードアプリでSwiftUI+TCA採用。副作用管理を活用。 | Luupブログ(2023年) |
株式会社クラッソーネ | SwiftUI | MVVM | 解体工事見積もりアプリでSwiftUIフル採用。アニメーションを活用。 | クラッソーネブログ(2024年) |
株式会社TRIDENT | SwiftUI | MVVM | 教育アプリでSwiftUI採用。迅速なプロトタイプ作成を重視。 | インタビュー記事(2023年) |
株式会社Speee | SwiftUI + UIKit | MVVM | 不動産アプリでSwiftUI試験導入。モジュール間依存を最小化。 | Speeeテックブログ(2024年) |
株式会社リモートウェル | SwiftUI | MVVM | リモートワークツールでSwiftUI採用。シンプルな設計を追求。 | 技術ブログ(2024年) |
株式会社HEROZ | SwiftUI + UIKit | MVVM | AI将棋アプリでSwiftUI試験導入。盤面描画はUIKit依存。 | HEROZテックブログ(2023年) |
株式会社プレイド | SwiftUI | TCA | CX管理ツールでSwiftUI+TCA採用。状態管理の一貫性を重視。 | プレイド技術ブログ(2024年) |
株式会社リモハブ | SwiftUI | MVVM | 健康管理アプリでSwiftUIフル採用。迅速な開発を優先。 | インタビュー記事(2023年) |
株式会社リンクアンドモチベーション | SwiftUI + UIKit | MVVM | エンゲージメントアプリでSwiftUI導入。既存UIKitと互換性維持。 | 技術ブログ(2024年) |
株式会社BASE | SwiftUI | MVVM | ECアプリ新機能でSwiftUI採用。Combineでデータバインディング。 | BASEテックブログ(2023年) |
株式会社メンバーズ | SwiftUI | TCA | マーケティングツールでSwiftUI+TCA採用。テスト容易性を重視。 | メンバーズブログ(2024年) |
株式会社ビットキー | SwiftUI + UIKit | MVVM | スマートロックアプリでSwiftUI試験導入。セキュリティ機能はUIKit。 | ビットキーブログ(2023年) |
株式会社リザーブリンク | SwiftUI | MVVM | 予約管理アプリでSwiftUIフル採用。保守性を重視した設計。 | リザーブリンクブログ(2023年) |
株式会社オクト | SwiftUI + UIKit | TCA | 社内ツールでSwiftUI+TCA採用。モジュール化を推進。 | オクトブログ(2024年) |
株式会社VOYAGE GROUP | SwiftUI | MVVM | アドテクアプリでSwiftUI採用。軽量なUI実装を優先。 | VOYAGEブログ(2023年) |
株式会社サイバーエージェント | SwiftUI + UIKit | MVVM | 「Ameba」でSwiftUI試験導入。既存コードとの統合を重視。 | CyberAgentブログ(2024年) |
株式会社ワークスアプリケーションズ | SwiftUI | TCA | ERPアプリ新機能でSwiftUI+TCA採用。一貫した状態管理を追求。 | ワークスブログ(2023年) |
株式会社レアゾン | SwiftUI | MVVM | AIチャットアプリでSwiftUI採用。迅速なUI開発を重視。 | インタビュー記事(2024年) |
株式会社ラクス | SwiftUI + UIKit | MV | 業務支援アプリでSwiftUI採用。ViewModelを省略しシンプルさを追求。 | ラクス技術ブログ(2024年) |
株式会社ドワンゴ | SwiftUI + UIKit | MVVM | 「ニコニコ」アプリでSwiftUI試験導入。既存コードとの統合を重視。 | ドワンゴ技術ブログ(2023年) |
株式会社はてな | SwiftUI | MV | 「はてなブックマーク」新機能でSwiftUI採用。軽量なMVパターンを使用。 | はてな技術ブログ(2024年) |
株式会社メルカリ | SwiftUI + UIKit | Clean Architecture | 一部新機能でSwiftUI+Clean採用。依存関係を明確化し拡張性を重視。 | メルカリ技術ブログ(2023年) |
株式会社クックパッド | SwiftUI | MVVM | レシピアプリ新機能でSwiftUI採用。データバインディングを最適化。 | クックパッド技術ブログ(2024年) |
株式会社リモート | SwiftUI | MV | リモートワーク支援ツールでSwiftUI採用。シンプルなMVで迅速開発。 | インタビュー記事(2023年) |
株式会社チームラボ | SwiftUI + UIKit | MVVM | アート関連アプリでSwiftUI導入。クリエイティブなUIを重視。 | チームラボ技術ブログ(2023年) |
株式会社サイボウズ | SwiftUI | Clean Architecture | グループウェア新機能でSwiftUI+Clean採用。テスト性を強化。 | サイボウズ技術ブログ(2024年) |
株式会社Sansan | SwiftUI + UIKit | MVVM | 名刺管理アプリでSwiftUI試験導入。既存UIKitと連携。 | Sansan技術ブログ(2023年) |
株式会社Preferred Networks | SwiftUI | TCA | AIツールでSwiftUI+TCA採用。状態管理の一貫性を重視。 | PFN技術ブログ(2024年) |
きいてみた
この結果を受けて、偏向はあるものの、それでも当初思っていたよりMVVMが多いことを確認できた。
そこで、洗い出しがある程度できた段階で、以下の質問をぐろ君になげかけてみた。
ところで、Swiftのアーキテクチャに関する有名な日本の書籍を書いた方は、SwiftUIにおいてはMVVMのViewModelは不要だと話していました。
SwiftUIを使いMVVMを採用している企業では、ViewModelにどのような役割を持たせているのでしょうか。freeeではTCAの採用にあたり、MVVMはメンバーごとに記載が変わる懸念があるため不採用とした経緯をブログに記載していましたが、そもそもMVVMのViewModelはどのような役割を持ち、どう記載すべきなのかがはっきりしないように思います。
SwiftUIかつMVVMとなっている企業について、それぞれのMVVMの詳細をまとめてください。
この回答が、以下。
ご質問ありがとうございます!確かに、SwiftUIにおけるMVVMのViewModelの必要性や役割については、議論の多いトピックです。SwiftUIの宣言的性質や組み込みの状態管理機能(@Stateや@ObservableObjectなど)が、従来のMVVMにおけるViewModelの役割を一部代替してしまうため、「MVVMは不要」とする意見も根強いですね。一方で、SwiftUIでMVVMを採用している企業では、ViewModelに具体的な役割を持たせ、独自の解釈や工夫を加えているケースが見られます。
以下では、まずSwiftUIにおけるMVVMのViewModelの一般的な役割と課題について整理した後、SwiftUIかつMVVMを採用している企業について、技術ブログや公開情報に基づき、その詳細をまとめます。特に、各社のViewModelがどのような役割を担い、どのように実装されているかを可能な限り明確にします。
この「以下では」を、そのまま流用してしまいます。
SwiftUIにおけるMVVMのViewModelの役割と課題
一般的な役割
MVVMのViewModelは、以下のような役割を持つとされています:
- データ変換: Modelの生データをViewが表示しやすい形に変換する(例: 日付を文字列にフォーマット)。
-
状態管理: Viewに表示するための状態(UI状態)を保持し、変更を通知する(SwiftUIでは
ObservableObject
を活用)。 - ビジネスロジック: 軽量なビジネスロジックや入力バリデーションを処理する。
- ViewとModelの分離: ViewがModelに直接依存しないよう、中間層として機能する。
SwiftUIでは、@State
や@Binding
、@ObservableObject
が状態管理を簡素化するため、ViewModelがなくてもViewとModelを直接つなげられるケースが多いです。そのため、ViewModelを導入する場合は、上記の役割を明確に定義し、不要な複雑さを避ける必要があります。
課題と議論
- 役割の曖昧さ: freeeが指摘するように、MVVMのViewModelの役割は開発者やチームによって解釈が異なりがちで、「何をどこまで担当するか」が曖昧になりやすい。
- SwiftUIとの相性: SwiftUIの宣言的UIでは、Viewが状態変化に即座に反応するため、ViewModelが単なる中間層として冗長に感じられる場合がある。
- テスト容易性とのトレードオフ: ViewModelを導入することでテストが容易になる一方、シンプルなアプリではオーバーヘッドが増える。
freeeがTCAを採用した理由として挙げた「MVVMはメンバーごとに記載が変わる懸念」は、この曖昧さがチーム開発での一貫性を損なうリスクを示しています。では、実際にMVVMを採用している企業では、どのようにViewModelを定義し、実装しているのでしょうか?
SwiftUI×MVVMにおけるViewModelの役割
どう実装されているのか、文章形式だとわかりにくいため、縦に並べて比較できるよう、表にまとめてもらった。
印象としては、Repository的な役割で表示用データを管理する場合と、単に表示の状態を管理する軽量な場合の大まかな2通りの使われ方をしているようである。
以下に、まとめてもらった表とその総括を、またそのまま流用して貼り付けます。
SwiftUIかつMVVMを採用している企業の詳細
以下は、SwiftUIかつMVVMを採用している企業のViewModelの役割を「データ変換」「状態管理」「その他のロジック」に分類し、技術ブログや公開情報に基づいてまとめたものです。
会社名 | UI | データ変換 | 状態管理 | その他のロジック | 実装の詳細・備考 | 出典 |
---|---|---|---|---|---|---|
株式会社カウシェ | SwiftUI + UIKit | 商品詳細(価格、在庫数)をView用に変換 | 在庫状況や価格変更をリアルタイムで反映 | ボタンの有効/無効判定 | ViewModelはObservableObject でCombineを使用。複雑なUIはUIKitで補完。 |
カウシェ技術ブログ(2023年) |
株式会社ミンネ | SwiftUI + UIKit | 商品一覧や作家情報をView向けに整形 | 商品の「お気に入り」や検索結果を管理 | リポジトリ連携 | 画面単位でViewModelを定義。RxSwiftで非同期処理を補完。 | ミンネテックブログ(2023年) |
コネヒト株式会社 | SwiftUI + UIKit | QAデータ(投稿日時)を「〇分前」に変換 | 投稿の表示状態(読み込み中、完了、エラー) | ユーザー入力処理 | ViewModelはObservableObject でRxSwiftを使用。iOS 13サポートでUIKit併用。 |
コネヒト技術ブログ(2023年) |
株式会社LayerX | SwiftUI(一部UIKit) | 請求書データ(金額)をカンマ区切りに変換 | 請求書リストの選択状態やフィルタ条件を管理 | 軽量な計算(合計金額) | ViewModelはObservableObject で再描画最適化。UIKitは互換性維持に限定。 |
LayerXテックブログ(2023年) |
株式会社FiNC Technologies | SwiftUI + UIKit | ヘルスケアデータをグラフ表示用に整形 | グラフ表示状態やユーザー入力(体重)を管理 | プレビュー用ダミーデータ提供 | ViewModelはObservableObject でCombineを使用。複雑なグラフはUIKit依存。 |
FiNCテックブログ(2023年) |
株式会社SmartHR | SwiftUI(新規のみ) | 人事データ(社員リスト)をフィルタリング | 選択された社員やフォーム状態を保持 | プロトタイピング用軽量ロジック | ViewModelは新規機能限定でObservableObject を使用。既存はUIKitベース。 |
SmartHRブログ(2024年) |
株式会社HERMES | SwiftUI | クライアントデータをView向けに整形 | 表示状態(ロード中、完了)を管理 | 複雑な処理はModelに委譲 | ViewModelはObservableObject でコード量削減。小規模プロジェクト向け。 |
インタビュー記事(2024年) |
株式会社LegalOn Technologies | SwiftUI + UIKit | 法務書類データ(契約書項目)をリスト化 | フォーム入力やナビゲーション状態を管理 | NavigationStackのカスタマイズ | ViewModelはObservableObject でCombineを使用。複雑なフォームはUIKit依存。 |
LegalOnテックブログ(2023年) |
株式会社カミナシ | SwiftUI | 現場データをリアルタイム表示用に整形 | データ更新やエラー状態を管理 | API呼び出しをViewModel内で処理 | ViewModelはObservableObject でCombineを使用。小規模チーム向けにシンプル化。 |
カミナシブログ(2024年) |
株式会社マネーフォワード | SwiftUI + UIKit | 家計簿データ(カテゴリ集計)を変換 | 表示モード(リスト/グラフ)や選択状態を管理 | UIKitコードとのブリッジ調整 | ViewModelはObservableObject でモジュール性重視。移行段階での柔軟性を確保。 |
マネーフォワードブログ(2023年) |
株式会社クラッソーネ | SwiftUI | 見積もりデータをView向けに整形 | 見積もり入力やアニメーション状態を管理 | 入力データをModelに反映 | ViewModelはObservableObject でアニメーション支援。ユーザー体験を重視。 |
クラッソーネブログ(2024年) |
株式会社TRIDENT | SwiftUI | 教育コンテンツデータを整形 | 表示状態やユーザー進捗を管理 | プロトタイピング用軽量ロジック | ViewModelはObservableObject で小規模開発向け。迅速な試作を優先。 |
インタビュー記事(2023年) |
株式会社Speee | SwiftUI + UIKit | 不動産データをView向けに変換 | 検索条件や選択状態を管理 | UIKitとの依存最小化 | ViewModelはObservableObject でモジュール分離。試験導入段階。 |
Speeeテックブログ(2024年) |
株式会社リモートウェル | SwiftUI | リモートワークツールデータを整形 | ツール使用状況を管理 | 軽量ロジックのみ | ViewModelはObservableObject でシンプル設計。小規模アプリ向け。 |
技術ブログ(2024年) |
株式会社HEROZ | SwiftUI + UIKit | 将棋データをView向けに変換 | 盤面の表示状態を管理 | UIKit描画との同期 | ViewModelはObservableObject でCombine使用。AI将棋アプリ向け。 |
HEROZテックブログ(2023年) |
株式会社リモハブ | SwiftUI | 健康管理データをView向けに整形 | 健康データ更新状態を管理 | 軽量ロジックで迅速開発 | ViewModelはObservableObject で迅速開発支援。小規模アプリ向け。 |
インタビュー記事(2023年) |
株式会社リンクアンドモチベーション | SwiftUI + UIKit | エンゲージメントデータを変換 | 社員データの表示状態を管理 | UIKitとの連携調整 | ViewModelはObservableObject で既存コード統合。互換性重視。 |
技術ブログ(2024年) |
株式会社BASE | SwiftUI | ECデータをView向けに整形 | 商品選択や表示状態を管理 | Combineでリアルタイム更新 | ViewModelはObservableObject で新機能向け。データバインディング重視。 |
BASEテックブログ(2023年) |
株式会社ビットキー | SwiftUI + UIKit | スマートロックデータを変換 | ロック状態を管理 | セキュリティ機能と連携 | ViewModelはObservableObject でセキュリティ調整。セキュリティ重視。 |
ビットキーブログ(2023年) |
株式会社リザーブリンク | SwiftUI | 予約データをView向けに整形 | 予約状況を管理 | シンプルなロジックで保守性確保 | ViewModelはObservableObject で保守性重視。予約管理アプリ向け。 |
リザーブリンクブログ(2023年) |
株式会社VOYAGE GROUP | SwiftUI | アドテクデータをView向けに整形 | 表示状態を管理 | 軽量なUI実装支援 | ViewModelはObservableObject で軽量設計。アドテクアプリ向け。 |
VOYAGEブログ(2023年) |
株式会社サイバーエージェント | SwiftUI + UIKit | 「Ameba」データをView向けに変換 | ブログ表示状態を管理 | 既存UIKitコードとの統合 | ViewModelはObservableObject で試験導入。統合重視。 |
CyberAgentブログ(2024年) |
株式会社レアゾン | SwiftUI | AIチャットデータをView向けに整形 | チャット状態を管理 | UI開発の迅速化 | ViewModelはObservableObject で小規模向け。AIアプリ向け。 |
インタビュー記事(2024年) |
株式会社ラクス | SwiftUI + UIKit | 業務支援データをView向けに変換 | 業務フローの状態を管理 | 軽量ロジックでシンプル化 | ViewModelはObservableObject でUIKit連携。シンプルさ重視。 |
ラクス技術ブログ(2024年) |
株式会社ドワンゴ | SwiftUI + UIKit | 「ニコニコ」動画データをView向けに整形 | 再生状態を管理 | 既存UIKitコードとの調整 | ViewModelはObservableObject で試験導入。既存アプリ統合。 |
ドワンゴ技術ブログ(2023年) |
株式会社クックパッド | SwiftUI | レシピデータをView向けに整形 | レシピ選択状態を管理 | データバインディング最適化 | ViewModelはObservableObject で新機能向け。テスト性重視。 |
クックパッド技術ブログ(2024年) |
株式会社チームラボ | SwiftUI + UIKit | アートデータをView向けに変換 | 表示状態を管理 | クリエイティブな挙動支援 | ViewModelはObservableObject でUIKit連携。アートアプリ向け。 |
チームラボ技術ブログ(2023年) |
株式会社Sansan | SwiftUI + UIKit | 名刺データをView向けに整形 | 名刺リストの状態を管理 | 既存UIKitコードと同期 | ViewModelはObservableObject で試験導入。名刺管理アプリ向け。 |
Sansan技術ブログ(2023年) |
総括と考察
ViewModelの役割の傾向
-
データ変換と状態管理が中心: ほとんどの企業で、ViewModelはModelデータの整形とViewの状態管理を担当。SwiftUIの
ObservableObject
と@Published
を活用し、リアルタイム更新を実現。 - 軽量ロジックの集約: 入力バリデーションや簡単な計算をViewModelに持たせ、複雑なビジネスロジックはModelや別層に分離する傾向。
- UIKitとの橋渡し: SwiftUIとUIKitが混在する場合、ViewModelが互換性を保つ役割を担う(例: マネーフォワード、LegalOn)。
freeeの懸念との関連
freeeが「MVVMはメンバーごとに記載が変わる」と懸念した点は、上記の企業でも微妙な違いとして現れています:
- 役割の範囲: 例えば、カウシェやLayerXでは軽量なビジネスロジックをViewModelに含める一方、HERMESやカミナシでは極力シンプルに保ち、Modelにロジックを委譲。
- 実装スタイル: Combineを使う企業(LayerX、カミナシ)とRxSwiftを併用する企業(コネヒト)で、非同期処理のアプローチが異なる。
どう記載すべきか?
- 明確なガイドラインが必要: ViewModelの役割をチーム内で事前に定義(例: データ変換のみ、状態管理のみ、軽量ロジックまで)し、文書化する。
-
一貫性を保つ命名と構造:
SearchViewModel
のように画面単位でViewModelを定義し、役割を明示的にコメントやプロトコルで規定。 -
SwiftUIの特性を活かす:
@ObservableObject
を基本とし、必要以上の抽象化(例: 過剰なプロトコル)は避ける。
SwiftUIの特性上、ViewModelは「Viewのためのデータホルダー」としてシンプルに保つのが理想的です。一方で、複雑なアプリでは、freeeのようにTCAやClean Architectureを採用し、役割の曖昧さを排除する選択肢も有効かもしれません。
まとめ
実務経験がなく現役のSwiftエンジニアとはほぼ全く会話したことがない私であったが、DeepResearchの力を借り、視野と深さを持つ地に足のついた検討ができたように思う。
調査開始前は、現場のエンジニアの総意としてViewModelがどう考えられているのか全くわからない状況であった。
しかし、こうして聞いて表にまとめてもらうことで、おおよそどのように考えられているのかを掴むことができた。
そして、自分の考えていた回答もそれほど実態と離れたものではないことがわかって、かなり安心した。
また、昨日の記事(SwiftUI時代のアーキテクチャ選定では「しょうきMVVMが最適」と書いたが、単に「MV」で良いとの指摘や、実際に「MV」を使っている企業も多いというのは、新しい発見であった。
記事を書くことで新たなフィードバックを得られるし、そのフィードバックをもとに新たな知識が身につくので、時間がある時にはmこうしてアウトプットに時間を使ってみたい。