Esistono numerosi articoli / blog che spiegano il Principio di inversione delle dipendenze (DIP) usando Swift; per citarne alcuni (i migliori risultati di Google):
- GitHub / ochococo / OOD-Principles-In-Swift - Il principio di inversione delle dipendenze ,
- clean-swift.com / Dependency Inversion - A Little Swifty Architecture
Ora, Swift è ampiamente descritto (anche da Apple) come un linguaggio di programmazione orientato al protocollo, piuttosto che un linguaggio OOP; in modo così naturale questi articoli realizzano le astrazioni in DIP utilizzando protocolli anziché ereditarietà, tuttavia protocolli specificamente eterogenei per consentire al livello della politica di utilizzare il polimorfismo per richiamare livelli inferiori senza dover conoscere dettagli di implementazione. Per esempio:.
// Example A
protocol Service {
func work()
}
final class Policy {
// Use heterogeneous protocol polymorphically.
private let service: Service
init(service: Service) { self.service = service }
func doWork() { service.work() }
}
final class SpecificService: Service {
func work() { /* ... */ print("Specific work ...") }
}
let policy = Policy(service: SpecificService())
// Resolves to doWork() of SpecificService at runtime
policy.doWork() // Specific work ...
Mi rendo conto che il polimorfismo è uno dei concetti chiave in DIP (a meno che non mi sbagli), ma da una prospettiva di implementazione di Swift preferirei vedere il DIP applicato usando generici vincolati al protocollo piuttosto che il polimorfismo di runtime. Per esempio:.
// Example B
protocol Service {
func work()
}
final class Policy<PolicyService: Service> {
private let service: PolicyService
init(service: PolicyService) { self.service = service }
func doWork() { service.work() }
}
final class SpecificService: Service {
func work() { /* ... */ print("Specific work ...") }
}
let policy = Policy(service: SpecificService())
// policy.service specialized as SpecificService instance at compile time
policy.doWork() // Specific work ...
Non ho visto nessuno usare i generici nel contesto di DIP e Swift, quindi sono probabilmente quello al buio qui, quindi questa domanda.
Come principio design , credo che B sopra abbia lo stesso obiettivo di A , w.r.t. TUFFO; e quando applicato in un linguaggio di programmazione orientato al protocollo tipicamente statico che generalmente preferisce la composizione sull'ereditarietà, in particolare (afaik) protocolli e generici su protocolli e polimorfismo, preferirei usare B . Questo è naturalmente sotto il vincolo che utilizziamo sempre un soloPolicy
specializzato alla volta e ci ricolleghiamo al DIP per semplificare le modifiche nei dettagli di basso livello mediante disaccoppiamento / inversione di dipendenza.
Domanda: Sarebbe opportuno che l'Esempio B sia considerato un'applicazione valida di DIP, anche se un% specializzatoPolicy
"sa" del concreto Service
in fase di compilazione (a causa di generici, ancora disaccoppiati da astrazioni applicate come vincoli al segnaposto generico)?