SlideShare a Scribd company logo
TEA in Prod
Artur Badretdinov, Squire
1
Artur Badretdinov
Digital Nomad, Lead Android
Developer at Squire
https://t.me/travelernote
https://t.me/ohmyeventbot
2
The Elm Architecture
in prod
3
Live demo ahead
Real app approach, 160 Fragments
Demo Repo:
https://github.com/Gaket/MvuMovieDb
4
The goal of this talk
» Not about theory
» But about a real example
5
6
Elm is a functional language for web
apps
7
Elm Architecture is one of the UDF band
8
Really Quick Recap 1
» Unidirectional data flow
» Pure functions
» Immutability
» Higher order functions
» State machine
» MVI
» TEA (MVU)
» Redux
» The Composable
Architecture
1 
https://www.youtube.com/watch?v=FPbUAgyMPAc
9
10
11
12
Unidirectional Flow (UDF)
13
view = f(state)
14
updated state = f(state, message)
15
What do we want?
» Explicit state
» Making state handling visible
» Clear responsibilities
» Increased testability
» No mocks, No flakiness
» Easy to reason about
16
Explicit state requirements
» Same way as no platform dependencies
» No side effects in Update
» Otherwise, we can't guarantee repeatability
17
One way to implement
Model
18
One way to implement
Model Feature
19
One way to implement Feature
» State
» Messages
» Update
» Commands
» Dependencies
20
Unidirectional Flow (UDF)
21
Real Unidirectional Flow (UDF)
22
State
» Contains everything needed to render the View
» Never updated manually
data class State(
val loading: Boolean,
val movies: List<Movie>,
val message: Text,
val lastRequestTime: LocalTime
)
23
Messages
Whatever can lead to state change
sealed class Message {
// user
data class SearchUpdated(val query: String, val time: LocalTime) : Message()
data class MovieClicked(val movie: Movie) : Message()
// system
data class MoviesResponse(val response: Try<List<Movie>>) : Message()
24
Update
Pure boy
"Old state in, new state out"
fun update(message: Message, state: State)
: Pair<State, Set<Command>> =
when (message) {
is Message.MovieClicked -> handleMovieClick(message.movie, state)
is Message.SearchUpdated -> handleSearchUpdate(message.query, state)
is Message.MoviesResponse -> handleMoviesResponse(message.response, state)
}
25
Commands
We live in a real world
* DB
* Network
* Random
class GetMovies(query: String) : Message ({ deps ->
val movies = deps.repository.searchMovies(query)
return@single Message.MoviesResponse(movies)
})
26
View
class MoviesFragment {
override fun initDispatchers() {
binding.searchInput.afterTextChanged { query ->
dispatch(MoviesFeature.Message.SearchUpdated(query, LocalTime.now()))
}
}
override fun render(state: MoviesFeature.State) {
if (state.loading) {
binding.searchIcon.visibility = View.GONE
binding.searchProgress.visibility = View.VISIBLE
} else {
binding.searchIcon.visibility = View.VISIBLE
binding.searchProgress.visibility = View.GONE
}
}
}
27
How to debug
1. Check what state gets to View
2. Check the update function calls
3. Roll back a few messages if needed
28
Logs
18:00:00 Init: State {...}
18:00:03 Message: OnMovieClick(Movie(...))
18:00:03 Render: State {...}
18:00:04 Message: OnMoviesResult(Movies(...))
18:00:04 Render: State {...}
29
Live demo
Real app approach, 160 Fragments
Demo Repo:
https://github.com/Gaket/MvuMovieDb
30
Other cases
» One-time events
» Navigation
» Seperate classes for UI models
31
Imperfect world
» View is expected to be stateless
» Still we have scroll position, animations
32
Conclusion
Not a silver bullet, but worth trying!
» Clear responsibilities
» Increased testability
» No flakiness
» Easy to reason about
» A bit more code
33
Acknowledgements
» Tim Plotnikov, https://twitter.com/timofeipl
» Sergey Opivalov
» Evgeniy Ekgardt
34
Questions?
Artur Badretdinov @ Squire
Repo:
https://github.com/Gaket/MvuMovieDb
https://twitter.com/ArtursTwit
https://t.me/gaket
35

More Related Content

PDF
Concurrency: Rubies, plural
PDF
Concurrency: Rubies, Plural
PDF
Exploring Clojurescript
PPTX
Introduction to ParSeq: to make asynchronous java easier
PDF
夜子まま塾講義2(javaのクラスとメソッド)
PPTX
Node.js and angular js
PDF
Make A Shoot ‘Em Up Game with Amethyst Framework
PDF
Hierarchical free monads and software design in fp
Concurrency: Rubies, plural
Concurrency: Rubies, Plural
Exploring Clojurescript
Introduction to ParSeq: to make asynchronous java easier
夜子まま塾講義2(javaのクラスとメソッド)
Node.js and angular js
Make A Shoot ‘Em Up Game with Amethyst Framework
Hierarchical free monads and software design in fp

Similar to The Elm Architecture in prod (20)

PDF
Akka with Scala
PDF
MBLTDev15: Cesar Valiente, Wunderlist
PPT
PPSX
JDBC Part - 2
PPTX
Session 24 - JDBC, Intro to Enterprise Java
PPTX
Reactive programming every day
PPTX
Serverless Stateful Architecture
PDF
Dataflows: The abstraction that powers Big Data by Raul Castro Fernandez at ...
PPTX
Flying Futures at the same sky can make the sun rise at midnight
PDF
The art of messaging tune (Joker 2015 edition)
PPTX
State of entity framework
PPTX
Android Unit Test
PDF
GDG Jakarta Meetup - Streaming Analytics With Apache Beam
PPTX
Legacy projects: how to win the race
PDF
Building Modern Apps using Android Architecture Components
PDF
Riga DevDays 2017 - The hitchhiker’s guide to Java class reloading
PDF
Kotlin+MicroProfile: Ensinando 20 anos para uma linguagem nova
PDF
Cotap Tech Talks: Roderic Campbell, Minority Report UX with an Apple Watch
PDF
How to optimize background processes - when Sylius meets Blackfire
Akka with Scala
MBLTDev15: Cesar Valiente, Wunderlist
JDBC Part - 2
Session 24 - JDBC, Intro to Enterprise Java
Reactive programming every day
Serverless Stateful Architecture
Dataflows: The abstraction that powers Big Data by Raul Castro Fernandez at ...
Flying Futures at the same sky can make the sun rise at midnight
The art of messaging tune (Joker 2015 edition)
State of entity framework
Android Unit Test
GDG Jakarta Meetup - Streaming Analytics With Apache Beam
Legacy projects: how to win the race
Building Modern Apps using Android Architecture Components
Riga DevDays 2017 - The hitchhiker’s guide to Java class reloading
Kotlin+MicroProfile: Ensinando 20 anos para uma linguagem nova
Cotap Tech Talks: Roderic Campbell, Minority Report UX with an Apple Watch
How to optimize background processes - when Sylius meets Blackfire
Ad

Recently uploaded (20)

PDF
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
PDF
Encapsulation theory and applications.pdf
PPTX
Programs and apps: productivity, graphics, security and other tools
PDF
Per capita expenditure prediction using model stacking based on satellite ima...
PDF
gpt5_lecture_notes_comprehensive_20250812015547.pdf
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PDF
Network Security Unit 5.pdf for BCA BBA.
PDF
Agricultural_Statistics_at_a_Glance_2022_0.pdf
PPTX
Tartificialntelligence_presentation.pptx
PPTX
TechTalks-8-2019-Service-Management-ITIL-Refresh-ITIL-4-Framework-Supports-Ou...
PDF
Diabetes mellitus diagnosis method based random forest with bat algorithm
PPTX
OMC Textile Division Presentation 2021.pptx
PPTX
Machine Learning_overview_presentation.pptx
PPTX
Spectroscopy.pptx food analysis technology
PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
PPTX
cloud_computing_Infrastucture_as_cloud_p
PDF
August Patch Tuesday
PDF
A comparative study of natural language inference in Swahili using monolingua...
PDF
Empathic Computing: Creating Shared Understanding
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
Encapsulation theory and applications.pdf
Programs and apps: productivity, graphics, security and other tools
Per capita expenditure prediction using model stacking based on satellite ima...
gpt5_lecture_notes_comprehensive_20250812015547.pdf
Mobile App Security Testing_ A Comprehensive Guide.pdf
Network Security Unit 5.pdf for BCA BBA.
Agricultural_Statistics_at_a_Glance_2022_0.pdf
Tartificialntelligence_presentation.pptx
TechTalks-8-2019-Service-Management-ITIL-Refresh-ITIL-4-Framework-Supports-Ou...
Diabetes mellitus diagnosis method based random forest with bat algorithm
OMC Textile Division Presentation 2021.pptx
Machine Learning_overview_presentation.pptx
Spectroscopy.pptx food analysis technology
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
cloud_computing_Infrastucture_as_cloud_p
August Patch Tuesday
A comparative study of natural language inference in Swahili using monolingua...
Empathic Computing: Creating Shared Understanding
Digital-Transformation-Roadmap-for-Companies.pptx
Ad

The Elm Architecture in prod

