モバイル開発におけるSoC:その意味、原則、責任の分離

著者: IT Sectr 公開日: 2026-05-13 読了時間: 8 分

SoC(Separation of Concerns)とは、ソフトウェアシステムを責任の分離された領域に分割する原則の略語です。Martin Fowlerによると、関心の分離は保守可能なコードの鍵となる要素です。SoCの原則により、開発者はアプリケーションの1つのレイヤーを他のレイヤーに影響を与えずに変更でき、これはチームでのモバイル開発において特に重要です。

重要なポイント

  • SoC はSeparation of Concernsの略で、責任領域ごとにコードを分割することを意味します
  • この略語はアーキテクチャ議論においてレイヤーの独立性の原則を示すために使用されます
  • MVP、MVVM、Clean Architecture はiOSおよびAndroidプロジェクトでSoCを実装するパターンです
  • レイヤーの分離により単体テストが容易になり、開発者間の作業を並列化できます
  • SoCの違反は、何千行にも及ぶクラスを生み出し、保守が困難になります

SoCという略語の意味

SoC はSeparation of Concernsの略で、「責任の分離」または「関心領域の分離」を意味します。開発の文脈において、concernという用語は、ユーザーインターフェースの表示、クリック処理、データ検証、ネットワーク通信、データベース操作など、分離可能な機能を指します。SoCの原則は、ある領域の変更が他の領域に影響を与えないように、コードをこれらの領域ごとにグループ化することを指示します。

略語 SoC は、技術文献、アーキテクチャ議論、フレームワークのドキュメントで広く使用されています。例えば、Android Architecture Componentsのドキュメントでは、ViewModelとViewを分離する動機としてSoCが繰り返し言及されています。iOSコミュニティでは、Massive View Controllerの問題を議論する際にこの用語が使用されます。これはSoCの欠如の直接的な結果です。

SoC は一度きりのアクションではなく、継続的なプロセスであることを理解することが重要です。アプリケーションの成長に伴い、新たな責任領域が生まれ、アーキテクチャを見直す必要があります。優れたコードベースは、各concernが分離され管理可能な安定状態に達するまで、分離の反復を数回経ます。

SoC vs Separation of Concerns

Separation of Concerns とその略語SoCは同じ原則を指します。違いは使用コンテキストのみです。完全な名称は正式な文書、教育資料、新しい開発者に初めて概念を説明する際に使用されます。SoCは、簡潔さが重要な技術的議論、コードレビュー、ドキュメントに便利です。

プロフェッショナルな環境では、両方の用語は互換性があります。開発者は「ここでSoCが違反されている」または「これはSeparation of Concernsに違反している」と言うことができ、意味は変わりません。ただし、求人広告やアーキテクチャ要件では完全な名称がより頻繁に使用され、チャットやコードレビューでは略語が使用されます。業界にスムーズに入るには、両方のバリアントを知る必要があります。

用語の混乱があります。SoCという略語は、ハードウェアの文脈ではSystem-on-a-Chip(システムオンチップ)にも使用されます。モバイル開発では、文脈は常に環境から明らかです。議論がコードアーキテクチャに関するものであれば、それはSeparation of Concernsを指します。この記事では、SoCは常に責任分離の原則を指します。

モバイルアーキテクチャにおけるSoCの適用方法

3層アーキテクチャは、モバイルアプリケーションでSoCを実装する最も一般的な方法です。コードをPresentation(UI)、Domain(ビジネスロジック)、Data(データソース)に分割します。各レイヤーには厳密に定義されたクラスタイプが含まれ、インターフェースを介して隣接レイヤーから分離されています。このアプローチはiOS、Android、Flutterプロジェクトに等しく効果的です。

PresentationレイヤーとViewModel

ViewとViewModel はプレゼンテーションレイヤーを形成します。Viewはインターフェースのレンダリングとユーザーイベントの転送を担当します。ViewModelは画面の状態を保持し、Domainレイヤーからのデータを表示用の形式に変換します。ViewModelはActivity、Fragment、UIViewControllerへの参照を持ちません。これによりUIとロジック間のSoCが確保されます。

