-
Notifications
You must be signed in to change notification settings - Fork 3
Description
One of the design goals for Netable was to reduce the need for "wide" enums or function interfaces to specify sets of operations, stuff like:
enum Endpoint {
case getFoo
case setFoo(Foo)
case getBar
case setBar(Bar)
//... dozens of other endpoints
}
class Api {
func getFoo(completion: (Foo?) -> Void) {
request(Endpoint.getFoo) {
//...
}
}
func setFoo(_ foo: Foo, completion: (Bool) -> Void) {
//...
}
// ... dozens of other functions
}
Netable has been quite successful at reducing uses of the first, but much less successful at reducing uses of the second. Adding the finalization logic removed one important source of boilerplate in those sorts of API wrappers, but there's still enough stuff that you want to be done in a common way per request but that the request interface doesn't capture, that there is often need for those sort of wrappers. Some common ones we see a lot:
- We want some common global or semi-global data to be set on certain types of requests. "Every time we read the user put that in LoginManager.currentUser".
- We want local common error handling of some type. "404 errors on this request get transformed into another error type because that has some special meaning here"
- We want some sort of global common error handling. "All of these apis should generate a warning error toast when network errors happen on them".
Assuming we still think that boilerplate is worth reducing further (which is a question we should ask first, rather than just charging ahead with this, in particular this question does interact with some of our thinking on how repositories and services should be structured in the overall architecture, which has evolved a fair bit since Netable started), we should do a bit more systematic of an audit of what the full set of things that still require that kind of point of functionality that can't fit into the request objects, and look into ways to specify those bits of behaviour as part of the request.