プロトコル抽象化による依存性逆転
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フィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- レイヤー:ドメイン、データ、プレゼンテーション
- ユースケースとリポジトリパターン
- プロトコル抽象化による依存性逆転
- DIフレームワークを使わずにレイヤーを接続する