Odwrócenie zależności z abstrakcjami protokołów
Zależność od abstrakcji, a nie konkretów, z użyciem protokołów Swift jako granic.
Odwrócenie zależności z abstrakcjami protokołów to bezpłatna lekcja Swift Academy na CoddyKit. To lekcja 3 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.
Zasada odwrócenia zależności
Moduły wysokiego poziomu nie powinny zależeć od modułów niskiego poziomu. Oba rodzaje modułów powinny zależeć od abstrakcji (protokołów).
// WITHOUT DIP:
class OrderService { let db = SQLiteDatabase() } // depends on concrete
// WITH DIP:
class OrderService { let db: Database } // depends on abstractionDefiniowanie abstrakcji
Należy wyodrębnić protokół opisujący kontrakt wymagany przez moduł wysokiego poziomu.
protocol Database {
func save<T: Encodable>(_ value: T, key: String) throws
func load<T: Decodable>(key: String) throws -> T
}Konkretne implementacje
Należy dostarczyć wiele konkretnych implementacji za protokołem: produkcyjną, testową i przyszłe alternatywy.
class SQLiteDatabase: Database { ... }
class InMemoryDatabase: Database { ... }
class KeychainDatabase: Database { ... }Wstrzykiwanie przez konstruktor
Abstrakcję należy przekazywać przez inicjalizator — to najbardziej jawny i podatny na testowanie styl wstrzykiwania zależności.
class ProfileService {
private let db: Database
init(db: Database) { self.db = db }
}Dlaczego nie używać wszędzie singletonów
Globalne singletony ukrywają zależności, przez co kod staje się trudniejszy do testowania i zrozumienia.
// Hard to test:
class Service { func run() { MySingleton.shared.doWork() } }
// Easy to test:
class Service { let dep: MyProtocol; func run() { dep.doWork() } }Abstrakcje protokołów w Swift
Protokoły Swift mogą zawierać typy powiązane, implementacje domyślne i kompozycję, dzięki czemu idealnie nadają się do tworzenia rozbudowanych abstrakcji.
protocol Cacheable {
associatedtype Key: Hashable
associatedtype Value
func get(_ key: Key) -> Value?
func set(_ key: Key, value: Value)
}Poziom szczegółowości abstrakcji
Zasada segregacji interfejsów: należy preferować wąskie protokoły zamiast rozbudowanych, aby implementacje udostępniały tylko to, czego potrzebują wywołujący.
// 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 }DIP z Combine
Metody protokołu powinny zwracać AnyPublisher, aby ukryć typ bazowego publishera.
protocol UserStream {
func userUpdates() -> AnyPublisher<User, Never>
}DIP z async/await
Metody protokołu oznaczone jako async throws są w pełni zgodne ze strukturalną współbieżnością w Swift.
protocol Analytics {
func track(event: String) async
}
struct FirebaseAnalytics: Analytics {
func track(event: String) async { /* Firebase call */ }
}DIP na poziomie aplikacji
Konkretne implementacje należy konfigurować w punkcie wejścia aplikacji (Composition Root), aby wszystkie powiązania znajdowały się w jednym miejscu.
@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) }
}
}Testowanie z użyciem DIP
W testach należy zastępować rzeczywiste implementacje mockami lub stubami w miejscu wstrzykiwania zależności.
let mockDB = InMemoryDatabase()
let service = ProfileService(db: mockDB)
// Exercise service
XCTAssertEqual(try mockDB.load(key: "profile"), expectedProfile)Szybkie sprawdzenie
Co zasada odwrócenia zależności mówi o modułach wysokiego poziomu?
Podsumowanie lekcji
DIP: moduły wysokiego poziomu zależą od abstrakcji protokołów, a typy konkretne je implementują. Należy wyodrębniać wąskie protokoły, wstrzykiwać zależności przez konstruktory i konfigurować wszystko w Composition Root. Umożliwia to wymianę implementacji na potrzeby testów, włączania funkcji za pomocą feature flag oraz przyszłych wymagań.
Często zadawane pytania
Czy lekcja „Odwrócenie zależności z abstrakcjami protokołów” jest bezpłatna?
Tak — pełny tekst „Odwrócenie zależności z abstrakcjami protokołów” 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 „Odwrócenie zależności z abstrakcjami protokołów”?
Zależność od abstrakcji, a nie konkretów, z użyciem protokołów Swift jako granic. Ć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 3 z 4.
Ile czasu zajmuje lekcja „Odwrócenie zależności z abstrakcjami protokołów”?
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