AladinWay/NetworkingExample

is It possible to refactor code little bit ?

saroar opened this issue · 7 comments

can we add some func for each request
now you have this

        return performRequest(route: APIRouter.login(email: email, password: password))
    }

    static func userArticles(userID: Int) -> Future<[Article]> {
        let jsonDecoder = JSONDecoder()
        jsonDecoder.dateDecodingStrategy = .formatted(.articleDateFormatter)
        return performRequest(route: APIRouter.articles(userId: userID), decoder: jsonDecoder)
    }

    static func getArticle(articleID: Int) -> Future<Article> {
        let jsonDecoder = JSONDecoder()
        jsonDecoder.dateDecodingStrategy = .formatted(.articleDateFormatter)
        return performRequest(route: APIRouter.article(id: articleID), decoder: jsonDecoder)
    }

so each model we have to create this typ of func but if you can create something like this with Generic

func get<T>{...}
func post<T>{...}
func put<T>{...}
func delete<T>{...}
func performRequest {...}

here some example code
https://gist.github.com/saroar/fc5fbd0c2ac4901904ab01ad3ac20048

i am trying to do something like this

    static func get<T>(ID: String, route: APIRouter) -> Future<T> {
        let jsonDecoder = JSONDecoder()
//        jsonDecoder.dateDecodingStrategy = .formatted(.articleDateFormatter)
        return performRequest(route: route, decoder: jsonDecoder)
    }
``` but getting error
`Cannot convert return expression of type 'Future<_>' to return type 'Future<T>'`

To make the code compile you need to add the Decodable constraint to T like that:

static func get<T:Decodable>(ID: String, route: APIRouter) -> Future<T> {
    return performRequest(route: route, decoder: JSONDecoder())
}

so is it a good idea? @AladinWay need your advice thanks and what you think?

@saroar It depends on your use case, there is always a room for improvement. But I think that the networking layer approach of the tutorial already encapsulate the method of the request in the router so I don't see the benefits of having separate methods to perform the request. This does not mean that it's not a good idea, but for my uses cases I didn't need to have another layer of abstraction.

so is it good practice for creating func like below for each model?

    static func login(email: String, password: String) -> Future<User> {
        return performRequest(route: APIRouter.login(email: email, password: password))
    }

    static func userArticles(userID: Int) -> Future<[Article]> {
        let jsonDecoder = JSONDecoder()
        jsonDecoder.dateDecodingStrategy = .formatted(.articleDateFormatter)
        return performRequest(route: APIRouter.articles(userId: userID), decoder: jsonDecoder)
    }

    static func getArticle(articleID: Int) -> Future<Article> {
        let jsonDecoder = JSONDecoder()
        jsonDecoder.dateDecodingStrategy = .formatted(.articleDateFormatter)
        return performRequest(route: APIRouter.article(id: articleID), decoder: jsonDecoder)
    }

where we can use this for anykind of model

func post<T>{...}
func put<T>{...}
func delete<T>{...}``` without duplication or create any new func 

i think i cant use like this

static func post<D:Decodable>(route: APIRouter) -> Future<D> { 
  return performRequest(route: route)
 }
func createHevent() {
        APIClient.post(route: APIRouter.person(
            id: nil, firstName: "babal", lastName: "balba", phoneNumbers: nil)).execute(onSuccess: { response in
                print("respoonse", response)
            }) { error in
                print("error", error)
        }
    }

error is getting this error Extra argument 'onSuccess' in call`

Looks like that execute function doesn’t want your onSuccess argument. Check the method definition for execute

@saroar I think it's easier to fork this repository and submit a pull request with your suggested changes then I can review your code :)