ishkawa / APIKit

Type-safe networking abstraction layer that associates request type with response type.
MIT License
2k stars 205 forks source link

UnexpectedURLRequest seems orphaned in APIKit 2 #177

Closed takasek closed 8 years ago

takasek commented 8 years ago

See the search result: https://github.com/ishkawa/APIKit/search?utf8=%E2%9C%93&q=UnexpectedURLRequest

ishkawa commented 8 years ago

Oh, yes. I leave this to indicate common errors. This may be useful when user don't define their custom errors. Users can also throw their custom error, so they can choose type of errors to throw.

takasek commented 8 years ago

I got your intention. So, which is better way when user throws the error?

1) uses defined ErrorType as possible. 2) defines their own ErrorType as they like.

If 1), I prefer associated errors of SessionTaskError to belong to each NSError, RequestError and ResponseError type. If 2), pre-defined but unused UnexpectedURLRequest seems confusing. And RequestError and ResponseError suit rather Struct type than Enum type.

And in any case, what do you think of specify protocols for associated ErrorTypes in SessionTaskError? they looks too vague to use.

ishkawa commented 8 years ago

I think the second one is better.

Generally, several kind of errors might happen while getting web API response. It is impossible to enumerate possible errors exhaustively because there're custom errors, and that is the reason why associated values of SessionTaskType is untyped.

From the viewpoint of call-site, we can get where the error occurred by the case of SessionTaskError, but can't get the type of the associated error. We have to cast the error to known error type to get what the error is. Here's an example:

let request = GitHubAPI.SearchRepositoriesRequest(query: "APIKit")

Session.sendRequest(request) { result in
    switch result {
    case .Success(let response):
        print("response: ", response)

    case .Failure(let error):
        switch error {
        case .ResponseError(let gitHubError as GitHubError):
            print("GitHub API Error: \(gitHubError.message)")

        default:
            print("Unknown Error: \(error)")
        }
    }
}

This is exactly the same way to do-try-catch, which is untyped error handling model. We can specialize error handling for known error types, but handling unknown errors is unavoidable. In other words, all specializations for known errors are optional, but handling unknown errors is required. Thus, specializations for predefine errors such as RequestError and ResponseError are also optional.