ユースケースとリポジトリパターン
ユースケースをSwiftプロトコルとして定義し、リポジトリインターフェースを実装します。
「ユースケースとリポジトリパターン」はCoddyKit上の無料Swift Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはSwift Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Swift Academyコースには全4レッスンが含まれています。
ユースケースとは
ユースケース(インタラクター)は、単一のビジネスアクションをカプセル化し、ドメインエンティティとリポジトリを調整します。
struct PlaceOrderUseCase {
let cart: CartRepository
let payment: PaymentService
let orders: OrderRepository
func execute(userId: Int) async throws -> Order {
let items = try await cart.items(for: userId)
let receipt = try await payment.charge(items: items)
return try await orders.create(receipt: receipt)
}
}単一責任
各ユースケースは、まさに1つのことだけを行います。複数の責任がある場合は、複数のユースケースに分割します。
// One use case per business action:
struct FetchUserUseCase { ... }
struct UpdateUserUseCase { ... }
struct DeleteUserUseCase { ... }プロトコルとしてのユースケース
ユースケース用のプロトコルを定義すると、プレゼンテーション層のテストでモックに差し替えられます。
protocol PlacingOrder {
func execute(userId: Int) async throws -> Order
}
struct PlaceOrderUseCase: PlacingOrder { ... }リポジトリとは
リポジトリはデータソースを抽象化します。呼び出し側はSwiftのプロトコルを通じて操作し、実装にはネットワーク、Core Data、メモリ内のデータなどを利用できます。
protocol OrderRepository {
func create(receipt: PaymentReceipt) async throws -> Order
func list(userId: Int) async throws -> [Order]
func cancel(orderId: Int) async throws
}リポジトリの実装
具体的なリポジトリは、ドメインからの呼び出しをネットワークやデータベースの操作に変換します。
struct RemoteOrderRepository: OrderRepository {
func create(receipt: PaymentReceipt) async throws -> Order {
let dto = receipt.toDTO()
let data = try await api.post("/orders", body: dto)
return try JSONDecoder().decode(OrderDTO.self, from: data).toDomain()
}
func list(userId: Int) async throws -> [Order] { ... }
func cancel(orderId: Int) async throws { ... }
}テスト用のメモリ内リポジトリ
I/Oを使わずに高速で決定論的なテストを行えるよう、メモリ内リポジトリを用意します。
final class InMemoryOrderRepo: OrderRepository {
var orders: [Order] = []
func create(receipt: PaymentReceipt) async throws -> Order {
let order = Order(id: orders.count + 1, items: receipt.items)
orders.append(order)
return order
}
func list(userId: Int) async throws -> [Order] { orders }
func cancel(orderId: Int) async throws { orders.removeAll { $0.id == orderId } }
}ユースケースの組み合わせ
ユースケースは、共通するサブ処理のために他のユースケースを呼び出せます。これにより、それぞれの役割を明確に保てます。
struct CheckoutUseCase {
let validateCart: ValidateCartUseCase
let placeOrder: PlaceOrderUseCase
let notifyUser: NotifyUserUseCase
func execute(userId: Int) async throws -> Order {
try await validateCart.execute(userId: userId)
let order = try await placeOrder.execute(userId: userId)
try await notifyUser.execute(order: order)
return order
}
}リポジトリとサービスの違い
リポジトリ:単一のエンティティ型に対するCRUDを行います。サービス:複数のエンティティを調整したり、直接ストレージを扱わずに外部APIを呼び出したりします。
// Repository: single entity
protocol UserRepository { func getUser(id: Int) async throws -> User }
// Service: cross-entity operation
protocol AuthService { func login(email: String, password: String) async throws -> Session }リポジトリでのキャッシュ
リポジトリは、実装の詳細をユースケースに意識させることなく、透過的に結果をキャッシュできます。
struct CachedUserRepository: UserRepository {
private var cache: [Int: User] = [:]
private let remote: UserRepository
func getUser(id: Int) async throws -> User {
if let cached = cache[id] { return cached }
let user = try await remote.getUser(id: id)
cache[id] = user
return user
}
func saveUser(_ user: User) async throws { try await remote.saveUser(user) }
}テスト容易性
ユースケースはプロトコルで定義されたリポジトリに依存するため、スタブを注入してビジネスロジックを単独でテストできます。
let repo = InMemoryOrderRepo()
let sut = PlaceOrderUseCase(orders: repo, ...)
let order = try await sut.execute(userId: 1)
XCTAssertEqual(repo.orders.count, 1)エラーの変換
リポジトリは、データ層のエラー(ネットワークやDBのエラー)を返す前にドメインエラーへ変換する必要があります。
func getUser(id: Int) async throws -> User {
do {
let data = try await api.get("/users/\(id)")
return try decode(data)
} catch let e as URLError where e.code == .notConnectedToInternet {
throw DomainError.offline
}
}確認問題
Clean Architectureにおけるリポジトリとサービスの主な違いは何ですか。
学習内容のまとめ
ユースケースは単一のビジネスアクションをカプセル化し、リポジトリプロトコルに依存します。リポジトリはプロトコルの背後でデータソースを抽象化します。高速なテストにはメモリ内リポジトリを使用します。リポジトリはインフラストラクチャのエラーをドメインエラーに変換します。サービスは複数のエンティティにまたがる処理を調整します。
AI チューターと学ぶ Swift — 無料
ブラウザでリアルコードを書いて実行し、24/7 の AI チューターから瞬時にサポートを受け、ウェブまたはアプリで続きから学習できます。
- コース
- 122
- レッスン
- 409
よくある質問
「ユースケースとリポジトリパターン」レッスンは無料ですか?
はい。「ユースケースとリポジトリパターン」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Swift Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Swift Academyコースには全4レッスンが含まれています。
「ユースケースとリポジトリパターン」で何を学びますか?
ユースケースをSwiftプロトコルとして定義し、リポジトリインターフェースを実装します。 ブラウザで直接実行するハンズオンコードでSwift Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Swift Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのSwift Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。
「ユースケースとリポジトリパターン」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このSwift Academyレッスンでコードを書いて実行できますか?
はい。すべてのSwift Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- レイヤー:ドメイン、データ、プレゼンテーション
- ユースケースとリポジトリパターン
- プロトコル抽象化による依存性逆転
- DIフレームワークを使わずにレイヤーを接続する