Describing how to use Swift protocols to refactor obj-c networking layer to Swift while improving project architecture and test coverage. CocoaHeads-Berlin Sep 16
3. Starting Point
#import <AFNetworking/AFNetworking.h>
@interface GHAPIClient : AFHTTPSessionManager
+ (instancetype)sharedClient;
-(void)fetchGitHubUserWithName:(NSString *)name
completionHandler:(void(^)(id result, NSError *error))handler;
@end
• Client has too many responsibilities
4. Starting Point
#import <AFNetworking/AFNetworking.h>
@interface GHAPIClient : AFHTTPSessionManager
+ (instancetype)sharedClient;
-(void)fetchGitHubUserWithName:(NSString *)name
completionHandler:(void(^)(id result, NSError *error))handler;
@end
• Client has too many responsibilities
• Client is tightly coupled to the network library
5. Starting Point
#import <AFNetworking/AFNetworking.h>
@interface GHAPIClient : AFHTTPSessionManager
+ (instancetype)sharedClient;
-(void)fetchGitHubUserWithName:(NSString *)name
completionHandler:(void(^)(id result, NSError *error))handler;
@end
• Client has too many responsibilities
• Client is tightly coupled to the network library
• Client is hard to test
6. Starting Point
#import <AFNetworking/AFNetworking.h>
@interface GHAPIClient : AFHTTPSessionManager
+ (instancetype)sharedClient;
-(void)fetchGitHubUserWithName:(NSString *)name
completionHandler:(void(^)(id result, NSError *error))handler;
@end
• Client has too many responsibilities
• Client is tightly coupled to the network library
• Client is hard to test
• Implementation details is not hidden
23. More Protocols
protocol Resource {
var path: String { get }
var method: HTTPMethod { get }
var parameters: [String: Any]? { get }
}
24. More Protocols
protocol Response {}
protocol Resource {
var path: String { get }
var method: HTTPMethod { get }
var parameters: [String: Any]? { get }
associatedtype ResponseType: Response
}
25. More Protocols
protocol Response {}
protocol Resource {
var path: String { get }
var method: HTTPMethod { get }
var parameters: [String: Any]? { get }
associatedtype ResponseType: Response
func parse(response: Data) -> (ResponseType?, Error?)
}
26. Define Endpoints
struct GitHubUserEndpoint: Resource {
private let name: String
init(loginName: String) {
name = loginName
}
var path: String { return "users/(name)" }
var method: HTTPMethod { return .GET }
var parameters: [String : Any]? { return nil }
func parse(response: Data) -> ( GitHubUser?, Error?) {
// Parse JSON -> data model object
}
}
struct GitHubUser: Response {
// Define data model
}
39. Summary
• Client has too many responsibilities
• Client is tightly coupled to the network library
40. Summary
• Client has too many responsibilities
• Client is tightly coupled to the network library
41. Summary
• Client has too many responsibilities
• Client is tightly coupled to the network library
• Client is hard to test
42. Summary
• Client has too many responsibilities
• Client is tightly coupled to the network library
• Client is hard to test
43. Summary
• Client has too many responsibilities
• Client is tightly coupled to the network library
• Client is hard to test
• Implementation details is not hidden
44. Summary
• Client has too many responsibilities
• Client is tightly coupled to the network library
• Client is hard to test
• Implementation details is not hidden
45. Summary
• Client has too many responsibilities
• Client is tightly coupled to the network library
• Client is hard to test
• Implementation details is not hidden
• Client still has too many responsibilities
46. Summary
• Client has too many responsibilities
• Client is tightly coupled to the network library
• Client is hard to test
• Implementation details is not hidden
• Client still has too many responsibilities
47. Summary
• Client has too many responsibilities
• Client is tightly coupled to the network library
• Client is hard to test
• Implementation details is not hidden
• Client still has too many responsibilities
• Client lacks general handlers
48. Summary
• Client has too many responsibilities
• Client is tightly coupled to the network library
• Client is hard to test
• Implementation details is not hidden
• Client still has too many responsibilities
• Client lacks general handlers