Exploring Protocol Dependencies (in conjunction with @Dependency) #1723
Replies: 1 comment 4 replies
-
While this seems to work at first blush, we have found it to be unwieldy in practice, and is one of the reasons we recommend the structified approach to dependencies. The problem comes up when you try to provide an implementation of public struct JwtMock: JwtClient {
public init() {}
public func decode<T>(_ token: String) async throws -> Result<T, ApiClient.Failure> where T : Decodable, T : Encodable {
???
}
} How are you supposed to return something from this when you know nothing about public func decode<T>(_ token: String) async throws -> Result<T, ApiClient.Failure> where T : Decodable, T : Encodable {
if T.self == Int.self {
return 42 as! T
} else {
return try await Task.never()
}
} But that seems really strange. You can still model this dependency as a struct even if you can't use a generic in a property. You start with a field for the struct JwtClient {
let _decode: (_ token: String) async throws -> Result<Data, Error>
func decode<T: Encodable>(token: String) -> Result<T, Error> {
// ...
}
} Then it is easy to cook up mock clients, and it comes with a bunch more benefits since it's a struct. We discussed this at length in our "API clients for free" episode, and this is the style we use for the URL routing library we open sourced, which is used by isowords. Now, you more than free to pursue the protocol style of this dependency if you prefer it. We understand struct dependencies aren't for everyone. But, even if you do use a protocol, you can still use it with the |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
In creating a dependency with a generic result type I've had to opt for using a protocol to declare its interface.
Test
andNoop
implementations can follow as suchYou can then even extend the protocol to include a
typealias
for these.Such that when you must provide a concrete type you can use
.Noop()
or.Test()
I've found dependency injection via the feature works fine but does add an extra explicit requirement.
I thought I would share this methodology on the forums if anyone needs the example.
This alternative route is needed because you cannot have generic properties on structs. Does anyone know a language that allows this? Wondering if there is a technical reason for such. It would seem to be logical for a definition to exist that looks like:
Note, this would not require a generic in the type definition of
JwtClient
.Beta Was this translation helpful? Give feedback.
All reactions