6. @_mboudraa
Problem to Solve
Easy to test all the components of an app (even the UI)
Easy to update
Easy to reproduce bugs to fix them
7. @_mboudraa
Problem to Solve
Easy to test all the components of an app (even the UI)
Easy to update
Easy to reproduce bugs to fix them
Global Picture of what’s happening by reading the code
11. @_mboudraa
Store
Reducer
f(AppState, Action) -> AppState
Redux / MVI
Pure
fun add(a: Int, b: Int): Int {
return a + b
}
fun add(a: Int, b: Int): Int {
val result = a + b
println(result)
return result
}
Not Pure
What’s a Pure function?
49. @_mboudraa
Action
sealed class Action {
data class CheckFields(val username: String, val password: String) : Action()
data class AttemptLogin(val username: String, val password: String) : Action()
data class LoginError(val message: String) : Action()
data class UnexpectedError(val message: String) : Action()
}
53. @_mboudraa
Store
It has the State of the App
Create a new State by reducing an action using the old state
f(State, Action) -> State
State is immutable
54. @_mboudraa
Store
It has the State of the App
Create a new State by reducing an action using the old state
f(State, Action) -> State
It dispatches actions to Side Effects after being reduced
State is immutable
56. @_mboudraa
State
data class AppState(val email: String,
val password: String,
val canSubmit: Boolean,
val isLoading: Boolean,
val hasLoginError: Boolean,
val loginError: String?,
val hasUnexpectedError: Boolean,
val unexpectedError: String?
val isLoginSuccessful: Boolean)
89. @_mboudraa
Implementation
class ValidState(private val stateMachine: StateMachine) {
fun onAction(action: Action) =
when(action){
is Action.CheckFields-> {
if (!action.username.isBlank())
stateMachine.nextState(ValidState(stateMachine))
else
stateMachine.nextState(DefaultState(stateMachine))
}
is Action.AttemptLogin -> {
stateMachine.nexState(LoadingState(stateMachine), Action.AttemptLogin))
}
}
}
class DefaultState(private val stateMachine: StateMachine) {
fun onAction(action: Action) =
if (action is Action.CheckFields)
if (!action.username.isBlank())
stateMachine.nextState(ValidState())
}
90. @_mboudraa
Implementationclass DefaultState(private val stateMachine: StateMachine) {
fun onAction(action: Action) {
if (action is Action.CheckFields) {
if (!action.username.isBlank()) {
stateMachine.nextState(ValidState())
}
}
}
}
class LoadingState(private val stateMachine: StateMachine) {
fun onAction(action: Action) =
if(action is Action.AttemptLogin){
async(UI) {
val account = bg { authService.signIn(action.credentials}.await()
stateMachine.nextState(AuthenticatedState())
}
}
}
class ValidState(private val stateMachine: StateMachine) {
fun onAction(action: Action) =
when(action){
is Action.CheckFields-> {
if (!action.username.isBlank())
stateMachine.nextState(ValidState(stateMachine))
else
stateMachine.nextState(DefaultState(stateMachine))
}
is Action.AttemptLogin -> {
stateMachine.nexState(LoadingState(stateMachine), Action.AttemptLogin))
}
}
}
92. @_mboudraa
Sum Up
Pros
Cons
MVI / Redux
Easy to find bugs
Easy to maintain
Easy to add new actions
Global Picture of possible actions
Logic business is isolated in pure functions
Side Effects are isolated
ViewController need to figure out the actual state
Actions can be dispatched from anywhere
No Global Picture of the flow
93. @_mboudraa
Sum Up
Pros
Cons
MVI / Redux
Easy to find bugs
Easy to maintain
Easy to add new actions
Global Picture of possible actions
Logic business is isolated in pure functions
Side Effects are isolated
ViewController need to figure out the actual state
Actions can be dispatched from anywhere
No Global Picture of the flow
State Machine
Easy to find bugs
Easy to maintain
Actions are carried by the state
ViewController receive a state
Hard to add new states
No Global Picture of the flow
Business Logic and Side effects are inside the state
State are responsible for going to the next state
94. @_mboudraa
Sum Up
MVI / Redux State Machine
Pros
Easy to find bugs
Easy to maintain
Easy to add new actions
Global Picture of possible actions
Logic business is isolated in pure functions
Side Effects are isolated
Easy to find bugs
Easy to maintain
Actions are carried by the state
ViewController receive a state
Cons
ViewController need to figure out the actual state
Actions can be dispatch from anywhere
No Global Picture of the flow
Hard to add new states
No Global Picture of the flow
Business Logic and Side effects are inside the state
State are responsible for going to the next state
97. @_mboudraa
Kotlin to the rescue
class HTML {
var title: String
fun body() {
...
}
}
html {
title = "Droidcon Dubai"
body()
}
98. @_mboudraa
Kotlin to the rescue
class HTML {
var title: String
fun body() {
...
}
}
fun html(content: HTML.() -> Unit): HTML {
val html = HTML() // create the receiver object
html.content() // pass the receiver object to the lambda
return html
}
html {
title = "Droidcon Dubai"
body()
}