Swift Academy · Lektion

Varför dependency injection

Separera konstruktion från användning för bättre testbarhet.

Lektion 1 av 413 steg

Varför dependency injection är en gratis lektion i Swift Academy på CoddyKit. Detta är lektion 1 av 4. Du kan läsa vilka 3 lektioner som helst i den här lärvägen kostnadsfritt i sin helhet – därefter låser CoddyKit PRO upp alla lektioner, plus praktisk övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Den ingår i lärvägen för Swift Academy, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i Swift Academy innehåller totalt 4 lektioner.

Varför beroendeinjektion

Beroendeinjektion (DI) innebär att ett objekt får det det behöver utifrån, i stället för att skapa det själv. Det minskar kopplingen mellan komponenter och gör dem enklare att testa.

Problemet: hård koppling

När en typ skapar sina egna samarbetande objekt blir den bunden till de konkreta klasserna och kan inte konfigureras om eller testas isolerat.

class Logger {
    func log(_ m: String) { print("LOG: \(m)") }
}
class Service {
    let logger = Logger() // hard-coded dependency
    func run() { logger.log("running") }
}
Service().run()

Koppling försvårar testning

Eftersom Service alltid skapar en riktig Logger kan ett test inte fånga upp eller ersätta loggutdata. Beroendet är osynligt utifrån.

class Logger { func log(_ m: String) { print(m) } }
class Service {
    let logger = Logger()
    func run() { logger.log("hello") }
}
// No way to swap Logger here.
Service().run()

Idén: injicera det

Skicka i stället in beroendet. Den som anropar avgör vilken implementation som ska tillhandahållas, så Service behöver inte längre känna till den.

class Logger { func log(_ m: String) { print("LOG: \(m)") } }
class Service {
    let logger: Logger
    init(logger: Logger) { self.logger = logger }
    func run() { logger.log("running") }
}
Service(logger: Logger()).run()

Fördelar med minskad koppling

Med injektion fungerar samma Service med olika loggare, både i produktion och i tester, utan att koden behöver ändras.

class Logger { var lines: [String] = []
    func log(_ m: String) { lines.append(m) } }
class Service {
    let logger: Logger
    init(logger: Logger) { self.logger = logger }
    func run() { logger.log("event") }
}
let l = Logger()
Service(logger: l).run()
print(l.lines)

Enkelt ansvar

DI stödjer principen om ett enda ansvar: en typ fokuserar på sin uppgift och överlåter andra ansvarsområden till injicerade samarbetande objekt.

struct Mailer { func send(_ to: String) { print("Mail to \(to)") } }
struct SignupFlow {
    let mailer: Mailer
    func register(_ email: String) { mailer.send(email) }
}
SignupFlow(mailer: Mailer()).register("a@b.com")

Flexibilitet

Du kan kombinera objekt på nya sätt. Ihopkopplingen sker i appens ytterkanter, vilket håller kärnan flexibel.

struct Engine { let power: Int }
struct Car {
    let engine: Engine
    func describe() { print("Power: \(engine.power)") }
}
Car(engine: Engine(power: 200)).describe()
Car(engine: Engine(power: 90)).describe()

Tydliga beroenden

En initializer som listar sina beroenden dokumenterar exakt vad typen behöver. Dolda, självskapade beroenden döljer detta kontrakt.

struct Repo { func load() -> [Int] { [1, 2, 3] } }
struct Report {
    let repo: Repo // visible dependency
    func total() -> Int { repo.load().reduce(0, +) }
}
print(Report(repo: Repo()).total())

Komposition framför konstruktion

DI föredrar att objekt sätts samman utifrån. En liten composition root sätter ihop objektgrafen; resten av koden tar bara emot det den behöver.

struct DB { func count() -> Int { 42 } }
struct Stats { let db: DB; func show() { print(db.count()) } }
// Composition root:
let app = Stats(db: DB())
app.show()

Inte bara för stora appar

Även små program har nytta av detta: genom att injicera ett beroende kan beteendet bytas ut och avsikterna bli tydliga utan extra ramverk.

struct Clock { func now() -> Int { 12 } }
struct Greeter {
    let clock: Clock
    func greet() { print(clock.now() < 12 ? "Morning" : "Afternoon") }
}
Greeter(clock: Clock()).greet()

Inget ramverk behövs

DI i Swift kräver inget bibliotek. Vanliga initializers och protokoll räcker. I de kommande lektionerna visas konstruktorsinjektion, protokoll och mocking.

struct Adder { func add(_ a: Int, _ b: Int) -> Int { a + b } }
struct Calc {
    let adder: Adder
    func run() { print(adder.add(2, 3)) }
}
Calc(adder: Adder()).run()

Snabb kontroll

Vad är grundidén med beroendeinjektion?

Sammanfattning

Beroendeinjektion tillhandahåller samarbetande objekt utifrån i stället för att skapa dem internt. Det minskar kopplingen, tydliggör beroenden och möjliggör testning. I Swift behövs inget ramverk. Nästa avsnitt handlar om den vanligaste formen: konstruktorsinjektion.

Gratis att börja

Lär dig Swift med en AI-lärare – gratis

Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.

Kurser
122
Lektioner
409

Vanliga frågor

Är lektionen ”Varför dependency injection” gratis?

Ja – du kan läsa vilka 3 lektioner som helst i lärvägen Swift Academy, inklusive ”Varför dependency injection”, kostnadsfritt i sin helhet här på webben. Därefter låser CoddyKit PRO upp alla lektioner, plus interaktiv övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Kursen i Swift Academy innehåller totalt 4 lektioner.

Vad lär jag mig i ”Varför dependency injection”?

Separera konstruktion från användning för bättre testbarhet. Ni övar på Swift Academy med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.

Behöver jag någon erfarenhet för att börja lära mig Swift Academy?

Du behöver inga förkunskaper. Utbildningen i Swift Academy på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 1 av 4.

Hur lång tid tar lektionen ”Varför dependency injection”?

De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.

Kan jag skriva och köra kod i den här Swift Academy-lektionen?

Ja. Varje Swift Academy-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.

Alla lektioner i den här kursen

  1. Varför dependency injection
  2. Constructor injection
  3. Protokollbaserade abstraktioner
  4. Mocka beroenden i tester
← Tillbaka till Swift Academy