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

Unidirectional Data Flow in Mobile Applications

Unidirectional Data Flow in Mobile Applications

Avatar for Matthias Schmidt

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