Protocol Oriented Programing - POP (Tales Pinheiro)

49

Transcript of Protocol Oriented Programing - POP (Tales Pinheiro)

Page 1: Protocol Oriented Programing - POP (Tales Pinheiro)
Page 2: Protocol Oriented Programing - POP (Tales Pinheiro)

Protocol Oriented Programming

Colocando em prática

Page 3: Protocol Oriented Programing - POP (Tales Pinheiro)

Conteúdo

• Tales Pinheiro de Andrade

• @talesp, [email protected] • - Mestre em computação pelo IME-USP

• - Líder do Capítulo iOS na Concrete Solutions

• - Líder do Capítulo São Paulo do CocoaHeads Brasil • - Desenvolvedor C desde 2002

• - Objective-C desde 2007 (coisas básicas antes do iPhone!)

• - Swift desde 08/2015

• - iOS desde 2010

Page 4: Protocol Oriented Programing - POP (Tales Pinheiro)

O que é?

– Protocolos

– contratos, assinaturas

– Já existiam no Objective-C – Categorias – Protocolos – Extensões

Page 5: Protocol Oriented Programing - POP (Tales Pinheiro)

Classe

#import <Foundation/Foundation.h>

@interface Foo : NSObject

- (void)doSomething;

@end

#import "Foo.h"

@implementation Foo

- (void)doSomething { NSLog(@"doSomething"); }

@end

Page 6: Protocol Oriented Programing - POP (Tales Pinheiro)

Categoria

#import "Foo.h"

@interface Foo (Bar)

- (void)doSomethingElse;

@end

#import "Foo+Bar.h"

@implementation Foo (Bar)

- (void)doSomethingElse { NSLog(@"doSomethingElse"); }

@end

Page 7: Protocol Oriented Programing - POP (Tales Pinheiro)

Extensão

@interface Foo ()

- (void)privatelyDoAnotherThing;

@end

Page 8: Protocol Oriented Programing - POP (Tales Pinheiro)

Extensão@interface Foo ()

- (void)privatelyDoAnotherThing;

@end

@implementation Foo

- (void)doSomething { NSLog(@"doSomething"); }

- (void)privatelyDoAnotherThing { NSLog(@"privatelyDoAnotherThing"); }

@end

Page 9: Protocol Oriented Programing - POP (Tales Pinheiro)

Extensão

@protocol Baz <NSObject>

- (void)doAnotherThing;

@end

Page 10: Protocol Oriented Programing - POP (Tales Pinheiro)

Classe

#import <Foundation/Foundation.h> #import "Baz.h"

@interface Wibbly : NSObject <Baz>

@end

@implementation Wibbly

