Łą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 fetchUserKontenery 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) ← NotificationServiceKiedy 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 factoriesPrzykł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
- Warstwy: domena, dane i prezentacja
- Wzorce Use Case i Repository
- Odwrócenie zależności z abstrakcjami protokołów
- Łączenie warstw bez frameworka DI