0Pricing
Swift Academy · Lekcja

Łączenie warstw bez frameworka DI

Komponowanie obiektów w punkcie wejścia aplikacji za pomocą wzorca Composition Root.

Łączenie warstw bez frameworka DI to bezpłatna lekcja Swift Academy na CoddyKit. To lekcja 4 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.

Composition Root

Composition Root to jedno miejsce, w którym wszystkie obiekty są tworzone i łączone. W aplikacji SwiftUI jest to zazwyczaj @main.

@main
struct MyApp: App {
  // All wiring happens here
  private let container = AppContainer()
  var body: some Scene {
    WindowGroup { container.makeRootView() }
  }
}

Wzorzec AppContainer

Struktura lub klasa AppContainer tworzy graf obiektów, ukrywając złożoność konfiguracji przed strukturą App.

final class AppContainer {
  let db = SQLiteDatabase()
  lazy var userRepo: UserRepository = RemoteUserRepository(db: db)
  lazy var fetchUser = FetchUserUseCase(repo: userRepo)
  lazy var profileVM = ProfileViewModel(useCase: fetchUser)
  func makeRootView() -> some View { ProfileView(viewModel: profileVM) }
}

Właściwości lazy zapewniające właściwą kolejność

Należy używać właściwości lazy, aby zapewnić tworzenie zależności we właściwej kolejności bez ręcznego ustalania tej kolejności.

final class Container {
  lazy var network: NetworkClient = URLSessionClient()
  lazy var api: APIService = APIService(client: network)  // created after network
  lazy var repo: ItemRepository = RemoteItemRepository(api: api)
}

Metody fabrykujące

Należy dodać do kontenera metody fabrykujące, aby tworzyć obiekty na poziomie widoku wraz z zależnościami właściwymi dla poszczególnych ekranów.

extension AppContainer {
  func makeOrderFlow() -> OrderFlowView {
    let repo = RemoteOrderRepository(api: api)
    let useCase = PlaceOrderUseCase(repo: repo)
    let vm = OrderViewModel(useCase: useCase)
    return OrderFlowView(viewModel: vm)
  }
}

Wartości środowiska do wstrzykiwania

W SwiftUI należy używać niestandardowych kluczy EnvironmentKey, aby wstrzykiwać zależności głęboko do drzewa widoków bez przekazywania ich przez każdy komponent.

private struct FetchUserKey: EnvironmentKey {
  static let defaultValue: FetchingUser = FetchUserUseCase(repo: NullUserRepo())
}
extension EnvironmentValues {
  var fetchUser: FetchingUser {
    get { self[FetchUserKey.self] } set { self[FetchUserKey.self] = newValue }
  }
}

Używanie klucza środowiska

Zależność należy wstrzykiwać za pomocą .environment(\.fetchUser, container.fetchUser) i odczytywać ją w widokach za pomocą @Environment(\.fetchUser).

ContentView()
  .environment(\.fetchUser, container.fetchUser)

// In a deep view:
@Environment(\.fetchUser) private var fetchUser

Kontenery o określonym zakresie

Należy tworzyć kontenery podrzędne dla zakresów funkcji. Dziedziczą one współdzielone zależności, ale zarządzają zależnościami właściwymi dla danej funkcji.

final class CheckoutContainer {
  let cart: CartRepository
  let payment: PaymentService
  lazy var placeOrder = PlaceOrderUseCase(cart: cart, payment: payment)
  init(parent: AppContainer) {
    cart = parent.cartRepo
    payment = parent.paymentService
  }
}

Testowanie Composition Root

Należy testować metody fabrykujące kontenera, sprawdzając, czy zwracane obiekty mają właściwy typ i konfigurację.

func testContainerBuildsProfileView() {
  let container = AppContainer(db: InMemoryDatabase())
  let view = container.makeRootView()
  XCTAssertTrue(type(of: view) == ProfileView.self)
}

Unikanie cyklicznych zależności

Jeśli A zależy od B, a B zależy od A, należy wprowadzić mediator lub zmienić podział odpowiedzialności, aby przerwać cykl.

// Circular:
// UserService → NotificationService → UserService
// Fix: UserService → NotificationInput (protocol) ← NotificationService

Kiedy sięgnąć po framework DI

Ręczne konfigurowanie zależności dobrze sprawdza się w aplikacjach średniej wielkości. Po frameworki (Needle, Swinject) należy sięgać dopiero wtedy, gdy utrzymanie kontenera stanie się zbyt trudne.

// Manual: fine for <20 top-level dependencies
// Framework: helps with large teams, 50+ services, code-generation for factories

Przykład podsumowujący

Pełny przykład konfiguracji w małej aplikacji: kontener tworzy wszystkie zależności, a metoda fabrykująca tworzy widok główny.

final class AppContainer {
  private let db = CoreDataStack.shared
  lazy var userRepo: UserRepository = LocalUserRepository(db: db)
  lazy var fetchUser = FetchUserUseCase(repo: userRepo)
  func makeContentView() -> ContentView {
    ContentView(viewModel: ProfileViewModel(useCase: fetchUser))
  }
}

Szybkie sprawdzenie

Czym jest Composition Root w aplikacji Swift?

Podsumowanie lekcji

Aplikację należy konfigurować w Composition Root, zwykle w @main. Należy używać AppContainer z właściwościami lazy, aby zachować właściwą kolejność tworzenia. Dla grafów zależnych od poszczególnych ekranów należy dodawać metody fabrykujące. Głębokie zależności należy wstrzykiwać za pomocą niestandardowych kluczy EnvironmentKey. Cykliczne zależności należy przerywać za pomocą protokołów mediatorów.

Często zadawane pytania

Czy lekcja „Łączenie warstw bez frameworka DI” jest bezpłatna?

Tak — pełny tekst „Łączenie warstw bez frameworka DI” 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 „Łączenie warstw bez frameworka DI”?

Komponowanie obiektów w punkcie wejścia aplikacji za pomocą wzorca Composition Root. Ć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 4 z 4.

Ile czasu zajmuje lekcja „Łączenie warstw bez frameworka DI”?

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