- (void)doAnotherThing { //empty }

@end

Page 11: Protocol Oriented Programing - POP (Tales Pinheiro)

E no Swift?

Page 12: Protocol Oriented Programing - POP (Tales Pinheiro)

“Novidades” do Swift 1.0 ~ 1.2

• Unifica as categories e extensions

• Remove separação de interface/implementação

• Não é necessário declarar a extensão

Page 13: Protocol Oriented Programing - POP (Tales Pinheiro)

“Novidades” do Swift 1.0 ~ 1.2

protocol Wheeled { var numberOfWheels: Int { get } }

class Car: Wheeled { let numberOfWheels = 4 }

class Motorcycle: Wheeled { let numberOfWheels = 2 }

Page 14: Protocol Oriented Programing - POP (Tales Pinheiro)

“Novidades” do Swift 1.0 ~ 1.2

protocol Wheeled { var numberOfWheels: Int { get } }

class Car: Wheeled { let numberOfWheels = 4 }

class Motorcycle: Wheeled { }

Page 15: Protocol Oriented Programing - POP (Tales Pinheiro)

“Novidades” do Swift 1.0 ~ 1.2

class Hello { }

extension Hello { static func world() { print("Hello, world") } }

Hello.world() //"Hello, world\n"

Page 16: Protocol Oriented Programing - POP (Tales Pinheiro)

E no Swift 2.0?

class Hello { }

extension Hello { static func world() { print("Hello, world") } }

Hello.world() //"Hello, world\n"

Page 17: Protocol Oriented Programing - POP (Tales Pinheiro)

E no Swift 2.0?

protocol Greeter { }

class Car: Greeter { }

class Motorcycle: Greeter { }

Page 18: Protocol Oriented Programing - POP (Tales Pinheiro)

Extendendo um protocolo Implementação padrão

extension Greeter { static func greeting() { print("Hello, \(String(describing: self))") } }

Page 19: Protocol Oriented Programing - POP (Tales Pinheiro)

Extendendo um protocolo Implementação padrão

extension Greeter { static func greeting() { print("Hello, \(String(describing: self))") } } Car.greeting() //Hello, Car

Page 20: Protocol Oriented Programing - POP (Tales Pinheiro)

Extendendo um protocolo Implementação padrão

extension Greeter { static func greeting() { print("Hello, \(String(describing: self))") } } Car.greeting() //Hello, Car Motorcycle.greeting() //Hello, Motorcycle

Page 21: Protocol Oriented Programing - POP (Tales Pinheiro)

Protocol Oriented Programming

Extensão de protocolos com implementações padrão

Page 22: Protocol Oriented Programing - POP (Tales Pinheiro)

POP Everything

• Views

• Networking

• Models

Page 23: Protocol Oriented Programing - POP (Tales Pinheiro)

POPing table view controllers

class DataViewcontroller: UITableViewController { override func viewDidLoad() { super.viewDidLoad() let dataCellNIB = UINib(nibName: "DataCell", bundle: nil) tableView.register(dataCellNIB, forCellReuseIdentifier: "DataCell") } }

Page 24: Protocol Oriented Programing - POP (Tales Pinheiro)

POPing table view controllers

class DataViewcontroller: UITableViewController { override func viewDidLoad() { super.viewDidLoad() let dataCellNIB = UINib(nibName: String(describing: DataCell.self), bundle: nil) tableView.register(dataCellNIB, forCellReuseIdentifier: String(describing: DataCell.self)) } }

Page 25: Protocol Oriented Programing - POP (Tales Pinheiro)

POPing table view controllers

protocol ReusableView: class {}

extension ReusableView where Self: UIView { static var reuseIdentifier: String { return String(describing: self) } }

Page 26: Protocol Oriented Programing - POP (Tales Pinheiro)

POPing table view controllers

protocol ReusableView: class {}

extension ReusableView where Self: UIView { static var reuseIdentifier: String { return String(describing: self) } }

extension UITableViewCell: ReusableView {} DataCell.reuseIdentifier

Page 27: Protocol Oriented Programing - POP (Tales Pinheiro)

POPing table view controllers

class DataViewcontroller: UITableViewController { override func viewDidLoad() { super.viewDidLoad() let dataCellNIB = UINib(nibName: String(describing: DataCell.self), bundle: nil) tableView.register(dataCellNIB, forCellReuseIdentifier: DataCell.reuseIdentifier) } }

Page 28: Protocol Oriented Programing - POP (Tales Pinheiro)

POPing table view controllers

protocol NibLoadableView: class {}

extension NibLoadableView where Self: UIView { static var nibName: String { return String(describing: self) } }

extension UITableViewCell: ReusableView {} DataCell.nibName

Page 29: Protocol Oriented Programing - POP (Tales Pinheiro)

POPing table view controllers

class DataViewcontroller: UITableViewController { override func viewDidLoad() { super.viewDidLoad() let dataCellNIB = UINib(nibName: DataCell.nibName, bundle: nil) tableView.register(dataCellNIB, forCellReuseIdentifier: DataCell.reuseIdentifier) } }

Page 30: Protocol Oriented Programing - POP (Tales Pinheiro)

POPing table view controllers

extension UITableView { func register<T: UITableViewCell>(class: T.Type) where T: ReusableView, T: NibLoadableView {

let nib = UINib(nibName: T.nibName, bundle: nil) register(nib, forCellReuseIdentifier: T.reuseIdentifier)

} }

Page 31: Protocol Oriented Programing - POP (Tales Pinheiro)

POPing table view controllers

let dataCellNIB = UINib(nibName: "DataCell", bundle: nil) tableView.register(dataCellNIB, forCellReuseIdentifier: "DataCell")

Page 32: Protocol Oriented Programing - POP (Tales Pinheiro)

POPing table view controllers

tableView.register(class: DataCell.self)

Page 33: Protocol Oriented Programing - POP (Tales Pinheiro)

POPing table view controllers

extension UITableView { func dequeueReusableCell<T: UITableViewCell>(forIndexPath indexPath: IndexPath) -> T where T: ReusableView { guard let cell = dequeueReusableCell(withIdentifier: T.reuseIdentifier, for: indexPath) as? T else { fatalError("Could not dequeue cell with identifier: \(T.reuseIdentifier)") } return cell } }

Page 34: Protocol Oriented Programing - POP (Tales Pinheiro)

POPing table view controllers

extension DataViewcontroller { override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

guard let cell = tableView.dequeueReusableCell(withIdentifier: "DataCel", for: indexPath) as? DataCell else { fatalError("Could not dequeue cell with identifier: DataCell") } return cell } }