例えば、Android Jetpackでは、ViewModelは画面回転後も存続し、UIは再作成されます。SoCがなければ、Activityに状態を保存しなければならず、ライフサイクル管理とデータが混在することになります。ViewModelはこの問題を分離して解決し、責任分離の原則のクリーンな実装を示しています。

Domainレイヤーとユースケース

ユースケース にはプラットフォームに依存しないビジネスルールが含まれます。このレイヤーはAndroid SDK、iOS UIKit、Flutter frameworkをインポートしません。ユースケースはRepositoryからデータを受け取り、ビジネスロジックを適用して結果を返します。SoCのおかげで、1つのユースケースを異なる画面やプラットフォームで再利用できます。

古典的な例は、登録フォーム用の ValidateAndSaveUseCase です。電子メールとパスワードの検証を行い、UserRepositoryを呼び出して保存し、ValidationResultを返します。UIもデータベースも検証ルールを知りません。それらは一箇所に集中しており、変更が容易です。

DataレイヤーとRepository

Repository はデータソースをアプリケーションの他の部分から抽象化します。ViewModelはデータがREST API、GraphQL、ローカルデータベース、キャッシュのどこから来るのかを知りません。Repositoryは使用するソースを決定し、このロジックをインターフェースの背後に隠します。これがデータ取得とデータ消費の間のSoCです。

DataSourceはさらに 深い 分離を提供します。RemoteDataSourceはHTTPリクエストのみを担当し、LocalDataSourceはRoom、CoreData、SharedPreferencesとの連携を担当します。Repositoryはキャッシュ戦略を適用してこれらを組み合わせます。各DataSourceは独立して置き換えることができ、サーバーやデータベース間の移行時に重要です。

このような 多層的な DataSourceシステムは、インフラストラクチャレベルでSoCを実装します。ネットワーク通信、ローカルストレージ、キャッシングは別々のconcernであり、それぞれが独自のロジックとライフサイクルを持ちます。HTTPクライアントを交換する場合、RemoteDataSourceのみが変更され、Repositoryと上位レイヤーは影響を受けず、責任分離の実用的価値を確認できます。

アーキテクチャパターンにおけるSoC

MVP(Model-View-Presenter)は、モバイル開発でSoCを明示的に実装した最初のパターンの1つです。Presenterはロジックを含み、インターフェースを介してViewを制御します。Viewは受動的で、Presenterが指示する内容を表示するだけです。この分離によりテストが容易になります。Presenterはエミュレータなしでテストでき、Viewは非常にシンプルで壊れるものがありません。

MVVM はリアクティブバインディングを追加しました。ViewはObservableやStateFlowを介してViewModelの変更を購読します。ViewModelはViewへの参照を保持しないため、メモリリークのリスクがなくなり、concernがさらに分離されます。AndroidではJetpack ViewModelとLiveDataのおかげでMVVMが標準になり、iOSではCombineとRxSwiftのおかげです。

Robert Martinの Clean Architecture はSoCをリングによる抜本的な分離にまで高めます。外側のリング(フレームワークとドライバー)は内側(エンティティ)に依存しますが、その逆はありません。実際には、モバイルプロジェクトが4つのリングすべてを実装することは稀で、Presentationの周りのDomainレイヤーとDataレイヤーで十分です。しかし「内向き依存」の原則は、フレームワークを変更する際に大きな利点をもたらします。

swift
// View — 表示のみ、ロジックなし
final class LoginViewController: UIViewController {
    let viewModel: LoginViewModel

    func loginTapped() {
        viewModel.login(emailField.text, passwordField.text)
    }
}

// ViewModel — 画面ロジックを含み、UIKitを知らない
final class LoginViewModel {
    private let loginUseCase: LoginUseCase

    func login(email: String?, password: String?) {
        loginUseCase.execute(email, password)
    }
}

// Use Case — ビジネスロジック、プラットフォーム非依存
final class LoginUseCase {
    private let repo: AuthRepository

    func execute(email: String?, password: String?) {
        guard let e = email, let p = password else { return }
        repo.authenticate(e, p)
    }
}

