Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Dobry zwyczaj: nie odziedziczaj

Dobry zwyczaj: nie odziedziczaj

Slides for my conference talk from Mobilization 2015, 2015/10/17.

Polish only.

English title would be "Solely on merit: do not inherit"

43d2bef703ec7165166f161f137ac54f?s=128

Krzysztof Siejkowski

October 17, 2015
Tweet

Transcript

  1. Dobry zwyczaj nie odziedziczaj @_siejkowski siejkowski.net !

  2. None
  3. class A : B

  4. BaseViewController BaseDataFetchingViewController :BaseViewController BaseFormPresentingViewController :BaseDataFetchingViewController

  5. Przepraszam, czy mogę przeciążyć?

  6. super ?

  7. None
  8. NSManagedObject https://github.com/rentzsch/mogenerator

  9. BaseViewController : UIViewController ThirdPartyBehaviorEnablingViewController : UIViewController UserAccountDetailsViewController : !

  10. struct SomeStruct {} enum SomeEnum {} typealias SomeFunction = (Int

    -> String) class C : SomeFunction ❗ Inheritance from non-protocol, non-class type 'SomeFunction'
  11. agregacja protokoły funkcje

  12. ThirdPartyBehaviorEnablingService ThirdPartyBehaviorEnablingDelegate

  13. init(accountService: AccountService, transactionService: TransactionService, sessionService: SessionService, favouritesService: FavouritesService, locationService: LocationService,

    ...)
  14. class *-Utils class *-Helper

  15. UITableViewDataSource UITableViewDelegate

  16. code review TDD style guide clean code

  17. agregacja protokoły funkcje

  18. protocol SessionAware protocol LocationAware protocol FavouritesFetchable class MyViewController : UIViewController,

    SessionAware, LocationAware, FavouritesFetchable
  19. extension UIViewController : SessionAware

  20. protocol SessionAware { func login(username: String, _ password: String, _

    callback: (UserDetails) -> ()) } extension MyViewController : SessionAware {} extension SessionAware { func login(username: String, _ password: String, _ callback: (UserDetails) -> ())) { // domyślna implementacja } } ❗ http://nomothetis.svbtle.com/the-ghost-of-swift-bugs-future
  21. protocol FavouritesDataSource : UITableViewDataSource { var state: [FavouriteDetails] { get

    } // "obietnica" stanu } extension FavouritesDataSource { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return state.count // ... protocol FavouritesTableDelegate : UITableViewDelegate { var state: [FavouriteDetails] { get } // "obietnica" stanu } extension FavouritesTableDelegate { func tableView(_ tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { // ... class MyViewController : NSObject, FavouritesDataSource, FavouritesTableDelegate { var state: [FavouriteDetails] = Array() init(newState: [FavouriteDetails]) { state = newState }
  22. ⬆ dziedziczenie ⬇ ⬅ protokoły ➡

  23. agregacja protokoły funkcje

  24. func login(username: String, _ password: String, _ callback: (UserDetails) ->

    ()) func update(view: HeaderView) (_ user: UserDetails) -> UserDetails func fetchFavourites(user: UserDetails) (_ callback: (FavouritesData) -> ()) func update(source: FavoritesDataSource) (_ tableView: UITableView) (_ favourites: FavouritesData)
  25. class SomeViewController { let updateHeader = update(headerView) let updateFavourites =

    update(favouritesDataSource)(tableView) override func viewDidLoad() { // ..., m.in super.viewDidLoad() login("siejkowski","mobilization") { details in fetchFavourites(updateHeader(details))(updateFavourites) } }
  26. infix operator |> { associativity left } infix operator <|

    { associativity right } public func |> <A, B>(a : A, f : A -> B) -> B { return f(a) } public func <| <A, B>(f : A -> B, a : A) -> B { return f(a) }
  27. infix operator useFor { associativity left } details useFor updateHeader

    ❗ !
  28. login("siejkowski","mobilization") { details in fetchFavourites(updateHeader(details))(updateFavourites) } ⬇ ⬇ ⬇ login("siejkowski","mobilization")

    { details in (details |> updateHeader |> fetchFavourites) <| updateFavourites }
  29. agregacja protokoły funkcje

  30. class SomeViewController { let updateHeader = update(headerView) let updateFavourites =

    update(favouritesDataSource)(tableView) override func viewDidLoad() { super.viewDidLoad() login("siejkowski","mobilization") { details in (details |> updateHeader |> fetchFavourites) <| updateFavourites } } !
  31. pure functions Swift functions

  32. struct FunctionUsingStruct { let func: String -> Bool init(_ injectedFunc:

    String -> Bool) { // funkcje można wstrzykiwać func = injectedFunc ... } } !
  33. class DIFactory { func realFunc(string: String) -> Bool { ...

    } // w produkcyjnym kodzie wstrzykujemy prawdziwą funkcję func functionUsingStruct() -> FunctionUsingStruct { return FunctionUsingStruct(realFunc) } class TestCase { func testFunc(string: String) -> Bool { return true } // w testowym kodzie używamy mockowej funkcji let testStruct = FunctionUsingStruct(testFunc) !
  34. func login(username: String, _ password: String, _ callback: (UserDetails) ->

    ()) func fullLogin(loginManager: LoginManager) (_ username: String, _ password: String, _ callback(UserDetails) -> ()) -> () { loginManager.login(username, password, callback) } let login = fullLogin(actualLoginManager) let mockLogin = fullLogin(mockLoginManager)
  35. funkcje ❤ protokoły

  36. extension MyViewController : SessionAware { func login(username: String, _ password:

    String, _ callback: (UserDetails) -> ()) { // tutaj przekazany jest domyślnie self } } func login(username: String, _ password: String, _ callback: (UserDetails) -> ()) { // tutaj przekazane jest to co w sygnaturze }
  37. func root(double: Double) -> Double? { ... } func root(float:

    Float) -> Float? { ... } func root(int: Int) -> Int? { ... } protocol Rootable { func root() -> Self? } extension Double : Rootable { ... } extension Float : Rootable { ... } extension Int : Rootable { ... } func useRootable(rootable: Rootable) { rootable.root() }
  38. *-able protocol JSONDecodable { static func decode(json: JSON) -> Self

    } protocol Validatable { func validate(validator: Validator) -> Bool } protocol Hashable : Equatable { public var hashValue: Int { get } }
  39. Co jest problemem? nil ErrorType asynchroniczność logowanie sekwencja callback cokolwiek

    chcesz !
  40. func canCauseProblem(input: Int) -> ProblemHiding<String> func possibleProblem(input: String) -> ProblemHiding<Double>

    func yetAnotherProblem(input: Double) -> ProblemHiding<Int> let input = 42 ProblemHiding(input) // udajemy że wszystko gra .execute(canCauseProblem) // jakby nic się nie stało .execute(possibleProblem) // bez nerwów, bez ifów .execute(yetAnotherProblem) // jak kwiat lotosu .obtainValue() // sprawdzam!
  41. protocol Monad { typealias A typealias B typealias FB func

    bind(f: A -> FB) -> FB } !
  42. extension Optional : Monad { typealias A = Wrapped typealias

    B = Any // nil jest problemem typealias FB = B? func bind<B>(f: A -> B?) -> B? { return self.flatMap(f) } } extension Array : Monad { typealias A = Element typealias B = Any // wiele wartości to problem typealias FB = Array<B> func bind<B>(f: A -> [B]) -> [B] { return self.flatMap(f) } }
  43. enum Result<Value> { // możliwy ErrorType to problem case Success(Value)

    case Failure(ErrorType) } extension Result : Monad { typealias A = Value typealias B = Any typealias FB = Result<B> func bind<B>(f: A -> Result<B>) -> Result<B> { switch self { case .Success(let value): return f(value) case .Failure(let error): return .Failure(error) } } }
  44. https://github.com/typelift Swiftx Swiftz https://github.com/thoughtbot Runes Argo https://github.com/robrix Prelude

  45. agregacja ❤ protokoły ❤ funkcje

  46. agregacja ❤ protokoły ❤ funkcje ❤ dziedziczenie

  47. Dziękuję! @_siejkowski !