Integración de capas sin un framework de DI
Componga objetos en el punto de entrada de la app mediante el patrón Composition Root.
Integración de capas sin un framework de DI es una lección gratuita de Swift Academy en CoddyKit. Esta es la lección 4 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.
Composition Root
El Composition Root es el único lugar donde se crean y conectan todos los objetos. En una aplicación de SwiftUI, normalmente es @main.
@main
struct MyApp: App {
// All wiring happens here
private let container = AppContainer()
var body: some Scene {
WindowGroup { container.makeRootView() }
}
}Patrón AppContainer
Una estructura o clase AppContainer construye el grafo de objetos y oculta la complejidad de la configuración a la estructura App.
final class AppContainer {
let db = SQLiteDatabase()
lazy var userRepo: UserRepository = RemoteUserRepository(db: db)
lazy var fetchUser = FetchUserUseCase(repo: userRepo)
lazy var profileVM = ProfileViewModel(useCase: fetchUser)
func makeRootView() -> some View { ProfileView(viewModel: profileVM) }
}Propiedades lazy para controlar el orden
Use propiedades lazy para asegurarse de que las dependencias se construyan en el orden correcto sin tener que establecerlo manualmente.
final class Container {
lazy var network: NetworkClient = URLSessionClient()
lazy var api: APIService = APIService(client: network) // created after network
lazy var repo: ItemRepository = RemoteItemRepository(api: api)
}Métodos de fábrica
Añada métodos de fábrica al contenedor para crear objetos del nivel de vista con dependencias específicas de cada pantalla.
extension AppContainer {
func makeOrderFlow() -> OrderFlowView {
let repo = RemoteOrderRepository(api: api)
let useCase = PlaceOrderUseCase(repo: repo)
let vm = OrderViewModel(useCase: useCase)
return OrderFlowView(viewModel: vm)
}
}Valores de entorno para la inyección
En SwiftUI, use EnvironmentKeys personalizados para inyectar dependencias en cualquier nivel del árbol de vistas sin tener que pasarlas por todas las vistas intermedias.
private struct FetchUserKey: EnvironmentKey {
static let defaultValue: FetchingUser = FetchUserUseCase(repo: NullUserRepo())
}
extension EnvironmentValues {
var fetchUser: FetchingUser {
get { self[FetchUserKey.self] } set { self[FetchUserKey.self] = newValue }
}
}Uso de la clave de entorno
Inyecte mediante .environment(\.fetchUser, container.fetchUser) y lea el valor con @Environment(\.fetchUser) en las vistas.
ContentView()
.environment(\.fetchUser, container.fetchUser)
// In a deep view:
@Environment(\.fetchUser) private var fetchUserContenedores con ámbito
Cree contenedores secundarios para los ámbitos de las funcionalidades, de modo que hereden las dependencias compartidas y sean propietarios de las específicas de cada funcionalidad.
final class CheckoutContainer {
let cart: CartRepository
let payment: PaymentService
lazy var placeOrder = PlaceOrderUseCase(cart: cart, payment: payment)
init(parent: AppContainer) {
cart = parent.cartRepo
payment = parent.paymentService
}
}Pruebas del Composition Root
Pruebe los métodos de fábrica del contenedor verificando que los objetos devueltos tengan el tipo y la configuración correctos.
func testContainerBuildsProfileView() {
let container = AppContainer(db: InMemoryDatabase())
let view = container.makeRootView()
XCTAssertTrue(type(of: view) == ProfileView.self)
}Cómo evitar dependencias circulares
Si A depende de B y B depende de A, introduzca un mediador o reorganice las responsabilidades para romper el ciclo.
// Circular:
// UserService → NotificationService → UserService
// Fix: UserService → NotificationInput (protocol) ← NotificationServiceCuándo recurrir a un framework de DI
La configuración manual funciona bien en aplicaciones de tamaño mediano. Considere frameworks como Needle o Swinject únicamente cuando el contenedor sea demasiado grande para mantenerlo.
// Manual: fine for <20 top-level dependencies
// Framework: helps with large teams, 50+ services, code-generation for factoriesEjemplo de repaso
Ejemplo completo de configuración en una aplicación pequeña: el contenedor construye todas las dependencias y una fábrica produce la vista raíz.
final class AppContainer {
private let db = CoreDataStack.shared
lazy var userRepo: UserRepository = LocalUserRepository(db: db)
lazy var fetchUser = FetchUserUseCase(repo: userRepo)
func makeContentView() -> ContentView {
ContentView(viewModel: ProfileViewModel(useCase: fetchUser))
}
}Comprobación rápida
¿Qué es el Composition Root en una aplicación de Swift?
Resumen de la lección
Configure la aplicación en un Composition Root (normalmente @main). Use un AppContainer con propiedades lazy para mantener el orden correcto de construcción. Añada métodos de fábrica para los grafos específicos de cada pantalla. Inyecte dependencias profundas mediante EnvironmentKeys personalizados. Rompa las dependencias circulares con protocolos mediadores.
Preguntas frecuentes
¿La lección «Integración de capas sin un framework de DI» es gratis?
Sí — el texto completo de «Integración de capas sin un framework de DI» 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 «Integración de capas sin un framework de DI»?
Componga objetos en el punto de entrada de la app mediante el patrón Composition Root. 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 4 de 4.
¿Cuánto tiempo toma la lección «Integración de capas sin un framework de DI»?
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