  • 1. TEA in Prod Artur Badretdinov, Squire 1
  • 2. Artur Badretdinov Digital Nomad, Lead Android Developer at Squire https://t.me/travelernote https://t.me/ohmyeventbot 2
  • 4. Live demo ahead Real app approach, 160 Fragments Demo Repo: https://github.com/Gaket/MvuMovieDb 4
  • 5. The goal of this talk » Not about theory » But about a real example 5
  • 6. 6
  • 7. Elm is a functional language for web apps 7
  • 8. Elm Architecture is one of the UDF band 8
  • 9. Really Quick Recap 1 » Unidirectional data flow » Pure functions » Immutability » Higher order functions » State machine » MVI » TEA (MVU) » Redux » The Composable Architecture 1  https://www.youtube.com/watch?v=FPbUAgyMPAc 9
  • 10. 10
  • 11. 11
  • 12. 12
  • 15. updated state = f(state, message) 15
  • 16. What do we want? » Explicit state » Making state handling visible » Clear responsibilities » Increased testability » No mocks, No flakiness » Easy to reason about 16
  • 17. Explicit state requirements » Same way as no platform dependencies » No side effects in Update » Otherwise, we can't guarantee repeatability 17
  • 18. One way to implement Model 18
  • 19. One way to implement Model Feature 19
  • 20. One way to implement Feature » State » Messages » Update » Commands » Dependencies 20
  • 23. State » Contains everything needed to render the View » Never updated manually data class State( val loading: Boolean, val movies: List<Movie>, val message: Text, val lastRequestTime: LocalTime ) 23
  • 24. Messages Whatever can lead to state change sealed class Message { // user data class SearchUpdated(val query: String, val time: LocalTime) : Message() data class MovieClicked(val movie: Movie) : Message() // system data class MoviesResponse(val response: Try<List<Movie>>) : Message() 24
  • 25. Update Pure boy "Old state in, new state out" fun update(message: Message, state: State) : Pair<State, Set<Command>> = when (message) { is Message.MovieClicked -> handleMovieClick(message.movie, state) is Message.SearchUpdated -> handleSearchUpdate(message.query, state) is Message.MoviesResponse -> handleMoviesResponse(message.response, state) } 25
  • 26. Commands We live in a real world * DB * Network * Random class GetMovies(query: String) : Message ({ deps -> val movies = deps.repository.searchMovies(query) return@single Message.MoviesResponse(movies) }) 26
  • 27. View class MoviesFragment { override fun initDispatchers() { binding.searchInput.afterTextChanged { query -> dispatch(MoviesFeature.Message.SearchUpdated(query, LocalTime.now())) } } override fun render(state: MoviesFeature.State) { if (state.loading) { binding.searchIcon.visibility = View.GONE binding.searchProgress.visibility = View.VISIBLE } else { binding.searchIcon.visibility = View.VISIBLE binding.searchProgress.visibility = View.GONE } } } 27
  • 28. How to debug 1. Check what state gets to View 2. Check the update function calls 3. Roll back a few messages if needed 28
  • 29. Logs 18:00:00 Init: State {...} 18:00:03 Message: OnMovieClick(Movie(...)) 18:00:03 Render: State {...} 18:00:04 Message: OnMoviesResult(Movies(...)) 18:00:04 Render: State {...} 29
  • 30. Live demo Real app approach, 160 Fragments Demo Repo: https://github.com/Gaket/MvuMovieDb 30
  • 31. Other cases » One-time events » Navigation » Seperate classes for UI models 31
  • 32. Imperfect world » View is expected to be stateless » Still we have scroll position, animations 32
  • 33. Conclusion Not a silver bullet, but worth trying! » Clear responsibilities » Increased testability » No flakiness » Easy to reason about » A bit more code 33
  • 35. Questions? Artur Badretdinov @ Squire Repo: https://github.com/Gaket/MvuMovieDb https://twitter.com/ArtursTwit https://t.me/gaket 35