Page 35: Protocol Oriented Programing - POP (Tales Pinheiro)

POPing table view controllers

extension DataViewcontroller { override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { return tableView.dequeueReusableCell(forIndexPath: indexPath) as DataCell } }

Page 36: Protocol Oriented Programing - POP (Tales Pinheiro)

POPing networking

class Session { static func sendRequest<R: Request>(request: R, handler: (Result<R.Response, Error>) -> Void) { } }

Page 37: Protocol Oriented Programing - POP (Tales Pinheiro)

POPing networking

let request = CreateBucketRequest(name: "Bucket", description: "My short description")

Session.sendRequest(request: request) { result in switch result { case let .success(response): // show response break case let .failure(error): // handle error break } }

Page 38: Protocol Oriented Programing - POP (Tales Pinheiro)

POPing networking

protocol Request { associatedtype Response var baseURL: URL { get } var method: HTTPMethod { get } var path: String { get } var paramenters: [String : Any] { get } func responseFromObject(object: AnyObject, URLResponse: HTTPURLResponse) throws -> Response }

Page 39: Protocol Oriented Programing - POP (Tales Pinheiro)

POPing networking

struct CreateBucketRequest: Request {

var baseURL = URL(string: "https: //api.dribbble.com/v1")! var method: HTTPMethod = .POST var path = "/buckets" var paramenters = [String : Any]() init(name: String, description: String) { paramenters["name"] = name paramenters["description"] = description } func responseFromObject(object: AnyObject, URLResponse: HTTPURLResponse) throws -> Bucket { guard let bucketDictionary = object as? [String : Any] else { throw ServiceError.InvalidObject(object) } let issue = Bucket(dictionary: bucketDictionary) return issue } }

Page 40: Protocol Oriented Programing - POP (Tales Pinheiro)

POPing networking

extension Request { var baseURL: URL { return URL(string: "https: //api.dribbble.com/v1")! } }

Page 41: Protocol Oriented Programing - POP (Tales Pinheiro)

POPing networking

extension Request where Response: Decodable { func responseFromObject(object: AnyObject, URLResponse: HTTPURLResponse) throws -> Bucket { return try Response.decode(object: object) as! Bucket } }

Page 42: Protocol Oriented Programing - POP (Tales Pinheiro)

POPing model

protocol Decodable { static func decode(object: AnyObject) throws -> Self }

Page 43: Protocol Oriented Programing - POP (Tales Pinheiro)

POPing model

protocol Decodable { static func decode(object: AnyObject) throws -> Self }

struct Bucket: Decodable { let id: Int var name: String var shots: [Shot] // ... static func decode(object: AnyObject) throws -> Bucket { var bucket = Bucket() //parsing ... return bucket } }

Page 44: Protocol Oriented Programing - POP (Tales Pinheiro)

POPing model

extension Collection where Iterator.Element: Shot { func filter(tag: String) -> [Iterator.Element] { let result = self.filter { shot in return shot.tags.contains(tag) } return result } }

Page 45: Protocol Oriented Programing - POP (Tales Pinheiro)

POPing model

extension Collection where Iterator.Element: Shot { func filter(tag: String) -> [Iterator.Element] { let result = self.filter { shot in return shot.tags.contains(tag) } return result } }

let bucket = Bucket() let shots = try! bucket.shots.filter(tag: "nature")

Page 46: Protocol Oriented Programing - POP (Tales Pinheiro)

POPing model

extension Collection where Iterator.Element: Bucket { func filter(tag: String) -> [Bucket] { return self.filter { bucket in return bucket.shots.filter(tag: tag).count > 0 } } }

Page 47: Protocol Oriented Programing - POP (Tales Pinheiro)

POPing model

extension Collection where Iterator.Element: Bucket { func filter(tag: String) -> [Bucket] { return self.filter { bucket in return bucket.shots.filter(tag: tag).count > 0 } } }

let buckets: [Bucket] = ... let natureBuckets = buckets.filter(tag: "nature")

Page 48: Protocol Oriented Programing - POP (Tales Pinheiro)

Conclusão

• POP é MUITO util

• principalmente com generics, mas isso fica para depois

• Elimina boilerplate

• Composição, flexibilidade dinamismo

• Apliquem :D

Obrigado :D

Page 49: Protocol Oriented Programing - POP (Tales Pinheiro)

www.concretesolutions.com.br blog.concretesolutions.com.br

Rio de Janeiro – Rua São José, 90 – cj. 2121 Centro – (21) 2240-2030

São Paulo - Rua Sansão Alves dos Santos, 433 4º andar - Brooklin - (11) 4119-0449