Как выполнить рефакторинг преобразования типизированных результатов в сплошную структуру в объединении

#ios #swift #generics #refactoring #combine

#iOS #быстрый #дженерики #рефакторинг #объединять

Вопрос:

У меня есть эта уродливая конструкция возврата универсального типа в виде твердой модели, у кого-нибудь есть идеи по рефакторингу, чтобы быть более декларативным?

 extension NetworkingService {    func login(email: String, password: String) -gt; AnyPublisherlt;UserModel, APIErrorgt; {  func convertToModel() -gt; AnyPublisherlt;ResponseObjectlt;UserResponsegt;, APIErrorgt; {  return request(with: AuthRequests.login(email: email, password: password)).eraseToAnyPublisher()  }  return convertToModel().map { UserModel(with: $0.data!) }.eraseToAnyPublisher()  }    func requestlt;Tgt;(with endpoint: Endpoint) -gt; AnyPublisherlt;T, APIErrorgt; where T : Decodable {  //... returning any publisher with Decodable  } }  

Ответ №1:

Ваша requestlt;Tgt;(with:) функция использует только T в возврате. Хотя это выполнимо, это означает, что вызывающий код должен вызывать то, что T есть, что делает ваш вызывающий код «уродливым».

Из того, что вы опубликовали, у меня сложилось впечатление, что единственное Endpoint , что делает ваш тип, — это создает URL-запрос. Если бы он также определял форму ожидаемых возвращаемых данных, то вся конструкция была бы чище.

Я предлагаю сделать так, чтобы ваш Endpoint тип выглядел вот так:

 public struct Endpointlt;Responsegt; {  public let request: URLRequest  public let response: (Data) throws -gt; Response   public init(request: URLRequest, response: @escaping (Data) throws -gt; Response) {  self.request = request  self.response = response  } }  

Затем, с подходящими обновлениями в другом месте, вы могли бы сделать что-то вроде этого:

 extension NetworkingService {   func login(email: String, password: String) -gt; AnyPublisherlt;UserModel, APIErrorgt; {  request(with: AuthRequests.login(email: email, password: password))  .map { $0.response.model }  .eraseToAnyPublisher()  }   func requestlt;Tgt;(with endpoint: Endpointlt;Tgt;) -gt; AnyPublisherlt;T, APIErrorgt; where T: Decodable {  //... returning any publisher with Decodable  } }