この例は SoCの3つのレベル を示しています。LoginViewControllerはイベントを渡すだけ、LoginViewModelは状態を管理、LoginUseCaseはビジネスルールを含みます。各クラスは独立してテストでき、UIフレームワークを変更してもユースケースには影響しません。

モバイルプロジェクトにおけるSoCの典型的な違反

Massive View Controller はiOSで最も一般的なSoC違反です。UIを管理し、ネットワークリクエストを処理し、JSONをパースし、データを永続化するクラスは、すべてのレベルで原則に違反しています。解決策は、各責任を別々のコンポーネント(NetworkingService、JSONParser、CoreDataStack)に抽出し、ViewControllerにはViewの管理のみを残すことです。

Android でも同様の問題はGod ActivityやGod Fragmentです。データのロード、フォームの検証、ダイアログの表示、UIの更新をすべて行う1つのアクティビティです。これはViewModelとRepositoryを導入することで治療され、状態管理とデータ処理を引き受けます。ViewModelは画面回転時のデータ損失も防ぎます。

3つ目の違反は プラットフォームコードとビジネスコードの混合 です。例えば、SwiftUI ViewやAndroid Composableに直接HTTPリクエストを配置することです。これによりコードは移植性がなくなり、テストが困難になります。正しいアプローチは、リクエストをRepositoryに移動し、ユースケースを介して呼び出し、Viewは結果を購読するだけにすることです。システムの各要素は自身のタスクを解決し、その境界を越えません。

よくある質問

SoCとSOLIDは同じものですか?

いいえ。SoCはシステムを責任領域に分割するより一般的な原則です。SOLIDはオブジェクト指向設計のための5つの具体的なルールのセットです。SOLIDの最初の原則(Single Responsibility)は、単一クラスレベルでのSoCの特殊なケースです。

プロジェクトでSoCが守られているか確認するには?

単一変更理由のルール(Single Responsibility)を使用してください。クラスがUI、データ形式、ビジネスルールの変更によって変更される場合、SoCが違反されています。ArchTest(Android)やStrictConcurrency(iOS)などのツールは、このような違反を自動的に検出するのに役立ちます。

SoCはパフォーマンスを低下させますか?

理論的には、追加のレイヤーは間接的な呼び出しを追加しますが、実際にはモバイルアプリケーションのパフォーマンスへの影響は無視できます。コンパイラは多くの呼び出しをインライン化し、JITおよびAOT最適化がオーバーヘッドを排除します。コードの保守性は、抽象化によって失われるものよりもはるかに大きな利益をもたらします。

既存のプロジェクトにSoCを導入するには?

まずUIからネットワークリクエストを 抽出 してRepositoryに入れます。次にビジネスロジックをユースケースに移動します。依存性注入を使用してレイヤーを接続します。変更を反復的に行い、新しいコードをテストでカバーします。これによりリファクタリングが既存機能を壊さないことが保証されます。

プロトタイプやMVPでもSoCを守る必要がありますか?

プロトタイプでは、スピードのためにSoCを犠牲にしても構いません。しかしプロトタイプがプロダクション開発に移行する場合、リファクタリングのコストが迅速な開始の利点を上回る可能性があります。最適なのは、プロトタイプでも最小限の分離(UIとデータ)を維持し、ローンチ時にすべてをゼロから書き直さないようにすることです。

まとめ

  • SoC はSeparation of Concernsの略で、コードを独立した責任領域に分割する原則
  • 3層アーキテクチャ(Presentation、Domain、Data)はモバイル開発でSoCを実装する標準的な方法
  • MVPとMVVM はUIとビジネスロジックの分離に基づくアーキテクチャパターン
  • Clean Architecture はSoCをシステム全体に拡張し、ビジネスエンティティをフレームワークから分離
  • Massive View Controller はSoC違反の直接的な結果で、レイヤー抽出によって修正
  • 依存性注入 はSoC実装時にレイヤー間の境界を維持するための重要なツール
  • バランス 分離とシンプルさの間が、SoCを実践で適用する際の主要なルール

ターンキー方式のモバイルアプリケーションを開発します

IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。

プロジェクトについて相談

こちらもお読みください