0Pricing
Swift Academy · レッスン

プロトコル抽象化による依存性逆転

Swiftのプロトコルを境界として使用し、具象ではなく抽象に依存します。

「プロトコル抽象化による依存性逆転」はCoddyKit上の無料Swift Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはSwift Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Swift Academyコースには全4レッスンが含まれています。

依存性逆転の原則

高レベルモジュールは低レベルモジュールに依存してはいけません。どちらも抽象(プロトコル)に依存する必要があります。

// WITHOUT DIP:
class OrderService { let db = SQLiteDatabase() }  // depends on concrete
// WITH DIP:
class OrderService { let db: Database }  // depends on abstraction

抽象の定義

高レベルモジュールが必要とする契約を表すプロトコルを切り出します。

protocol Database {
  func save<T: Encodable>(_ value: T, key: String) throws
  func load<T: Decodable>(key: String) throws -> T
}

具体的な実装

プロトコルの背後に、プロダクション用、テスト用、将来の代替用など、複数の具体的な実装を用意します。

class SQLiteDatabase: Database { ... }
class InMemoryDatabase: Database { ... }
class KeychainDatabase: Database { ... }

コンストラクター注入

抽象をイニシャライザー経由で渡します。これは最も明示的で、テストしやすい注入方法です。

class ProfileService {
  private let db: Database
  init(db: Database) { self.db = db }
}

すべてをシングルトンにしない理由

グローバルなシングルトンは依存関係を隠してしまうため、コードのテストや理解が難しくなります。

// Hard to test:
class Service { func run() { MySingleton.shared.doWork() } }
// Easy to test:
class Service { let dep: MyProtocol; func run() { dep.doWork() } }

Swiftのプロトコル抽象

Swiftのプロトコルは、associated type、デフォルト実装、合成を利用できます。柔軟な抽象を構築するのに適しています。

protocol Cacheable {
  associatedtype Key: Hashable
  associatedtype Value
  func get(_ key: Key) -> Value?
  func set(_ key: Key, value: Value)
}

抽象の粒度

インターフェース分離の原則に従い、肥大化したプロトコルよりも細かいプロトコルを優先します。そうすれば、実装は呼び出し側が必要とするものだけを提供できます。

// Fat (avoid):
protocol DataStore {
  func save(...); func load(...); func delete(...); func query(...); func migrate()
}
// Narrow (prefer):
protocol Readable { func load<T>(...) throws -> T }
protocol Writable { func save<T>(...) throws }

CombineでのDIP

プロトコルメソッドから AnyPublisher を返すと、基盤となるpublisherの型を隠せます。

protocol UserStream {
  func userUpdates() -> AnyPublisher<User, Never>
}

async/awaitでのDIP

async throws を付けたプロトコルメソッドは、Swiftの構造化並行処理と完全に互換性があります。

protocol Analytics {
  func track(event: String) async
}
struct FirebaseAnalytics: Analytics {
  func track(event: String) async { /* Firebase call */ }
}

アプリレベルでのDIP

具体的な実装はアプリのエントリーポイント(Composition Root)で組み立て、すべてのバインディングを1か所に集約します。

@main
struct MyApp: App {
  let db: Database = SQLiteDatabase()
  let repo: UserRepository = RemoteUserRepository(db: db)
  let useCase = FetchUserUseCase(repo: repo)
  var body: some Scene {
    WindowGroup { ContentView(useCase: useCase) }
  }
}

DIPを使ったテスト

テストでは、注入箇所で実際の実装をモックやスタブに差し替えます。

let mockDB = InMemoryDatabase()
let service = ProfileService(db: mockDB)
// Exercise service
XCTAssertEqual(try mockDB.load(key: "profile"), expectedProfile)

確認問題

依存性逆転の原則は、高レベルモジュールについて何を定めていますか。

学習内容のまとめ

DIPでは、高レベルモジュールがプロトコルによる抽象に依存し、具体的な型がその抽象を実装します。細かいプロトコルを切り出し、コンストラクター経由で注入し、すべてをComposition Rootで組み立てます。これにより、テストや機能フラグ、将来の要件に合わせて実装を差し替えられます。

よくある質問

「プロトコル抽象化による依存性逆転」レッスンは無料ですか?

はい。「プロトコル抽象化による依存性逆転」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Swift Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Swift Academyコースには全4レッスンが含まれています。

「プロトコル抽象化による依存性逆転」で何を学びますか?

Swiftのプロトコルを境界として使用し、具象ではなく抽象に依存します。 ブラウザで直接実行するハンズオンコードでSwift Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Swift Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのSwift Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。

「プロトコル抽象化による依存性逆転」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このSwift Academyレッスンでコードを書いて実行できますか?

はい。すべてのSwift Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. レイヤー:ドメイン、データ、プレゼンテーション
  2. ユースケースとリポジトリパターン
  3. プロトコル抽象化による依存性逆転
  4. DIフレームワークを使わずにレイヤーを接続する
← Swift Academyに戻る