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)
}
}
Explanation:
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.