Perché usare la dependency injection
Separa la costruzione dall’uso per facilitare i test.
Perché usare la dependency injection è una lezione Swift Academy gratuita su CoddyKit. Questa è la lezione 1 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Swift Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Swift Academy include 4 lezioni in totale.
Perché usare l'iniezione delle dipendenze
L'iniezione delle dipendenze (DI) consiste nel fornire a un oggetto ciò di cui ha bisogno dall'esterno, invece di consentirgli di creare autonomamente queste dipendenze. In questo modo i componenti sono disaccoppiati e più facili da testare.
Il problema: accoppiamento forte
Quando un tipo costruisce autonomamente i propri collaboratori, rimane vincolato a quelle classi concrete e non può essere riconfigurato né testato in isolamento.
class Logger {
func log(_ m: String) { print("LOG: \(m)") }
}
class Service {
let logger = Logger() // hard-coded dependency
func run() { logger.log("running") }
}
Service().run()L'accoppiamento ostacola i test
Poiché Service crea sempre un Logger reale, un test non può acquisire o simulare l'output del log. La dipendenza è invisibile dall'esterno.
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()L'idea: iniettare la dipendenza
Passate invece la dipendenza dall'esterno. È il chiamante a decidere quale implementazione fornire, quindi Service non deve più occuparsene.
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()Vantaggi del disaccoppiamento
Con l'iniezione, lo stesso Service funziona con logger diversi, in produzione o nei test, senza modificarne il codice.
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)Responsabilità singola
La DI supporta il principio della responsabilità singola: un tipo si concentra sul proprio compito e delega le altre responsabilità ai collaboratori iniettati.
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")Flessibilità
È possibile ricombinare gli oggetti in modi nuovi. Il collegamento delle dipendenze avviene ai margini dell'app, mantenendo flessibile il nucleo.
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()Dipendenze esplicite
Un inizializzatore che elenca le proprie dipendenze documenta esattamente ciò di cui il tipo ha bisogno. Le dipendenze nascoste e create autonomamente celano questo contratto.
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())Composizione anziché costruzione
La DI privilegia la composizione degli oggetti dall'esterno. Una piccola radice di composizione assembla il grafo; il resto del codice riceve semplicemente ciò di cui ha bisogno.
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()Non solo per le app grandi
Anche i programmi più piccoli ne traggono vantaggio: iniettare una dipendenza rende il comportamento sostituibile e le intenzioni chiare, senza framework aggiuntivi.
struct Clock { func now() -> Int { 12 } }
struct Greeter {
let clock: Clock
func greet() { print(clock.now() < 12 ? "Morning" : "Afternoon") }
}
Greeter(clock: Clock()).greet()Non serve alcun framework
La DI in Swift non richiede librerie. Sono sufficienti semplici inizializzatori e protocolli. Le prossime lezioni illustreranno l'iniezione tramite costruttore, i protocolli e i mock.
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()Verifica rapida
Qual è l'idea fondamentale dell'iniezione delle dipendenze?
Riepilogo
L'iniezione delle dipendenze fornisce i collaboratori dall'esterno invece di crearli internamente, riducendo l'accoppiamento, rendendo chiare le dipendenze e consentendo i test. In Swift non richiede alcun framework. Prossimo argomento: la forma più comune, l'iniezione tramite costruttore.
Domande Frequenti
La lezione «Perché usare la dependency injection» è gratuita?
Sì — il testo completo di «Perché usare la dependency injection» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Swift Academy, passa a CoddyKit PRO. Il corso Swift Academy include 4 lezioni in totale.
Cosa imparerò in «Perché usare la dependency injection»?
Separa la costruzione dall’uso per facilitare i test. Eserciti Swift Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare Swift Academy?
Non è richiesta alcuna esperienza precedente. Swift Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 1 di 4.
Quanto tempo richiede la lezione «Perché usare la dependency injection»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione Swift Academy?
Sì. Ogni lezione Swift Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Perché usare la dependency injection
- Dependency injection tramite inizializzatore
- Astrazioni basate sui protocolli
- Mock delle dipendenze nei test