0Pricing
Swift Academy · Lekcja

Wzorce Use Case i Repository

Definiowanie przypadków użycia jako protokołów Swift i implementowanie interfejsów repozytoriów.

Wzorce Use Case i Repository to bezpłatna lekcja Swift Academy na CoddyKit. To lekcja 2 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Swift Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Swift Academy zawiera 4 lekcji w sumie.

Czym jest przypadek użycia

Przypadek użycia (interaktor) enkapsuluje pojedyncze działanie biznesowe, koordynując encje domenowe i repozytoria.

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)
  }
}

Pojedyncza odpowiedzialność

Każdy przypadek użycia realizuje dokładnie jedno zadanie. Wiele odpowiedzialności oznacza potrzebę utworzenia wielu przypadków użycia.

// One use case per business action:
struct FetchUserUseCase { ... }
struct UpdateUserUseCase { ... }
struct DeleteUserUseCase { ... }

Przypadek użycia jako protokół

Należy zdefiniować protokół dla przypadku użycia, aby można było używać jego atrap w testach warstwy prezentacji.

protocol PlacingOrder {
  func execute(userId: Int) async throws -> Order
}
struct PlaceOrderUseCase: PlacingOrder { ... }

Czym jest repozytorium

Repozytorium abstrahuje źródło danych. Kod wywołujący korzysta z protokołu w Swift, a implementacja może używać sieci, Core Data lub pamięci operacyjnej.

protocol OrderRepository {
  func create(receipt: PaymentReceipt) async throws -> Order
  func list(userId: Int) async throws -> [Order]
  func cancel(orderId: Int) async throws
}

Implementacja repozytorium

Konkretne repozytorium tłumaczy wywołania domenowe na operacje sieciowe lub bazodanowe.

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 { ... }
}

Repozytorium w pamięci do testów

Należy udostępnić repozytorium działające w pamięci, aby przeprowadzać szybkie i deterministyczne testy bez operacji wejścia-wyjścia.

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 } }
}

Komponowanie przypadków użycia

Przypadki użycia mogą wywoływać inne przypadki użycia w celu współdzielenia podoperacji, dzięki czemu każdy z nich pozostaje skoncentrowany na swoim zadaniu.

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
  }
}

Repozytorium a usługa

Repozytorium: operacje CRUD na jednym typie encji. Usługa: koordynuje działania na wielu encjach lub wywołuje zewnętrzne API bez bezpośredniego przechowywania danych.

// 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 }

Buforowanie w repozytoriach

Repozytoria mogą w sposób przezroczysty buforować wyniki, bez ujawniania szczegółów implementacji przypadkowi użycia.

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) }
}

Testowalność

Ponieważ przypadki użycia zależą od repozytoriów zdefiniowanych za pomocą protokołów, można wstrzykiwać stuby, aby testować logikę biznesową w izolacji.

let repo = InMemoryOrderRepo()
let sut = PlaceOrderUseCase(orders: repo, ...)
let order = try await sut.execute(userId: 1)
XCTAssertEqual(repo.orders.count, 1)

Tłumaczenie błędów

Repozytoria powinny przed zwróceniem przekształcać błędy warstwy danych (sieciowe, bazodanowe) w błędy domenowe.

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
  }
}

Szybkie sprawdzenie

Jaka jest kluczowa różnica między repozytorium a usługą w Clean Architecture?

Podsumowanie lekcji

Przypadki użycia enkapsulują pojedyncze działania biznesowe i zależą od protokołów repozytoriów. Repozytoria abstrahują źródła danych za pomocą protokołu. Repozytoria działające w pamięci służą do szybkich testów. Repozytoria przekształcają błędy infrastruktury w błędy domenowe. Usługi koordynują operacje na wielu encjach.

Często zadawane pytania

Czy lekcja „Wzorce Use Case i Repository” jest bezpłatna?

Tak — pełny tekst „Wzorce Use Case i Repository” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Swift Academy, przejdź na CoddyKit PRO. Kurs Swift Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Wzorce Use Case i Repository”?

Definiowanie przypadków użycia jako protokołów Swift i implementowanie interfejsów repozytoriów. Ćwiczysz Swift Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Swift Academy?

Nie wymagamy żadnego doświadczenia. Swift Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 2 z 4.

Ile czasu zajmuje lekcja „Wzorce Use Case i Repository”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Swift Academy?

Tak. Każda lekcja Swift Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Warstwy: domena, dane i prezentacja
  2. Wzorce Use Case i Repository
  3. Odwrócenie zależności z abstrakcjami protokołów
  4. Łączenie warstw bez frameworka DI
← Powrót do Swift Academy