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

A portal from Elm to Swift

A portal from Elm to Swift

An introduction to the Elm architecture analyzing what's wrong with all the architectures that came before (MVC, MVP, MVVM) and how to implement it in Swift.

17411ddb51e17861ef4f8e2d866f7ab6?s=128

Guido Marucci Blas

April 26, 2017
Tweet

More Decks by Guido Marucci Blas

Other Decks in Programming

Transcript

  1. A PORTAL FROM ELM TO SWIFT 1 — A Portal

    from Elm to Swift by Guido Marucci Blas
  2. GUIDO MARUCCI BLAS CO-FOUNDER & TECH LEAD AT WOLOX CTO

    AT SYRMO Twitter: @guidomb Blog: http://guidomb.blog GitHub: http://github.com/guidomb 2 — A Portal from Elm to Swift by Guido Marucci Blas
  3. 3 — A Portal from Elm to Swift by Guido

    Marucci Blas
  4. 4 — A Portal from Elm to Swift by Guido

    Marucci Blas
  5. A PORTAL FROM ELM TO SWIFT 5 — A Portal

    from Elm to Swift by Guido Marucci Blas
  6. 6 — A Portal from Elm to Swift by Guido

    Marucci Blas
  7. 7 — A Portal from Elm to Swift by Guido

    Marucci Blas
  8. 8 — A Portal from Elm to Swift by Guido

    Marucci Blas
  9. 9 — A Portal from Elm to Swift by Guido

    Marucci Blas
  10. GO BACK IN TIME ... 10 — A Portal from

    Elm to Swift by Guido Marucci Blas
  11. MODEL VIEW CONTROLLER 11 — A Portal from Elm to

    Swift by Guido Marucci Blas
  12. 12 — A Portal from Elm to Swift by Guido

    Marucci Blas
  13. MVC - PROBLEMS > Massive fat controllers > Hard to

    test > Highly coupled > Lots of boilerplate 13 — A Portal from Elm to Swift by Guido Marucci Blas
  14. MVC - POSSIBLE SOLUTIONS > Extract business logic > Extract

    "side-effects" into services with protocols > Use dependency injection > Use notifications 14 — A Portal from Elm to Swift by Guido Marucci Blas
  15. MODEL VIEW PRESENTER 15 — A Portal from Elm to

    Swift by Guido Marucci Blas
  16. 16 — A Portal from Elm to Swift by Guido

    Marucci Blas
  17. MVP - PROBLEMS > Way more boilerplate > Most of

    the problems / solutions from MVC still apply. 17 — A Portal from Elm to Swift by Guido Marucci Blas
  18. MODEL VIEW VIEWMODEL 18 — A Portal from Elm to

    Swift by Guido Marucci Blas
  19. 19 — A Portal from Elm to Swift by Guido

    Marucci Blas
  20. 20 — A Portal from Elm to Swift by Guido

    Marucci Blas
  21. MVVM - PROBLEMS > Requires a binding mechanisim > It's

    not clear who is responsable for view transitions > Forces you to use DI framework, singletons or propagate dependencies over the whole hierarchy 21 — A Portal from Elm to Swift by Guido Marucci Blas
  22. FUNCTIONAL REACTIVE PROGRAMMING 22 — A Portal from Elm to

    Swift by Guido Marucci Blas
  23. 23 — A Portal from Elm to Swift by Guido

    Marucci Blas
  24. 24 — A Portal from Elm to Swift by Guido

    Marucci Blas
  25. All this architectures still have the same problems 25 —

    A Portal from Elm to Swift by Guido Marucci Blas
  26. The application's state is spread over several components 26 —

    A Portal from Elm to Swift by Guido Marucci Blas
  27. Which means state is mutated all over the place 27

    — A Portal from Elm to Swift by Guido Marucci Blas
  28. Which also means that if state needs to be shared,

    it must be kept in sync 28 — A Portal from Elm to Swift by Guido Marucci Blas
  29. Shared mutable state is the root of all EVIL 29

    — A Portal from Elm to Swift by Guido Marucci Blas
  30. 30 — A Portal from Elm to Swift by Guido

    Marucci Blas
  31. yes, there is more 31 — A Portal from Elm

    to Swift by Guido Marucci Blas
  32. The other big issue is how this architectures manage side-

    effects 32 — A Portal from Elm to Swift by Guido Marucci Blas
  33. What do we do next? 33 — A Portal from

    Elm to Swift by Guido Marucci Blas
  34. THE ELM ARCHITECTURE 34 — A Portal from Elm to

    Swift by Guido Marucci Blas
  35. 35 — A Portal from Elm to Swift by Guido

    Marucci Blas
  36. 36 — A Portal from Elm to Swift by Guido

    Marucci Blas
  37. but what about Swift? 37 — A Portal from Elm

    to Swift by Guido Marucci Blas
  38. GITHUB ReSwift/ReSwift BendingSpoons/katana-swift 38 — A Portal from Elm to

    Swift by Guido Marucci Blas
  39. If you want the full power of the Elm architecture

    you need ... 39 — A Portal from Elm to Swift by Guido Marucci Blas
  40. DECLARATIVES UI 40 — A Portal from Elm to Swift

    by Guido Marucci Blas
  41. But UIKit will make your life miserable 41 — A

    Portal from Elm to Swift by Guido Marucci Blas
  42. guidomb/PortalView 42 — A Portal from Elm to Swift by

    Guido Marucci Blas
  43. A (potentially) cross-platform, declarative and immutable Swift library for building

    user interfaces 43 — A Portal from Elm to Swift by Guido Marucci Blas
  44. 100% written in Swift 44 — A Portal from Elm

    to Swift by Guido Marucci Blas
  45. The declarative API is NOT coupled to UIKit 45 —

    A Portal from Elm to Swift by Guido Marucci Blas
  46. facebook/yoga 46 — A Portal from Elm to Swift by

    Guido Marucci Blas
  47. enum Message { case like case goToDetailScreen } let component:

    Component<Message> = container( children: [ label( text: "Hello PortalView!", style: labelStyleSheet() { base, label in base.backgroundColor = .white label.textColor = .red label.textSize = 12 }, layout: layout() { $0.flex = flex() { $0.grow = .one } $0.justifyContent = .flexEnd } ) button( properties: properties() { $0.text = "Tap to like!" $0.onTap = .like } ) button( properties: properties() { $0.text = "Tap to got to detail screen" $0.onTap = .goToDetailScreen } ) ] ) 47 — A Portal from Elm to Swift by Guido Marucci Blas
  48. label( text: "Hello PortalView!", style: labelStyleSheet() { base, label in

    base.backgroundColor = .white label.textColor = .red label.textSize = 12 }, layout: layout() { $0.flex = flex() { $0.grow = .one } $0.justifyContent = .flexEnd } ) 48 — A Portal from Elm to Swift by Guido Marucci Blas
  49. button( properties: properties() { $0.text = "Tap to like!" $0.onTap

    = .like } ) 49 — A Portal from Elm to Swift by Guido Marucci Blas
  50. public indirect enum Component<MessageType> { case button(ButtonProperties<MessageType>, StyleSheet<ButtonStyleSheet>, Layout) case

    label(LabelProperties, StyleSheet<LabelStyleSheet>, Layout) case mapView(MapProperties, StyleSheet<EmptyStyleSheet>, Layout) case imageView(Image, StyleSheet<EmptyStyleSheet>, Layout) case container([Component<MessageType>], StyleSheet<EmptyStyleSheet>, Layout) case table(TableProperties<MessageType>, StyleSheet<TableStyleSheet>, Layout) case collection(CollectionProperties<MessageType>, StyleSheet<EmptyStyleSheet>, Layout) case carousel(CarouselProperties<MessageType>, StyleSheet<EmptyStyleSheet>, Layout) case touchable(gesture: Gesture<MessageType>, child: Component<MessageType>) case segmented(ZipList<SegmentProperties<MessageType>>, StyleSheet<SegmentedStyleSheet>, Layout) case progress(ProgressCounter, StyleSheet<ProgressStyleSheet>, Layout) case textField(TextFieldProperties<MessageType>, StyleSheet<TextFieldStyleSheet>, Layout) case custom(componentIdentifier: String, layout: Layout) case spinner(Bool, StyleSheet<SpinnerStyleSheet>, Layout) } 50 — A Portal from Elm to Swift by Guido Marucci Blas
  51. DEMO 51 — A Portal from Elm to Swift by

    Guido Marucci Blas
  52. but what about state management and side-effects? 52 — A

    Portal from Elm to Swift by Guido Marucci Blas
  53. guidomb/PortalApplication 53 — A Portal from Elm to Swift by

    Guido Marucci Blas
  54. public protocol Application { associatedtype MessageType associatedtype StateType associatedtype CommandType

    associatedtype RouteType: Route associatedtype SubscriptionType: Equatable associatedtype NavigatorType: Navigator var initialState: StateType { get } var initialRoute: RouteType { get } func translateRouteChange(from currentRoute: RouteType, to nextRoute: RouteType) -> MessageType? func update(state: StateType, message: MessageType) -> (StateType, CommandType?)? func view(for state: StateType) -> View<RouteType, MessageType, NavigatorType> func subscriptions(for state: StateType) -> [Subscription<MessageType, RouteType, SubscriptionType>] } 54 — A Portal from Elm to Swift by Guido Marucci Blas
  55. public struct View<RouteType: Route, MessageType, NavigatorType: Navigator> { public typealias

    ActionType = Action<RouteType, MessageType> public enum Content { case alert(properties: AlertProperties<ActionType>) case component(Component<ActionType>) } public let navigator: NavigatorType public let root: RootComponent<ActionType> public let content: Content } 55 — A Portal from Elm to Swift by Guido Marucci Blas
  56. public indirect enum Action<RouteType: Route, MessageType> { case dismissNavigator(thenSend: Action<RouteType,

    MessageType>?) case navigateToPreviousRoute(preformTransition: Bool) case navigate(to: RouteType) case sendMessage(MessageType) } 56 — A Portal from Elm to Swift by Guido Marucci Blas
  57. public protocol Route: Equatable { var previous: Self? { get

    } } public protocol Navigator: Equatable { associatedtype RouteType: Route var baseRoute: RouteType { get } } 57 — A Portal from Elm to Swift by Guido Marucci Blas
  58. public protocol CommandExecutor { associatedtype CommandType associatedtype MessageType func execute(command:

    CommandType, dispatch: @escaping (MessageType) -> Void) } 58 — A Portal from Elm to Swift by Guido Marucci Blas
  59. import UIKit import PortalApplication import PortalView let context = UIKitApplicationContext(

    application: Voices(), commandExecutor: VoicesCommandExecutor(), subscriptionManager: VoicesSubscriptionManager(), customComponentRenderer: VoidCustomComponentRenderer() ) context.registerMiddleware(TimeLogger()) PortalUIApplication.start(applicationContext: context) { message in switch message { case .didFinishLaunching(_, _): return .applicationLaunched default: return .none } } 59 — A Portal from Elm to Swift by Guido Marucci Blas
  60. DEMO 60 — A Portal from Elm to Swift by

    Guido Marucci Blas
  61. guidomb/PortalView guidomb/PortalApplication guidomb/SyrmoPortalExample guidomb/Voices 61 — A Portal from Elm

    to Swift by Guido Marucci Blas
  62. PORTAL - WARNING > Still very early stage > API

    will probably change > Still needs important features like UI diffing 62 — A Portal from Elm to Swift by Guido Marucci Blas
  63. PORTAL - MILESTONES > API stability > Improve performance >

    Cool tooling, like hot UI reload > Server side rendering? > Android support 63 — A Portal from Elm to Swift by Guido Marucci Blas
  64. you are crazy, I cannot do a full rewrite of

    my massive application ... 64 — A Portal from Elm to Swift by Guido Marucci Blas
  65. you can add Portal gradually into your application or ...

    65 — A Portal from Elm to Swift by Guido Marucci Blas
  66. Take the key concepts from this talk and apply them

    to your existing architecture 66 — A Portal from Elm to Swift by Guido Marucci Blas
  67. TL; DR; > Decouple side-effects froms logic by describing effects

    using values > Avoid state sincronization, have a central place where state is mutated > Avoid deep view / object hierarchy, prefer wide hierarchies 67 — A Portal from Elm to Swift by Guido Marucci Blas
  68. GUIDO MARUCCI BLAS Twitter: @guidomb Blog: http://guidomb.blog GitHub: http://github.com/guidomb 68

    — A Portal from Elm to Swift by Guido Marucci Blas
  69. THANKS! 69 — A Portal from Elm to Swift by

    Guido Marucci Blas