SUCKAPPLICATION ARCHITECTURE DOESN’T HAVE TO
APPLICATION ARCHITECTURE DOESN’T HAVE TO SUCK
WHO AM I?
▸ Jeremy Tregunna
▸ Programming for 29 years
▸ iOS since the unofficial SDK
▸ Twitter: @jtregunna
▸ GitHub: github.com/jeremytregunna
APPLICATION ARCHITECTURE DOESN’T HAVE TO SUCK
WHO AM I?
▸ Jeremy Tregunna
▸ Programming for 29 years
▸ iOS since the unofficial SDK
▸ Twitter: @jtregunna
▸ GitHub: github.com/jeremytregunna
▸ Aspiring boat builder
MVC
APPLICATION ARCHITECTURE DOESN’T HAVE TO SUCK
VIEW CONTROLLER RESPONSIBILITIES
▸ Animations
▸ Orientation changes
▸ Laying out views
▸ Handling user input
APPLICATION ARCHITECTURE DOESN’T HAVE TO SUCK
VIEW CONTROLLER RESPONSIBILITIES
▸ Animations
▸ Orientation changes
▸ Laying out views
▸ Handling user input
▸ Making network requests
▸ Model Mutation
▸ Synchronizing communication
APPLICATION ARCHITECTURE DOESN’T HAVE TO SUCK
VIEW CONTROLLER RESPONSIBILITIES
▸ Animations
▸ Orientation changes
▸ Laying out views
▸ Handling user input
▸ Making network requests
▸ Model Mutation
▸ Synchronizing communication
MASSIVE VIEW
CONTROLLER
APPLICATION ARCHITECTURE DOESN’T HAVE TO SUCK
MVC PROBLEMS
▸ Massive view controllers suck
▸ State synchronization
▸ View controller entanglement
▸ Reuse issues abound
▸ Testing
▸ Many more, but that’s another talk.
MVVM
APPLICATION ARCHITECTURE DOESN’T HAVE TO SUCK
VIEW CONTROLLER
▸ Animations
▸ Orientation changes
▸ Binding views to data
VIEW
▸ Handling user input
▸ Laying out subviews
APPLICATION ARCHITECTURE DOESN’T HAVE TO SUCK
MVVM PROBLEMS
▸ Data binding support isn’t native
▸ High barrier to entry for new team members
▸ FRP helps, but tends to spread through your code like the plague
▸ Real world examples tend to pair ViewModels and ViewControllers, more like MVC-N
REDUX
REDUX-ISH
APPLICATION ARCHITECTURE DOESN’T HAVE TO SUCK
INTRODUCTION
▸ Web world
APPLICATION ARCHITECTURE DOESN’T HAVE TO SUCK
INTRODUCTION
▸ Web world
▸ Application state easy to conceptualize
APPLICATION ARCHITECTURE DOESN’T HAVE TO SUCK
INTRODUCTION
▸ Web world
▸ Application state easy to conceptualize
▸ Unidirectional data flow
APPLICATION ARCHITECTURE DOESN’T HAVE TO SUCK
INTRODUCTION
▸ Web world
▸ Application state easy to conceptualize
▸ Unidirectional data flow
▸ Changing state means firing an action
APPLICATION ARCHITECTURE DOESN’T HAVE TO SUCK
INTRODUCTION
▸ Web world
▸ Application state easy to conceptualize
▸ Unidirectional data flow
▸ Changing state means firing an action
▸ State transformers isolated
APPLICATION ARCHITECTURE DOESN’T HAVE TO SUCK
INTRODUCTION
▸ Web world
▸ Application state easy to conceptualize
▸ Unidirectional data flow
▸ Changing state means firing an action
▸ State transformers isolated
▸ Foreign, but easy to understand
CLOSER LOOK
APPLICATION ARCHITECTURE DOESN’T HAVE TO SUCK
STOREclass Store<S: State> { var subscriptions: [NewStateDeliverable] = [] var dispatchFunction: ((Action) -> Any)! var state: S! { didSet { subscriptions.forEach { $0.newState(state) } } }
func subscribe(subscriber: NewStateDeliverable) { guard _alreadySubscribed(subscriber) else { return } subscriptions.append(subscribe) if let state = state { subscriber.newState(state) } }
func dispatch(action: Action) -> Any { return dispatchFunction(action) } }
APPLICATION ARCHITECTURE DOESN’T HAVE TO SUCK
REDUCERstruct CounterReducer: Reducer { func handleAction(action: Action, state: AppState?) -> AppState { var state = state ?? AppState()
switch action { case _ as IncrementAction: state.counter += 1 case _ as DecrementAction: state.counter -= 1 default: break }
return state } }
APPLICATION ARCHITECTURE DOESN’T HAVE TO SUCK
ACTIONstruct IncreaseAction: Action {}
struct DecreaseAction: Action {}
// More realistic example…
struct SignInAction: Action { let email: String let password: String }
NAVIGATION
APPLICATION ARCHITECTURE DOESN’T HAVE TO SUCK
PROBLEMS
▸ View controllers tend to know about other view controllers
APPLICATION ARCHITECTURE DOESN’T HAVE TO SUCK
PROBLEMS
▸ View controllers tend to know about other view controllers
▸ Complicated state synchronization between VCs to share state changes
APPLICATION ARCHITECTURE DOESN’T HAVE TO SUCK
PROBLEMS
▸ View controllers tend to know about other view controllers
▸ Complicated state synchronization between VCs to share state changes
▸ External routers contain some of these problems, VCs still dependent
APPLICATION ARCHITECTURE DOESN’T HAVE TO SUCK
PROBLEMS
▸ View controllers tend to know about other view controllers
▸ Complicated state synchronization between VCs to share state changes
▸ External routers contain some of these problems, VCs still dependent
▸ Lack of dynamic hierarchies
SOLUTIONS?
APPLICATION ARCHITECTURE DOESN’T HAVE TO SUCKTEXT
FIRE AN ACTION
▸ Track navigation state as part of our application state, because it is.
▸ Router acts as a reducer over navigation state
▸ Fire an action when you want to present something
APPLICATION ARCHITECTURE DOESN’T HAVE TO SUCKTEXT
RESPONDER CHAIN
▸ Built in
▸ Passes messages along a chain of responsibility
▸ Message ignored if nobody can answer it
▸ Familiar pattern
DEMO
WHY?
APPLICATION ARCHITECTURE DOESN’T HAVE TO SUCK
REASONS FOR THIS ARCHITECTURE
▸ MVC defers complexity to controller level
APPLICATION ARCHITECTURE DOESN’T HAVE TO SUCK
REASONS FOR THIS ARCHITECTURE
▸ MVC defers complexity to controller level
▸ MVVM non-native binding mechanism
APPLICATION ARCHITECTURE DOESN’T HAVE TO SUCK
REASONS FOR THIS ARCHITECTURE
▸ MVC defers complexity to controller level
▸ MVVM non-native binding mechanism
▸ Actions can be persisted, and replayed
APPLICATION ARCHITECTURE DOESN’T HAVE TO SUCK
REASONS FOR THIS ARCHITECTURE
▸ MVC defers complexity to controller level
▸ MVVM non-native binding mechanism
▸ Actions can be persisted, and replayed
▸ Avoids hidden dependencies
APPLICATION ARCHITECTURE DOESN’T HAVE TO SUCK
REASONS FOR THIS ARCHITECTURE
▸ MVC defers complexity to controller level
▸ MVVM non-native binding mechanism
▸ Actions can be persisted, and replayed
▸ Avoids hidden dependencies
▸ State manipulation is standard
QUESTIONS?
THANK YOU!https://github.com/Greenshire/Calibre