Inversión de dependencias con abstracciones de protocolos
Dependa de abstracciones, no de concreciones, utilizando protocolos de Swift como límites.
Inversión de dependencias con abstracciones de protocolos es una lección gratuita de Swift Academy en CoddyKit. Esta es la lección 3 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Swift Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Swift Academy incluye 4 lecciones en total.
Principio de inversión de dependencias
Los módulos de alto nivel no deben depender de módulos de bajo nivel. Ambos deben depender de abstracciones (protocolos).
// WITHOUT DIP:
class OrderService { let db = SQLiteDatabase() } // depends on concrete
// WITH DIP:
class OrderService { let db: Database } // depends on abstractionDefinición de la abstracción
Extraiga un protocolo que represente el contrato que necesita su módulo de alto nivel.
protocol Database {
func save<T: Encodable>(_ value: T, key: String) throws
func load<T: Decodable>(key: String) throws -> T
}Implementaciones concretas
Proporcione varias implementaciones concretas detrás del protocolo: para producción, para pruebas y para futuras alternativas.
class SQLiteDatabase: Database { ... }
class InMemoryDatabase: Database { ... }
class KeychainDatabase: Database { ... }Inyección mediante el inicializador
Pase la abstracción mediante el inicializador: es el estilo de inyección más explícito y fácil de probar.
class ProfileService {
private let db: Database
init(db: Database) { self.db = db }
}¿Por qué no usar singletons para todo?
Los singletons globales ocultan las dependencias, lo que dificulta probar y comprender el código.
// Hard to test:
class Service { func run() { MySingleton.shared.doWork() } }
// Easy to test:
class Service { let dep: MyProtocol; func run() { dep.doWork() } }Abstracciones mediante protocolos en Swift
Los protocolos de Swift pueden incluir tipos asociados, implementaciones predeterminadas y composición, por lo que son ideales para crear abstracciones completas.
protocol Cacheable {
associatedtype Key: Hashable
associatedtype Value
func get(_ key: Key) -> Value?
func set(_ key: Key, value: Value)
}Granularidad de las abstracciones
Segregación de interfaces: prefiera protocolos reducidos en lugar de protocolos demasiado amplios, para que las implementaciones solo proporcionen lo que necesitan los consumidores.
// 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 con Combine
Devuelva AnyPublisher desde los métodos del protocolo para mantener oculto el tipo de publisher subyacente.
protocol UserStream {
func userUpdates() -> AnyPublisher<User, Never>
}DIP con async/await
Los métodos del protocolo marcados como async throws son totalmente compatibles con la concurrencia estructurada de Swift.
protocol Analytics {
func track(event: String) async
}
struct FirebaseAnalytics: Analytics {
func track(event: String) async { /* Firebase call */ }
}DIP en el nivel de la aplicación
Configure las implementaciones concretas en el punto de entrada de la aplicación (Composition Root) y mantenga todas las asociaciones en un solo lugar.
@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) }
}
}Pruebas con DIP
En las pruebas, sustituya las implementaciones reales por mocks o stubs en el punto de inyección.
let mockDB = InMemoryDatabase()
let service = ProfileService(db: mockDB)
// Exercise service
XCTAssertEqual(try mockDB.load(key: "profile"), expectedProfile)Comprobación rápida
¿Qué establece el principio de inversión de dependencias sobre los módulos de alto nivel?
Resumen de la lección
DIP: los módulos de alto nivel dependen de abstracciones definidas mediante protocolos; los tipos concretos las implementan. Extraiga protocolos reducidos, inyecte las dependencias mediante inicializadores y configure todo en el Composition Root. Esto permite intercambiar implementaciones para realizar pruebas, activar funcionalidades mediante indicadores y responder a requisitos futuros.
Preguntas frecuentes
¿La lección «Inversión de dependencias con abstracciones de protocolos» es gratis?
Sí — el texto completo de «Inversión de dependencias con abstracciones de protocolos» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Swift Academy, actualiza a CoddyKit PRO. El curso de Swift Academy incluye 4 lecciones en total.
¿Qué aprenderé en «Inversión de dependencias con abstracciones de protocolos»?
Dependa de abstracciones, no de concreciones, utilizando protocolos de Swift como límites. Practicas Swift Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar Swift Academy?
No se requiere experiencia previa. Swift Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 3 de 4.
¿Cuánto tiempo toma la lección «Inversión de dependencias con abstracciones de protocolos»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de Swift Academy?
Sí. Cada lección de Swift Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- Capas: dominio, datos y presentación
- Patrones de casos de uso y repositorios
- Inversión de dependencias con abstracciones de protocolos
- Integración de capas sin un framework de DI