Where to find photos, sources for stock imagery that doesn't suck
Application architecture doesn't have to suck
Transcript of Application architecture doesn't have to suck
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