import NeedleFoundation
protocol FetchAndSaveDependency: Dependency {
var database: Database { get }
var httpClient: HttpClient { get }
}
class FetchAndSave: Component<FetchAndSaveDependency> {
func run(userId: Int) async throws {
let api: HttpClient = dependency.httpClient
let db: Database = dependency.database
let user = try await api.fetch(userId: userId)
try await db.save(user: user)
}
}
In Swift, we generally reach for DI frameworks to solve this. DI frameworks can resolve at either compile time or runtime based on the library, generally runtime-based DI has less boilerplate, with the obvious downside of pushing errors to runtime.
This method of dependency management does not compose with other effects at all though. We can't pull dependencies "out" of the same type that allows us to resolve things like async, errors, or nondeterminism. These all require separate syntax.