Replies: 0 comments 2 replies
-
Hi @Jeehut! Thanks for the discussion and feedback! I could definitely see some tweaking here. Maybe something like: let loginResponse = try await client.response(for: .login, as: LoginResponse.self).value To respond more directly to a few of your items:
I definitely agree that typed errors can be handy, but we're trying to follow Apple's lead here, which is to prefer throwing functions. Luckily I think you can extend
We looked to prior art here. In particular, I think
The client-level JSON decoder was actually added in this PR: We just need to cut a new version for it. As for |
Beta Was this translation helpful? Give feedback.
-
I just watched your latest episode and while I loved the whole idea of keeping your API client in sync with the server & how mocking is solved in
_URLRouting
, I do have an issue with the API semantics of therequest(_:as:decoder:)
method, see this screenshot:To me this feels wrong for the following reasons:
request(...)
returns a request object similar toURLRequest
or executes a request and returns some kind of response. This is a common issue with English words that can be a verb or a noun, as some APIs prefer describing the return type and others prefer describing the side effects (which is what you do here).async
APIs, Apple actually prefers describing the return type, see for example theURLSession.data(for:delegate)
API or the freshMusicCatalogSearchRequest.response()
API from MusicKit introduced during WWDC2021. So Apple platform developers might expect that this to return some kind ofRequest
object, likeNSManagedObject.fetchRequest()
.throwing
which is fine for those who prefer throwing APIs, but in my own Twitter survey I learned that (at least in my bubble) more developers preferResult
APIs because we don't have precise error typing in Swift yet unless we returnResult.failure
instead of throwing. The cool thing about returningResult
instead of throwing is also, that users get a throwing API for free because they can just callget()
on the Result.as
naming makes the function readrequest as
which is not that bad, but still lacks some clarity in my opinion. It could be easily mixed up with the formatting of the body, for example, so some might try writingrequest(..., as: .json)
. In my own networking library I named that parameterdecodeBodyTo
which could fit here, too.decoder
currently needs to be provided with every single request, but it is very common to reuse one decoder for all request of a specific server. So much so, that I think the library should provide adefaultDecoder
property on theURLRoutingClient
level in my opinion. This could still be overridden when needed on a per-call basis.So putting all these changes together, I suggest to change the semantics of the
request
method from:To this:
Where the error type could look something like this:
The error type is just a quick and dirty suggestion, we could provide a more sophisticated error type covering all common error reasons to provide users with a more helpful explicit error type, something like my own
ApiError
type but adjusted to this library.Would love to hear your thoughts!
Beta Was this translation helpful? Give feedback.
All reactions