swiftui · note · architecture · environment
Environment Key Patterns for Features
Context
Environment keys are powerful, but feature code becomes hard to reason about when key naming and default behavior are inconsistent.
The snippet
private struct PaymentsClientKey: EnvironmentKey {
static let defaultValue = PaymentsClient.mock
}
extension EnvironmentValues {
var paymentsClient: PaymentsClient {
get { self[PaymentsClientKey.self] }
set { self[PaymentsClientKey.self] = newValue }
}
}
Why this works
This pattern keeps dependency intent visible and testable. A clearly named key reveals feature ownership, and a safe default allows previews and tests to run without hidden setup.
For feature teams, this reduces accidental global coupling. Instead of pulling random dependencies from ambient state, each feature exposes explicit environment entry points.
Use it when…
- a dependency is contextual across many nested views
- parameter threading would add noise without improving clarity
- you need clean override points in previews/tests
Avoid it when…
- the dependency is local and should be a constructor parameter
- defaults perform real production side effects
- key names are vague (
service,manager,client) and hide domain meaning
Takeaway: A good Environment key is a small DI contract with a clear name and a safe default.
Next steps
If you want to extend this into full architecture decisions, these are the best continuations: