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

Unidirectional Data Flow in Mobile Applications

Unidirectional Data Flow in Mobile Applications

Matthias Schmidt

November 19, 2017
Tweet

Other Decks in Programming

Transcript

  1. Unidirectional Data Flow in Mobile Applications - Mobile Developer Group

    Braunschweig Problem #1 • MVC doesn’t address many issues of modern app development • Complex UI • Networking • Navigation • View Controller as micromanagers ➔ Massive View Controllers 4
  2. Unidirectional Data Flow in Mobile Applications - Mobile Developer Group

    Braunschweig Problem #2 • Manage the different states • Currently active Views / View Controller • Database • Singletons • “how do I pass information between view controllers?” • Multiple copies of the state 5
  3. Unidirectional Data Flow in Mobile Applications - Mobile Developer Group

    Braunschweig Redux Components • State is an immutable data structure • State is stored inside of the store • Emitting actions to create a new state • Reducers perform the state changes • Observers will be view controllers 7
  4. Unidirectional Data Flow in Mobile Applications - Mobile Developer Group

    Braunschweig Demo func didSelectSightWithId(_ id: UInt) { store.dispatch(UpdateSelectedSight(sightId: id)) } 9
  5. Unidirectional Data Flow in Mobile Applications - Mobile Developer Group

    Braunschweig Demo func backendReducer(action: Action, state: BackendState?) -> BackendState { guard let state = state else { return BackendState(...) } var selectedSight = state.selectedSight switch action { case let action as UpdateSelectedSight: if action.sightId != nil { selectedSight = ... // Find Sight } else { selectedSight = nil } default: return state } return BackendState(selectedSight: selectedSight, ...) } 10
  6. Unidirectional Data Flow in Mobile Applications - Mobile Developer Group

    Braunschweig Demo func newState(state: AppState) { if state.backendState.selectedSight != nil && state.navigationState.sightDetailsViewIsVisible == false { // show details view store.dispatch(navigationService.showSightDetails) } } 11
  7. Unidirectional Data Flow in Mobile Applications - Mobile Developer Group

    Braunschweig Action-Creator func loginUser(state: AppState, store: Store<AppState>) -> Action? { guard let request = self.buildRequest(uri: "/users", credentials: state.authentificationState.credentials) else { return nil } request.responseJSON { response in ... }.validate(statusCode: 200...200) return nil } 13
  8. Unidirectional Data Flow in Mobile Applications - Mobile Developer Group

    Braunschweig Action-Creator func loginUser(state: AppState, store: Store<AppState>) -> Action? { guard let request = ... request.responseJSON { response in switch response.result { case .success: if let json = response.result.value as? [String: Any] { // DISPATCH #1 - New User store.dispatch(UpdateLoginState(user: User(JSON: json), status: .loggedIn)) } else { // DISPATCH #2 - Error store.dispatch(UpdateLoginState(user: nil, status: .failed(errorCode: 0))) } } }.validate(statusCode: 200...200) return nil } 14
  9. Unidirectional Data Flow in Mobile Applications - Mobile Developer Group

    Braunschweig Action-Creator func loginUser(state: AppState, store: Store<AppState>) -> Action? { guard let request = ... request.responseJSON { response in switch response.result { case .success: if let json = response.result.value as? [String: Any] { // DISPATCH #1 - New User store.dispatch(UpdateLoginState(user: User(JSON: json), status: .loggedIn)) } else { // DISPATCH #2 - Error store.dispatch(UpdateLoginState(user: nil, status: .failed(errorCode: 0))) } case .failure(_): // DISPATCH #3 - Invalid Credentials store.dispatch(UpdateLoginState(user: nil, status: .invalidCredentials)) } }.validate(statusCode: 200...200) return nil } 15
  10. Unidirectional Data Flow in Mobile Applications - Mobile Developer Group

    Braunschweig Action-Creator store.dispatch(backendService.loginUser) 16
  11. Unidirectional Data Flow in Mobile Applications - Mobile Developer Group

    Braunschweig Action-Creator-Creator func registerUser(registrationData: RegistrationData) -> (AppState, Store<AppState>) -> Action? { return { (state: AppState, store: Store<AppState>) -> Action? in return nil } } 18
  12. Unidirectional Data Flow in Mobile Applications - Mobile Developer Group

    Braunschweig Action-Creator-Creator func registerUser(registrationData: RegistrationData) -> (AppState, Store<AppState>) -> Action? { return { (state: AppState, store: Store<AppState>) -> Action? in let params: [String: Any] = ["name": registrationData.username, "email": registrationData.email, "password": registrationData.password] guard let request = ... return nil } } 19
  13. Unidirectional Data Flow in Mobile Applications - Mobile Developer Group

    Braunschweig Action-Creator-Creator func registerUser(registrationData: RegistrationData) -> (AppState, Store<AppState>) -> Action? { return { (state: AppState, store: Store<AppState>) -> Action? in let params: [String: Any] = ["name": registrationData.username, "email": registrationData.email, "password": registrationData.password] guard let request = ... request.responseJSON { response in switch response.result { case .success: // DISPATCH #1 - New User store.dispatch(UpdateLoginState(user: User(JSON: ...), status: .loggedIn)) case .failure(let error): ... }.validate(statusCode: 201...201) return nil } } 20
  14. Unidirectional Data Flow in Mobile Applications - Mobile Developer Group

    Braunschweig Action-Creator-Creator store.dispatch(backendService.registerUser(registrationData: registration)) 21
  15. Unidirectional Data Flow in Mobile Applications - Mobile Developer Group

    Braunschweig Middleware let actionLoggerMiddleware: Middleware = { dispatch, getState in return { next in return { action in print("Action: \(action)") // next middleware return next(action) } } } 23
  16. Unidirectional Data Flow in Mobile Applications - Mobile Developer Group

    Braunschweig Benefits • separation of concerns • decoupling of intent and implementation • clearer, declarative API • predictable and explicit state • state propagation for free 24
  17. Unidirectional Data Flow in Mobile Applications - Mobile Developer Group

    Braunschweig Credits • Unidirectional Data Flow: Shrinking Massive View Controllers
 https://academy.realm.io/posts/benji-encz-unidirectional-data-flow-swift/ • GitHub - ReSwift/ReSwift: Unidirectional Data Flow in Swift
 https://github.com/ReSwift/ReSwift • iOS Architecture Patterns
 https://medium.com/ios-os-x-development/ios-architecture-patterns-ecba4c38de52 25